diff options
author | Dalai Felinto <dalai@blender.org> | 2020-12-10 13:05:49 +0300 |
---|---|---|
committer | Dalai Felinto <dalai@blender.org> | 2020-12-10 13:05:49 +0300 |
commit | c5a17d5ea1ff786cb91cbcf3f12cd02f730c4143 (patch) | |
tree | f03a5935ee7dbc4c7ddabaee1c06570a26f698f9 | |
parent | 390c4efa0c15b39e2d1971bc81464cffae56d102 (diff) | |
parent | e795ba1529a28ec276a5178fda2025e5ec071bbf (diff) |
Merge remote-tracking branch 'origin/master' into geometry-nodes
804 files changed, 10919 insertions, 14549 deletions
diff --git a/.clang-tidy b/.clang-tidy index 49b238d8708..d65027687bb 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -34,17 +34,14 @@ Checks: > modernize-*, -modernize-use-auto, -modernize-use-trailing-return-type, - -modernize-deprecated-headers, -modernize-avoid-c-arrays, -modernize-use-equals-default, -modernize-use-nodiscard, - -modernize-use-using, -modernize-loop-convert, -modernize-pass-by-value, -modernize-use-default-member-init, -modernize-raw-string-literal, -modernize-avoid-bind, - -modernize-use-override, -modernize-use-transparent-functors, WarningsAsErrors: '*' diff --git a/CMakeLists.txt b/CMakeLists.txt index 81fe4739da4..0d7cf4e325c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,8 +427,8 @@ mark_as_advanced(WITH_CXX_GUARDEDALLOC) option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" ON) mark_as_advanced(WITH_ASSERT_ABORT) -if(UNIX AND NOT APPLE) - option(WITH_CLANG_TIDY "Use Clang Tidy to analyze the source code (only enable for development on Linux using Clang)" OFF) +if((UNIX AND NOT APPLE) OR (CMAKE_GENERATOR MATCHES "^Visual Studio.+")) + option(WITH_CLANG_TIDY "Use Clang Tidy to analyze the source code (only enable for development on Linux using Clang, or Windows using the Visual Studio IDE)" OFF) mark_as_advanced(WITH_CLANG_TIDY) endif() diff --git a/build_files/build_environment/cmake/clang.cmake b/build_files/build_environment/cmake/clang.cmake index 9de0ec1b182..d8d83619e1a 100644 --- a/build_files/build_environment/cmake/clang.cmake +++ b/build_files/build_environment/cmake/clang.cmake @@ -17,13 +17,14 @@ # ***** END GPL LICENSE BLOCK ***** set(CLANG_EXTRA_ARGS - -DCLANG_PATH_TO_LLVM_SOURCE=${BUILD_DIR}/ll/src/ll - -DCLANG_PATH_TO_LLVM_BUILD=${LIBDIR}/llvm + -DLLVM_DIR="${LIBDIR}/llvm/lib/cmake/llvm/" -DLLVM_USE_CRT_RELEASE=MD -DLLVM_USE_CRT_DEBUG=MDd -DLLVM_CONFIG=${LIBDIR}/llvm/bin/llvm-config ) +set(BUILD_CLANG_TOOLS OFF) + if(WIN32) set(CLANG_GENERATOR "Ninja") else() @@ -31,11 +32,32 @@ else() endif() if(APPLE) + set(BUILD_CLANG_TOOLS ON) set(CLANG_EXTRA_ARGS ${CLANG_EXTRA_ARGS} -DLIBXML2_LIBRARY=${LIBDIR}/xml2/lib/libxml2.a ) endif() +if(BUILD_CLANG_TOOLS) + # ExternalProject_Add does not allow multiple tarballs to be + # downloaded. Work around this by having an empty build action + # for the extra tools, and referring the clang build to the location + # of the clang-tools-extra source. + ExternalProject_Add(external_clang_tools + URL ${CLANG_TOOLS_URI} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH MD5=${CLANG_TOOLS_HASH} + INSTALL_DIR ${LIBDIR}/clang_tools + PREFIX ${BUILD_DIR}/clang_tools + CONFIGURE_COMMAND echo "." + BUILD_COMMAND echo "." + INSTALL_COMMAND echo "." + ) + list(APPEND CLANG_EXTRA_ARGS + -DLLVM_EXTERNAL_CLANG_TOOLS_EXTRA_SOURCE_DIR=${BUILD_DIR}/clang_tools/src/external_clang_tools/ + ) +endif() + ExternalProject_Add(external_clang URL ${CLANG_URI} DOWNLOAD_DIR ${DOWNLOAD_DIR} @@ -65,6 +87,14 @@ add_dependencies( ll ) +if(BUILD_CLANG_TOOLS) + # `external_clang_tools` is for downloading the source, not compiling it. + add_dependencies( + external_clang + external_clang_tools + ) +endif() + # We currently do not build libxml2 on Windows. if(NOT WIN32) add_dependencies( diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake index 0f9b67a3d44..536907f563d 100644 --- a/build_files/build_environment/cmake/harvest.cmake +++ b/build_files/build_environment/cmake/harvest.cmake @@ -98,6 +98,10 @@ harvest(jpg/include jpeg/include "*.h") harvest(jpg/lib jpeg/lib "libjpeg.a") harvest(lame/lib ffmpeg/lib "*.a") harvest(clang/bin llvm/bin "clang-format") +if(BUILD_CLANG_TOOLS) + harvest(clang/bin llvm/bin "clang-tidy") + harvest(clang/share/clang llvm/share "run-clang-tidy.py") +endif() harvest(clang/include llvm/include "*") harvest(llvm/include llvm/include "*") harvest(llvm/bin llvm/bin "llvm-config") diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 653db9f740c..d4a2c715ecc 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -120,6 +120,9 @@ set(LLVM_HASH 31eb9ce73dd2a0f8dcab8319fb03f8fc) set(CLANG_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/clang-${LLVM_VERSION}.src.tar.xz) set(CLANG_HASH 13468e4a44940efef1b75e8641752f90) +set(CLANG_TOOLS_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/clang-tools-extra-${LLVM_VERSION}.src.tar.xz) +set(CLANG_TOOLS_HASH c76293870b564c6a7968622b475b7646) + set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/openmp-${LLVM_VERSION}.src.tar.xz) set(OPENMP_HASH 6eade16057edbdecb3c4eef9daa2bfcf) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 3954a5f143c..dd8b286c689 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -239,9 +239,24 @@ if(NOT EXISTS "${LIBDIR}/") message(FATAL_ERROR "\n\nWindows requires pre-compiled libs at: '${LIBDIR}'. Please run `make update` in the blender source folder to obtain them.") endif() +if(CMAKE_GENERATOR MATCHES "^Visual Studio.+" AND # Only supported in the VS IDE + MSVC_VERSION GREATER_EQUAL 1924 AND # Supported for 16.4+ + WITH_CLANG_TIDY # And Clang Tidy needs to be on + ) + set(CMAKE_VS_GLOBALS + "RunCodeAnalysis=false" + "EnableMicrosoftCodeAnalysis=false" + "EnableClangTidyCodeAnalysis=true" + ) + set(VS_CLANG_TIDY On) +endif() + # Mark libdir as system headers with a lower warn level, to resolve some warnings # that we have very little control over -if(MSVC_VERSION GREATER_EQUAL 1914 AND NOT MSVC_CLANG AND NOT WITH_WINDOWS_SCCACHE) +if(MSVC_VERSION GREATER_EQUAL 1914 AND # Available with 15.7+ + NOT MSVC_CLANG AND # But not for clang + NOT WITH_WINDOWS_SCCACHE AND # And not when sccache is enabled + NOT VS_CLANG_TIDY) # Clang-tidy does not like these options add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0) endif() diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index ca545eec4ca..772fac56f63 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -453,7 +453,7 @@ TYPEDEF_HIDES_STRUCT = NO # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. -LOOKUP_CACHE_SIZE = 0 +LOOKUP_CACHE_SIZE = 3 #--------------------------------------------------------------------------- # Build related configuration options @@ -1321,7 +1321,7 @@ DOCSET_PUBLISHER_NAME = Publisher # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_HTMLHELP = YES +GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be diff --git a/doc/python_api/examples/bpy.types.bpy_struct.is_property_set.py b/doc/python_api/examples/bpy.types.bpy_struct.is_property_set.py new file mode 100644 index 00000000000..ed566fc3ea8 --- /dev/null +++ b/doc/python_api/examples/bpy.types.bpy_struct.is_property_set.py @@ -0,0 +1,30 @@ +""" +.. note:: + + Properties defined at run-time store the values of the properties as custom-properties. + + This method checks if the underlying data exists, causing the property to be considered *set*. + + A common pattern for operators is to calculate a value for the properties + that have not had their values explicitly set by the caller + (where the caller could be a key-binding, menu-items or Python script for example). + + In the case of executing operators multiple times, values are re-used from the previous execution. + + For example: subdividing a mesh with a smooth value of 1.0 will keep using + that value on subsequent calls to subdivision, unless the operator is called with + that property set to a different value. + + This behavior can be disabled using the ``SKIP_SAVE`` option when the property is declared (see: :mod:`bpy.props`). + + The ``ghost`` argument allows detecting how a value from a previous execution is handled. + + - When true: The property is considered unset even if the value from a previous call is used. + - When false: The existence of any values causes ``is_property_set`` to return true. + + While this argument should typically be omitted, there are times when + it's important to know if a value is anything besides the default. + + For example, the previous value may have been scaled by the scene's unit scale. + In this case scaling the value multiple times would cause problems, so the ``ghost`` argument should be false. +""" diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index b148f4c6a46..930e5b88911 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -551,7 +551,7 @@ def example_extract_docstring(filepath): file.close() return "", 0 - for line in file.readlines(): + for line in file: line_no += 1 if line.startswith('"""'): break @@ -559,6 +559,13 @@ def example_extract_docstring(filepath): text.append(line.rstrip()) line_no += 1 + + # Skip over blank lines so the Python code doesn't have blank lines at the top. + for line in file: + if line.strip(): + break + line_no += 1 + file.close() return "\n".join(text), line_no diff --git a/extern/audaspace/README.blender b/extern/audaspace/README.blender new file mode 100644 index 00000000000..97c0dd8c768 --- /dev/null +++ b/extern/audaspace/README.blender @@ -0,0 +1,5 @@ +Project: Audaspace +URL: https://audaspace.github.io/ +License: Apache 2.0 +Upstream version: 1.3 (Last Release) +Local modifications: None diff --git a/extern/bullet2/README.blender b/extern/bullet2/README.blender new file mode 100644 index 00000000000..48b71fe06df --- /dev/null +++ b/extern/bullet2/README.blender @@ -0,0 +1,5 @@ +Project: Bullet Continuous Collision Detection and Physics Library +URL: http://bulletphysics.org +License: zlib +Upstream version: 3.07 +Local modifications: Fixed inertia diff --git a/extern/ceres/README.blender b/extern/ceres/README.blender index 0b6063c9703..20e5dda6f57 100644 --- a/extern/ceres/README.blender +++ b/extern/ceres/README.blender @@ -1,4 +1,5 @@ Project: Ceres Solver URL: http://ceres-solver.org/ +License: BSD 3-Clause Upstream version 2.0.0 Local modifications: None diff --git a/extern/curve_fit_nd/README.blender b/extern/curve_fit_nd/README.blender index db520ea524e..8e70fd796bb 100644 --- a/extern/curve_fit_nd/README.blender +++ b/extern/curve_fit_nd/README.blender @@ -1,5 +1,5 @@ Project: Curve-Fit-nD URL: https://github.com/ideasman42/curve-fit-nd License: BSD 3-Clause -Upstream version: Unknown (Last Release) +Upstream version: ddcd5bd (Last Release) Local modifications: None diff --git a/extern/draco/CMakeLists.txt b/extern/draco/CMakeLists.txt index 6961fa8a769..d4cfeea4bee 100644 --- a/extern/draco/CMakeLists.txt +++ b/extern/draco/CMakeLists.txt @@ -19,20 +19,24 @@ # ***** END GPL LICENSE BLOCK ***** # Build Draco library. -add_subdirectory(dracoenc) +add_subdirectory(draco) -# Build blender-draco-exporter module. +# Build Draco-Blender bridging module. set(SRC - src/draco-compressor.cpp - src/draco-compressor.h + src/common.cpp + src/common.h + src/decoder.cpp + src/decoder.h + src/encoder.cpp + src/encoder.h ) set(INC - dracoenc/src + draco/src ) set(LIB - dracoenc + draco ) add_library(extern_draco SHARED "${SRC}") diff --git a/extern/draco/README.blender b/extern/draco/README.blender new file mode 100644 index 00000000000..b9c3bbb967d --- /dev/null +++ b/extern/draco/README.blender @@ -0,0 +1,5 @@ +Project: Draco +URL: https://google.github.io/draco/ +License: Apache 2.0 +Upstream version: 1.3.6 +Local modifications: None diff --git a/extern/draco/dracoenc/AUTHORS b/extern/draco/draco/AUTHORS index 67f63a67129..67f63a67129 100644 --- a/extern/draco/dracoenc/AUTHORS +++ b/extern/draco/draco/AUTHORS diff --git a/extern/draco/dracoenc/CMakeLists.txt b/extern/draco/draco/CMakeLists.txt index 3d33bdb74c2..6f9ffce6b48 100644 --- a/extern/draco/dracoenc/CMakeLists.txt +++ b/extern/draco/draco/CMakeLists.txt @@ -2,103 +2,165 @@ remove_strict_flags() set(SRC src/draco/animation/keyframe_animation.cc + src/draco/animation/keyframe_animation.h + src/draco/animation/keyframe_animation_decoder.cc + src/draco/animation/keyframe_animation_decoder.h src/draco/animation/keyframe_animation_encoder.cc src/draco/animation/keyframe_animation_encoder.h - src/draco/animation/keyframe_animation.h src/draco/attributes/attribute_octahedron_transform.cc src/draco/attributes/attribute_octahedron_transform.h src/draco/attributes/attribute_quantization_transform.cc src/draco/attributes/attribute_quantization_transform.h src/draco/attributes/attribute_transform.cc - src/draco/attributes/attribute_transform_data.h src/draco/attributes/attribute_transform.h + src/draco/attributes/attribute_transform_data.h src/draco/attributes/attribute_transform_type.h src/draco/attributes/geometry_attribute.cc src/draco/attributes/geometry_attribute.h src/draco/attributes/geometry_indices.h src/draco/attributes/point_attribute.cc src/draco/attributes/point_attribute.h + src/draco/compression/attributes/attributes_decoder.cc + src/draco/compression/attributes/attributes_decoder.h + src/draco/compression/attributes/attributes_decoder_interface.h src/draco/compression/attributes/attributes_encoder.cc src/draco/compression/attributes/attributes_encoder.h + src/draco/compression/attributes/kd_tree_attributes_decoder.cc + src/draco/compression/attributes/kd_tree_attributes_decoder.h src/draco/compression/attributes/kd_tree_attributes_encoder.cc src/draco/compression/attributes/kd_tree_attributes_encoder.h + src/draco/compression/attributes/kd_tree_attributes_shared.h src/draco/compression/attributes/linear_sequencer.h + src/draco/compression/attributes/mesh_attribute_indices_encoding_data.h + src/draco/compression/attributes/normal_compression_utils.h + src/draco/compression/attributes/point_d_vector.h src/draco/compression/attributes/points_sequencer.h + src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_encoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_shared.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h + src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_encoder.h + src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_encoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_base.h + src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_encoder.h + src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_encoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h + src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_decoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_encoder.h + src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_decoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_encoder.h src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_interface.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoding_transform.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_decoder.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_encoder.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h - src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoding_transform.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_factory.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_encoding_transform.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_base.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_encoding_transform.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_base.h + src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_encoding_transform.h src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h + src/draco/compression/attributes/sequential_attribute_decoder.cc + src/draco/compression/attributes/sequential_attribute_decoder.h + src/draco/compression/attributes/sequential_attribute_decoders_controller.cc + src/draco/compression/attributes/sequential_attribute_decoders_controller.h src/draco/compression/attributes/sequential_attribute_encoder.cc src/draco/compression/attributes/sequential_attribute_encoder.h src/draco/compression/attributes/sequential_attribute_encoders_controller.cc src/draco/compression/attributes/sequential_attribute_encoders_controller.h + src/draco/compression/attributes/sequential_integer_attribute_decoder.cc + src/draco/compression/attributes/sequential_integer_attribute_decoder.h src/draco/compression/attributes/sequential_integer_attribute_encoder.cc src/draco/compression/attributes/sequential_integer_attribute_encoder.h + src/draco/compression/attributes/sequential_normal_attribute_decoder.cc + src/draco/compression/attributes/sequential_normal_attribute_decoder.h src/draco/compression/attributes/sequential_normal_attribute_encoder.cc src/draco/compression/attributes/sequential_normal_attribute_encoder.h + src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc + src/draco/compression/attributes/sequential_quantization_attribute_decoder.h src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc src/draco/compression/attributes/sequential_quantization_attribute_encoder.h src/draco/compression/bit_coders/adaptive_rans_bit_coding_shared.h + src/draco/compression/bit_coders/adaptive_rans_bit_decoder.cc + src/draco/compression/bit_coders/adaptive_rans_bit_decoder.h src/draco/compression/bit_coders/adaptive_rans_bit_encoder.cc src/draco/compression/bit_coders/adaptive_rans_bit_encoder.h + src/draco/compression/bit_coders/direct_bit_decoder.cc + src/draco/compression/bit_coders/direct_bit_decoder.h src/draco/compression/bit_coders/direct_bit_encoder.cc src/draco/compression/bit_coders/direct_bit_encoder.h + src/draco/compression/bit_coders/folded_integer_bit_decoder.h src/draco/compression/bit_coders/folded_integer_bit_encoder.h + src/draco/compression/bit_coders/rans_bit_decoder.cc + src/draco/compression/bit_coders/rans_bit_decoder.h src/draco/compression/bit_coders/rans_bit_encoder.cc src/draco/compression/bit_coders/rans_bit_encoder.h + src/draco/compression/bit_coders/symbol_bit_decoder.cc + src/draco/compression/bit_coders/symbol_bit_decoder.h src/draco/compression/bit_coders/symbol_bit_encoder.cc src/draco/compression/bit_coders/symbol_bit_encoder.h src/draco/compression/config/compression_shared.h + src/draco/compression/config/decoder_options.h src/draco/compression/config/draco_options.h src/draco/compression/config/encoder_options.h src/draco/compression/config/encoding_features.h - src/draco/compression/encode_base.h + src/draco/compression/decode.cc + src/draco/compression/decode.h src/draco/compression/encode.cc src/draco/compression/encode.h + src/draco/compression/encode_base.h src/draco/compression/entropy/ans.h src/draco/compression/entropy/rans_symbol_coding.h + src/draco/compression/entropy/rans_symbol_decoder.h src/draco/compression/entropy/rans_symbol_encoder.h src/draco/compression/entropy/shannon_entropy.cc src/draco/compression/entropy/shannon_entropy.h + src/draco/compression/entropy/symbol_decoding.cc + src/draco/compression/entropy/symbol_decoding.h src/draco/compression/entropy/symbol_encoding.cc src/draco/compression/entropy/symbol_encoding.h src/draco/compression/expert_encode.cc src/draco/compression/expert_encode.h + src/draco/compression/mesh/mesh_decoder.cc + src/draco/compression/mesh/mesh_decoder.h + src/draco/compression/mesh/mesh_edgebreaker_decoder.cc + src/draco/compression/mesh/mesh_edgebreaker_decoder.h + src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc + src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.h + src/draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h src/draco/compression/mesh/mesh_edgebreaker_encoder.cc src/draco/compression/mesh/mesh_edgebreaker_encoder.h src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h src/draco/compression/mesh/mesh_edgebreaker_shared.h + src/draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h src/draco/compression/mesh/mesh_edgebreaker_traversal_encoder.h + src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_encoder.h + src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_encoder.h src/draco/compression/mesh/mesh_encoder.cc src/draco/compression/mesh/mesh_encoder.h - src/draco/compression/mesh/mesh_encoder_helpers.h + src/draco/compression/mesh/mesh_sequential_decoder.cc + src/draco/compression/mesh/mesh_sequential_decoder.h src/draco/compression/mesh/mesh_sequential_encoder.cc src/draco/compression/mesh/mesh_sequential_encoder.h src/draco/compression/mesh/traverser/depth_first_traverser.h @@ -106,18 +168,32 @@ set(SRC src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h src/draco/compression/mesh/traverser/traverser_base.h + src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.cc + src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.cc src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h + src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc + src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.cc src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h + src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.cc + src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h + src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.cc + src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h src/draco/compression/point_cloud/algorithms/point_cloud_types.h src/draco/compression/point_cloud/algorithms/quantize_points_3.h src/draco/compression/point_cloud/algorithms/queuing_policy.h + src/draco/compression/point_cloud/point_cloud_decoder.cc + src/draco/compression/point_cloud/point_cloud_decoder.h src/draco/compression/point_cloud/point_cloud_encoder.cc src/draco/compression/point_cloud/point_cloud_encoder.h + src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.cc + src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.h src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h + src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc + src/draco/compression/point_cloud/point_cloud_sequential_decoder.h src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc src/draco/compression/point_cloud/point_cloud_sequential_encoder.h src/draco/core/bit_utils.cc @@ -128,12 +204,15 @@ set(SRC src/draco/core/cycle_timer.h src/draco/core/data_buffer.cc src/draco/core/data_buffer.h + src/draco/core/decoder_buffer.cc + src/draco/core/decoder_buffer.h src/draco/core/divide.cc src/draco/core/divide.h src/draco/core/draco_index_type.h src/draco/core/draco_index_type_vector.h src/draco/core/draco_types.cc src/draco/core/draco_types.h + src/draco/core/draco_version.h src/draco/core/encoder_buffer.cc src/draco/core/encoder_buffer.h src/draco/core/hash_utils.cc @@ -145,20 +224,21 @@ set(SRC src/draco/core/quantization_utils.cc src/draco/core/quantization_utils.h src/draco/core/status.h - src/draco/core/statusor.h + src/draco/core/status_or.h + src/draco/core/varint_decoding.h src/draco/core/varint_encoding.h src/draco/core/vector_d.h src/draco/mesh/corner_table.cc src/draco/mesh/corner_table.h src/draco/mesh/corner_table_iterators.h + src/draco/mesh/mesh.cc + src/draco/mesh/mesh.h src/draco/mesh/mesh_are_equivalent.cc src/draco/mesh/mesh_are_equivalent.h src/draco/mesh/mesh_attribute_corner_table.cc src/draco/mesh/mesh_attribute_corner_table.h - src/draco/mesh/mesh.cc src/draco/mesh/mesh_cleanup.cc src/draco/mesh/mesh_cleanup.h - src/draco/mesh/mesh.h src/draco/mesh/mesh_misc_functions.cc src/draco/mesh/mesh_misc_functions.h src/draco/mesh/mesh_stripifier.cc @@ -169,13 +249,15 @@ set(SRC src/draco/metadata/geometry_metadata.cc src/draco/metadata/geometry_metadata.h src/draco/metadata/metadata.cc + src/draco/metadata/metadata.h + src/draco/metadata/metadata_decoder.cc + src/draco/metadata/metadata_decoder.h src/draco/metadata/metadata_encoder.cc src/draco/metadata/metadata_encoder.h - src/draco/metadata/metadata.h - src/draco/point_cloud/point_cloud_builder.cc - src/draco/point_cloud/point_cloud_builder.h src/draco/point_cloud/point_cloud.cc src/draco/point_cloud/point_cloud.h + src/draco/point_cloud/point_cloud_builder.cc + src/draco/point_cloud/point_cloud_builder.h ) set(LIB @@ -185,4 +267,5 @@ set(INC src ) -blender_add_lib(dracoenc "${SRC}" "${INC}" "" "${LIB}") +blender_add_lib(draco "${SRC}" "${INC}" "" "${LIB}") + diff --git a/extern/draco/dracoenc/LICENSE b/extern/draco/draco/LICENSE index 7a4a3ea2424..7a4a3ea2424 100644 --- a/extern/draco/dracoenc/LICENSE +++ b/extern/draco/draco/LICENSE diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation.cc b/extern/draco/draco/src/draco/animation/keyframe_animation.cc index 05ae3b1184e..eaf94a3305d 100644 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation.cc +++ b/extern/draco/draco/src/draco/animation/keyframe_animation.cc @@ -29,8 +29,9 @@ bool KeyframeAnimation::SetTimestamps( } else { // Check if the number of frames is consistent with // the existing keyframes. - if (num_frames != num_points()) + if (num_frames != num_points()) { return false; + } } } else { // This is the first attribute. @@ -40,10 +41,8 @@ bool KeyframeAnimation::SetTimestamps( // Add attribute for time stamp data. std::unique_ptr<PointAttribute> timestamp_att = std::unique_ptr<PointAttribute>(new PointAttribute()); - timestamp_att->Init(GeometryAttribute::GENERIC, nullptr, 1, DT_FLOAT32, false, - sizeof(float), 0); - timestamp_att->SetIdentityMapping(); - timestamp_att->Reset(num_frames); + timestamp_att->Init(GeometryAttribute::GENERIC, 1, DT_FLOAT32, false, + num_frames); for (PointIndex i(0); i < num_frames; ++i) { timestamp_att->SetAttributeValue(timestamp_att->mapped_index(i), ×tamp[i.value()]); diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation.h b/extern/draco/draco/src/draco/animation/keyframe_animation.h index 0e8b111aaea..a7afb2b81be 100644 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation.h +++ b/extern/draco/draco/src/draco/animation/keyframe_animation.h @@ -71,30 +71,29 @@ int32_t KeyframeAnimation::AddKeyframes(DataType data_type, uint32_t num_components, const std::vector<T> &data) { // TODO(draco-eng): Verify T is consistent with |data_type|. - if (num_components == 0) + if (num_components == 0) { return -1; + } // If timestamps is not added yet, then reserve attribute 0 for timestamps. if (!num_attributes()) { // Add a temporary attribute with 0 points to fill attribute id 0. std::unique_ptr<PointAttribute> temp_att = std::unique_ptr<PointAttribute>(new PointAttribute()); - temp_att->Init(GeometryAttribute::GENERIC, nullptr, num_components, - data_type, false, DataTypeLength(data_type), 0); - temp_att->Reset(0); + temp_att->Init(GeometryAttribute::GENERIC, num_components, data_type, false, + 0); this->AddAttribute(std::move(temp_att)); set_num_frames(data.size() / num_components); } - if (data.size() != num_components * num_frames()) + if (data.size() != num_components * num_frames()) { return -1; + } std::unique_ptr<PointAttribute> keyframe_att = std::unique_ptr<PointAttribute>(new PointAttribute()); - keyframe_att->Init(GeometryAttribute::GENERIC, nullptr, num_components, - data_type, false, DataTypeLength(data_type), 0); - keyframe_att->SetIdentityMapping(); - keyframe_att->Reset(num_frames()); + keyframe_att->Init(GeometryAttribute::GENERIC, num_components, data_type, + false, num_frames()); const size_t stride = num_components; for (PointIndex i(0); i < num_frames(); ++i) { keyframe_att->SetAttributeValue(keyframe_att->mapped_index(i), diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_decoder.cc b/extern/draco/draco/src/draco/animation/keyframe_animation_decoder.cc index 8c0e71f62fa..20659468d94 100644 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_decoder.cc +++ b/extern/draco/draco/src/draco/animation/keyframe_animation_decoder.cc @@ -21,8 +21,9 @@ Status KeyframeAnimationDecoder::Decode(const DecoderOptions &options, KeyframeAnimation *animation) { const auto status = PointCloudSequentialDecoder::Decode( options, in_buffer, static_cast<PointCloud *>(animation)); - if (!status.ok()) + if (!status.ok()) { return status; + } return OkStatus(); } diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_decoder.h b/extern/draco/draco/src/draco/animation/keyframe_animation_decoder.h index fdf086b3a38..fdf086b3a38 100644 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_decoder.h +++ b/extern/draco/draco/src/draco/animation/keyframe_animation_decoder.h diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_encoder.cc b/extern/draco/draco/src/draco/animation/keyframe_animation_encoder.cc index f7d84f3106a..f7d84f3106a 100644 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_encoder.cc +++ b/extern/draco/draco/src/draco/animation/keyframe_animation_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_encoder.h b/extern/draco/draco/src/draco/animation/keyframe_animation_encoder.h index 6096c79fa12..6096c79fa12 100644 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_encoder.h +++ b/extern/draco/draco/src/draco/animation/keyframe_animation_encoder.h diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_octahedron_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc index e1180a48dda..283a21251f4 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_octahedron_transform.cc +++ b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc @@ -25,8 +25,9 @@ bool AttributeOctahedronTransform::InitFromAttribute( const AttributeTransformData *const transform_data = attribute.GetAttributeTransformData(); if (!transform_data || - transform_data->transform_type() != ATTRIBUTE_OCTAHEDRON_TRANSFORM) + transform_data->transform_type() != ATTRIBUTE_OCTAHEDRON_TRANSFORM) { return false; // Wrong transform type. + } quantization_bits_ = transform_data->GetParameterValue<int32_t>(0); return true; } @@ -68,8 +69,9 @@ AttributeOctahedronTransform::GeneratePortableAttribute( float att_val[3]; int32_t dst_index = 0; OctahedronToolBox converter; - if (!converter.SetQuantizationBits(quantization_bits_)) + if (!converter.SetQuantizationBits(quantization_bits_)) { return nullptr; + } for (uint32_t i = 0; i < point_ids.size(); ++i) { const AttributeValueIndex att_val_id = attribute.mapped_index(point_ids[i]); attribute.GetValue(att_val_id, att_val); diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_octahedron_transform.h b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h index 6e4e74284f0..6e4e74284f0 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_octahedron_transform.h +++ b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc index 237becefc61..daa634ed03f 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.cc +++ b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc @@ -25,8 +25,9 @@ bool AttributeQuantizationTransform::InitFromAttribute( const AttributeTransformData *const transform_data = attribute.GetAttributeTransformData(); if (!transform_data || - transform_data->transform_type() != ATTRIBUTE_QUANTIZATION_TRANSFORM) + transform_data->transform_type() != ATTRIBUTE_QUANTIZATION_TRANSFORM) { return false; // Wrong transform type. + } int32_t byte_offset = 0; quantization_bits_ = transform_data->GetParameterValue<int32_t>(byte_offset); byte_offset += 4; @@ -80,22 +81,30 @@ bool AttributeQuantizationTransform::ComputeParameters( ++i) { attribute.GetValue(i, att_val.get()); for (int c = 0; c < num_components; ++c) { - if (min_values_[c] > att_val[c]) + if (min_values_[c] > att_val[c]) { min_values_[c] = att_val[c]; - if (max_values[c] < att_val[c]) + } + if (max_values[c] < att_val[c]) { max_values[c] = att_val[c]; + } } } for (int c = 0; c < num_components; ++c) { + if (std::isnan(min_values_[c]) || std::isinf(min_values_[c]) || + std::isnan(max_values[c]) || std::isinf(max_values[c])) { + return false; + } const float dif = max_values[c] - min_values_[c]; - if (dif > range_) + if (dif > range_) { range_ = dif; + } } // In case all values are the same, initialize the range to unit length. This // will ensure that all values are quantized properly to the same value. - if (range_ == 0.f) + if (range_ == 0.f) { range_ = 1.f; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.h b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h index 934856f2db7..934856f2db7 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.h +++ b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_transform.cc index 55af630ac07..55af630ac07 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_transform.cc +++ b/extern/draco/draco/src/draco/attributes/attribute_transform.cc diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_transform.h b/extern/draco/draco/src/draco/attributes/attribute_transform.h index d746fbf6eea..d746fbf6eea 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_transform.h +++ b/extern/draco/draco/src/draco/attributes/attribute_transform.h diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_transform_data.h b/extern/draco/draco/src/draco/attributes/attribute_transform_data.h index 96ed073200d..96ed073200d 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_transform_data.h +++ b/extern/draco/draco/src/draco/attributes/attribute_transform_data.h diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_transform_type.h b/extern/draco/draco/src/draco/attributes/attribute_transform_type.h index 51ce6f333b4..51ce6f333b4 100644 --- a/extern/draco/dracoenc/src/draco/attributes/attribute_transform_type.h +++ b/extern/draco/draco/src/draco/attributes/attribute_transform_type.h diff --git a/extern/draco/dracoenc/src/draco/attributes/geometry_attribute.cc b/extern/draco/draco/src/draco/attributes/geometry_attribute.cc index 914a85d9dc2..f7ed6a86915 100644 --- a/extern/draco/dracoenc/src/draco/attributes/geometry_attribute.cc +++ b/extern/draco/draco/src/draco/attributes/geometry_attribute.cc @@ -14,8 +14,6 @@ // #include "draco/attributes/geometry_attribute.h" -using std::array; - namespace draco { GeometryAttribute::GeometryAttribute() @@ -45,8 +43,9 @@ void GeometryAttribute::Init(GeometryAttribute::Type attribute_type, } bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) { - if (buffer_ == nullptr || src_att.buffer_ == nullptr) + if (buffer_ == nullptr || src_att.buffer_ == nullptr) { return false; + } buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size()); num_components_ = src_att.num_components_; data_type_ = src_att.data_type_; @@ -55,27 +54,35 @@ bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) { byte_offset_ = src_att.byte_offset_; attribute_type_ = src_att.attribute_type_; buffer_descriptor_ = src_att.buffer_descriptor_; + unique_id_ = src_att.unique_id_; return true; } bool GeometryAttribute::operator==(const GeometryAttribute &va) const { - if (attribute_type_ != va.attribute_type_) + if (attribute_type_ != va.attribute_type_) { return false; + } // It's OK to compare just the buffer descriptors here. We don't need to // compare the buffers themselves. - if (buffer_descriptor_.buffer_id != va.buffer_descriptor_.buffer_id) + if (buffer_descriptor_.buffer_id != va.buffer_descriptor_.buffer_id) { return false; + } if (buffer_descriptor_.buffer_update_count != - va.buffer_descriptor_.buffer_update_count) + va.buffer_descriptor_.buffer_update_count) { return false; - if (num_components_ != va.num_components_) + } + if (num_components_ != va.num_components_) { return false; - if (data_type_ != va.data_type_) + } + if (data_type_ != va.data_type_) { return false; - if (byte_stride_ != va.byte_stride_) + } + if (byte_stride_ != va.byte_stride_) { return false; - if (byte_offset_ != va.byte_offset_) + } + if (byte_offset_ != va.byte_offset_) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/attributes/geometry_attribute.h b/extern/draco/draco/src/draco/attributes/geometry_attribute.h index 7be40fe2f65..b94ba8e22dd 100644 --- a/extern/draco/dracoenc/src/draco/attributes/geometry_attribute.h +++ b/extern/draco/draco/src/draco/attributes/geometry_attribute.h @@ -91,8 +91,9 @@ class GeometryAttribute { // Byte address of the attribute index. const int64_t byte_pos = byte_offset_ + byte_stride_ * att_index.value(); // Check we are not reading past end of data. - if (byte_pos + sizeof(*out) > buffer_->data_size()) + if (byte_pos + sizeof(*out) > buffer_->data_size()) { return false; + } buffer_->Read(byte_pos, &((*out)[0]), sizeof(*out)); return true; } @@ -118,6 +119,13 @@ class GeometryAttribute { buffer_->Read(byte_pos, out_data, byte_stride_); } + // Sets a value of an attribute entry. The input value must be allocated to + // cover all components of a single attribute entry. + void SetAttributeValue(AttributeValueIndex entry_index, const void *value) { + const int64_t byte_pos = entry_index.value() * byte_stride(); + buffer_->Write(byte_pos, value, byte_stride()); + } + // DEPRECATED: Use // ConvertValue(AttributeValueIndex att_id, // int out_num_components, @@ -139,8 +147,9 @@ class GeometryAttribute { template <typename OutT> bool ConvertValue(AttributeValueIndex att_id, int8_t out_num_components, OutT *out_val) const { - if (out_val == nullptr) + if (out_val == nullptr) { return false; + } switch (data_type_) { case DT_INT8: return ConvertTypedValue<int8_t, OutT>(att_id, out_num_components, @@ -191,6 +200,26 @@ class GeometryAttribute { return ConvertValue<OutT>(att_index, num_components_, out_value); } + // Utility function. Returns |attribute_type| as std::string. + static std::string TypeToString(Type attribute_type) { + switch (attribute_type) { + case INVALID: + return "INVALID"; + case POSITION: + return "POSITION"; + case NORMAL: + return "NORMAL"; + case COLOR: + return "COLOR"; + case TEX_COORD: + return "TEX_COORD"; + case GENERIC: + return "GENERIC"; + default: + return "UNKNOWN"; + } + } + bool operator==(const GeometryAttribute &va) const; // Returns the type of the attribute indicating the nature of the attribute. @@ -285,8 +314,8 @@ struct GeometryAttributeHasher { size_t hash = HashCombine(va.buffer_descriptor_.buffer_id, va.buffer_descriptor_.buffer_update_count); hash = HashCombine(va.num_components_, hash); - hash = HashCombine((int8_t)va.data_type_, hash); - hash = HashCombine((int8_t)va.attribute_type_, hash); + hash = HashCombine(static_cast<int8_t>(va.data_type_), hash); + hash = HashCombine(static_cast<int8_t>(va.attribute_type_), hash); hash = HashCombine(va.byte_stride_, hash); return HashCombine(va.byte_offset_, hash); } diff --git a/extern/draco/dracoenc/src/draco/attributes/geometry_indices.h b/extern/draco/draco/src/draco/attributes/geometry_indices.h index 80e43e30a13..80e43e30a13 100644 --- a/extern/draco/dracoenc/src/draco/attributes/geometry_indices.h +++ b/extern/draco/draco/src/draco/attributes/geometry_indices.h diff --git a/extern/draco/dracoenc/src/draco/attributes/point_attribute.cc b/extern/draco/draco/src/draco/attributes/point_attribute.cc index 0c4e8e1c738..b28f860c15d 100644 --- a/extern/draco/dracoenc/src/draco/attributes/point_attribute.cc +++ b/extern/draco/draco/src/draco/attributes/point_attribute.cc @@ -32,20 +32,32 @@ PointAttribute::PointAttribute(const GeometryAttribute &att) num_unique_entries_(0), identity_mapping_(false) {} +void PointAttribute::Init(Type attribute_type, int8_t num_components, + DataType data_type, bool normalized, + size_t num_attribute_values) { + attribute_buffer_ = std::unique_ptr<DataBuffer>(new DataBuffer()); + GeometryAttribute::Init(attribute_type, attribute_buffer_.get(), + num_components, data_type, normalized, + DataTypeLength(data_type) * num_components, 0); + Reset(num_attribute_values); + SetIdentityMapping(); +} + void PointAttribute::CopyFrom(const PointAttribute &src_att) { if (buffer() == nullptr) { // If the destination attribute doesn't have a valid buffer, create it. attribute_buffer_ = std::unique_ptr<DataBuffer>(new DataBuffer()); ResetBuffer(attribute_buffer_.get(), 0, 0); } - if (!GeometryAttribute::CopyFrom(src_att)) + if (!GeometryAttribute::CopyFrom(src_att)) { return; + } identity_mapping_ = src_att.identity_mapping_; num_unique_entries_ = src_att.num_unique_entries_; indices_map_ = src_att.indices_map_; if (src_att.attribute_transform_data_) { attribute_transform_data_ = std::unique_ptr<AttributeTransformData>( - new AttributeTransformData(*src_att.attribute_transform_data_.get())); + new AttributeTransformData(*src_att.attribute_transform_data_)); } else { attribute_transform_data_ = nullptr; } @@ -56,14 +68,20 @@ bool PointAttribute::Reset(size_t num_attribute_values) { attribute_buffer_ = std::unique_ptr<DataBuffer>(new DataBuffer()); } const int64_t entry_size = DataTypeLength(data_type()) * num_components(); - if (!attribute_buffer_->Update(nullptr, num_attribute_values * entry_size)) + if (!attribute_buffer_->Update(nullptr, num_attribute_values * entry_size)) { return false; + } // Assign the new buffer to the parent attribute. ResetBuffer(attribute_buffer_.get(), entry_size, 0); num_unique_entries_ = static_cast<uint32_t>(num_attribute_values); return true; } +void PointAttribute::Resize(size_t new_num_unique_entries) { + num_unique_entries_ = static_cast<uint32_t>(new_num_unique_entries); + attribute_buffer_->Resize(new_num_unique_entries * byte_stride()); +} + #ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED AttributeValueIndex::ValueType PointAttribute::DeduplicateValues( const GeometryAttribute &in_att) { @@ -100,8 +118,9 @@ AttributeValueIndex::ValueType PointAttribute::DeduplicateValues( default: return -1; // Unsupported data type. } - if (unique_vals == 0) + if (unique_vals == 0) { return -1; // Unexpected error. + } return unique_vals; } @@ -181,8 +200,9 @@ AttributeValueIndex::ValueType PointAttribute::DeduplicateFormattedValues( ++unique_vals; } } - if (unique_vals == num_unique_entries_) + if (unique_vals == num_unique_entries_) { return unique_vals.value(); // Nothing has changed. + } if (is_mapping_identity()) { // Change identity mapping to the explicit one. // The number of points is equal to the number of old unique values. diff --git a/extern/draco/dracoenc/src/draco/attributes/point_attribute.h b/extern/draco/draco/src/draco/attributes/point_attribute.h index 46e58a40aa1..ee36620313e 100644 --- a/extern/draco/dracoenc/src/draco/attributes/point_attribute.h +++ b/extern/draco/draco/src/draco/attributes/point_attribute.h @@ -17,13 +17,12 @@ #include <memory> -#include "draco/draco_features.h" - #include "draco/attributes/attribute_transform_data.h" #include "draco/attributes/geometry_attribute.h" #include "draco/core/draco_index_type_vector.h" #include "draco/core/hash_utils.h" #include "draco/core/macros.h" +#include "draco/draco_features.h" namespace draco { @@ -41,6 +40,12 @@ class PointAttribute : public GeometryAttribute { PointAttribute(PointAttribute &&attribute) = default; PointAttribute &operator=(PointAttribute &&attribute) = default; + // Initializes a point attribute. By default the attribute will be set to + // identity mapping between point indices and attribute values. To set custom + // mapping use SetExplicitMapping() function. + void Init(Type attribute_type, int8_t num_components, DataType data_type, + bool normalized, size_t num_attribute_values); + // Copies attribute data from the provided |src_att| attribute. void CopyFrom(const PointAttribute &src_att); @@ -49,15 +54,17 @@ class PointAttribute : public GeometryAttribute { size_t size() const { return num_unique_entries_; } AttributeValueIndex mapped_index(PointIndex point_index) const { - if (identity_mapping_) + if (identity_mapping_) { return AttributeValueIndex(point_index.value()); + } return indices_map_[point_index]; } DataBuffer *buffer() const { return attribute_buffer_.get(); } bool is_mapping_identity() const { return identity_mapping_; } size_t indices_map_size() const { - if (is_mapping_identity()) + if (is_mapping_identity()) { return 0; + } return indices_map_.size(); } @@ -65,10 +72,14 @@ class PointAttribute : public GeometryAttribute { return GetAddress(mapped_index(point_index)); } - // Sets the new number of unique attribute entries for the attribute. - void Resize(size_t new_num_unique_entries) { - num_unique_entries_ = static_cast<uint32_t>(new_num_unique_entries); - } + // Sets the new number of unique attribute entries for the attribute. The + // function resizes the attribute storage to hold |num_attribute_values| + // entries. + // All previous entries with AttributeValueIndex < |num_attribute_values| + // are preserved. Caller needs to ensure that the PointAttribute is still + // valid after the resizing operation (that is, each point is mapped to a + // valid attribute value). + void Resize(size_t new_num_unique_entries); // Functions for setting the type of mapping between point indices and // attribute entry ids. @@ -92,13 +103,6 @@ class PointAttribute : public GeometryAttribute { indices_map_[point_index] = entry_index; } - // Sets a value of an attribute entry. The input value must be allocated to - // cover all components of a single attribute entry. - void SetAttributeValue(AttributeValueIndex entry_index, const void *value) { - const int64_t byte_pos = entry_index.value() * byte_stride(); - buffer()->Write(byte_pos, value, byte_stride()); - } - // Same as GeometryAttribute::GetValue(), but using point id as the input. // Mapping to attribute value index is performed automatically. void GetMappedValue(PointIndex point_index, void *out_data) const { @@ -165,7 +169,7 @@ struct PointAttributeHasher { hash = HashCombine(attribute.identity_mapping_, hash); hash = HashCombine(attribute.num_unique_entries_, hash); hash = HashCombine(attribute.indices_map_.size(), hash); - if (attribute.indices_map_.size() > 0) { + if (!attribute.indices_map_.empty()) { const uint64_t indices_hash = FingerprintString( reinterpret_cast<const char *>(attribute.indices_map_.data()), attribute.indices_map_.size()); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc index eb42edea06a..ce5b8b9c756 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc @@ -33,31 +33,42 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (point_cloud_decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!in_buffer->Decode(&num_attributes)) + if (!in_buffer->Decode(&num_attributes)) { return false; + } } else #endif { - if (!DecodeVarint(&num_attributes, in_buffer)) + if (!DecodeVarint(&num_attributes, in_buffer)) { return false; + } } - if (num_attributes == 0) + if (num_attributes == 0) { return false; + } point_attribute_ids_.resize(num_attributes); PointCloud *pc = point_cloud_; for (uint32_t i = 0; i < num_attributes; ++i) { // Decode attribute descriptor data. uint8_t att_type, data_type, num_components, normalized; - if (!in_buffer->Decode(&att_type)) + if (!in_buffer->Decode(&att_type)) { return false; - if (!in_buffer->Decode(&data_type)) + } + if (!in_buffer->Decode(&data_type)) { return false; - if (!in_buffer->Decode(&num_components)) + } + if (!in_buffer->Decode(&num_components)) { return false; - if (!in_buffer->Decode(&normalized)) + } + if (!in_buffer->Decode(&normalized)) { return false; - if (data_type <= DT_INVALID || data_type >= DT_TYPES_COUNT) + } + if (att_type >= GeometryAttribute::NAMED_ATTRIBUTES_COUNT) { + return false; + } + if (data_type == DT_INVALID || data_type >= DT_TYPES_COUNT) { return false; + } const DataType draco_dt = static_cast<DataType>(data_type); // Add the attribute to the point cloud @@ -70,8 +81,9 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) { if (point_cloud_decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 3)) { uint16_t custom_id; - if (!in_buffer->Decode(&custom_id)) + if (!in_buffer->Decode(&custom_id)) { return false; + } // TODO(draco-eng): Add "custom_id" to attribute metadata. unique_id = static_cast<uint32_t>(custom_id); ga.set_unique_id(unique_id); @@ -87,8 +99,10 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) { point_attribute_ids_[i] = att_id; // Update the inverse map. - if (att_id >= static_cast<int32_t>(point_attribute_to_local_id_map_.size())) + if (att_id >= + static_cast<int32_t>(point_attribute_to_local_id_map_.size())) { point_attribute_to_local_id_map_.resize(att_id + 1, -1); + } point_attribute_to_local_id_map_[att_id] = i; } return true; diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_decoder.h b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.h index 9c6e9fe5e4d..5b2bb2cfeb2 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.h @@ -17,11 +17,10 @@ #include <vector> -#include "draco/draco_features.h" - #include "draco/compression/attributes/attributes_decoder_interface.h" #include "draco/compression/point_cloud/point_cloud_decoder.h" #include "draco/core/decoder_buffer.h" +#include "draco/draco_features.h" #include "draco/point_cloud/point_cloud.h" namespace draco { @@ -54,12 +53,15 @@ class AttributesDecoder : public AttributesDecoderInterface { // Decodes attribute data from the source buffer. bool DecodeAttributes(DecoderBuffer *in_buffer) override { - if (!DecodePortableAttributes(in_buffer)) + if (!DecodePortableAttributes(in_buffer)) { return false; - if (!DecodeDataNeededByPortableTransforms(in_buffer)) + } + if (!DecodeDataNeededByPortableTransforms(in_buffer)) { return false; - if (!TransformAttributesToOriginalFormat()) + } + if (!TransformAttributesToOriginalFormat()) { return false; + } return true; } @@ -67,8 +69,9 @@ class AttributesDecoder : public AttributesDecoderInterface { int32_t GetLocalIdForPointAttribute(int32_t point_attribute_id) const { const int id_map_size = static_cast<int>(point_attribute_to_local_id_map_.size()); - if (point_attribute_id >= id_map_size) + if (point_attribute_id >= id_map_size) { return -1; + } return point_attribute_to_local_id_map_[point_attribute_id]; } virtual bool DecodePortableAttributes(DecoderBuffer *in_buffer) = 0; diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_decoder_interface.h b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder_interface.h index 8e5cf52ac3b..8e5cf52ac3b 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_decoder_interface.h +++ b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder_interface.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc index 797c62f30aa..797c62f30aa 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_encoder.h b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.h index 09d10109803..9de846ae6d4 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/attributes_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.h @@ -48,15 +48,18 @@ class AttributesEncoder { // Encode attribute data to the target buffer. virtual bool EncodeAttributes(EncoderBuffer *out_buffer) { - if (!TransformAttributesToPortableFormat()) + if (!TransformAttributesToPortableFormat()) { return false; - if (!EncodePortableAttributes(out_buffer)) + } + if (!EncodePortableAttributes(out_buffer)) { return false; + } // Encode data needed by portable transforms after the attribute is encoded. // This corresponds to the order in which the data is going to be decoded by // the decoder. - if (!EncodeDataNeededByPortableTransforms(out_buffer)) + if (!EncodeDataNeededByPortableTransforms(out_buffer)) { return false; + } return true; } @@ -87,8 +90,9 @@ class AttributesEncoder { void AddAttributeId(int32_t id) { point_attribute_ids_.push_back(id); - if (id >= static_cast<int32_t>(point_attribute_to_local_id_map_.size())) + if (id >= static_cast<int32_t>(point_attribute_to_local_id_map_.size())) { point_attribute_to_local_id_map_.resize(id + 1, -1); + } point_attribute_to_local_id_map_[id] = static_cast<int32_t>(point_attribute_ids_.size()) - 1; } @@ -127,8 +131,9 @@ class AttributesEncoder { int32_t GetLocalIdForPointAttribute(int32_t point_attribute_id) const { const int id_map_size = static_cast<int>(point_attribute_to_local_id_map_.size()); - if (point_attribute_id >= id_map_size) + if (point_attribute_id >= id_map_size) { return -1; + } return point_attribute_to_local_id_map_[point_attribute_id]; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc index 4faa8ab29b5..99469f94590 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/compression/attributes/kd_tree_attributes_decoder.h" + #include "draco/compression/attributes/kd_tree_attributes_shared.h" #include "draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h" #include "draco/compression/point_cloud/algorithms/float_points_tree_decoder.h" @@ -92,7 +93,7 @@ class PointAttributeVectorOutputIterator { const uint32_t &data_size = std::get<3>(att); const uint32_t &num_components = std::get<4>(att); const uint32_t *data_source = val.data() + offset; - if (data_size != 4) { // handle uint16_t, uint8_t + if (data_size < 4) { // handle uint16_t, uint8_t // selectively copy data bytes uint8_t *data_counter = data_; for (uint32_t index = 0; index < num_components; @@ -103,8 +104,9 @@ class PointAttributeVectorOutputIterator { data_source = reinterpret_cast<uint32_t *>(data_); } const AttributeValueIndex avi = attribute->mapped_index(point_id_); - if (avi >= static_cast<uint32_t>(attribute->size())) + if (avi >= static_cast<uint32_t>(attribute->size())) { return *this; + } attribute->SetAttributeValue(avi, data_source); } return *this; @@ -134,8 +136,9 @@ bool KdTreeAttributesDecoder::DecodePortableAttributes( return true; } uint8_t compression_level = 0; - if (!in_buffer->Decode(&compression_level)) + if (!in_buffer->Decode(&compression_level)) { return false; + } const int32_t num_points = GetDecoder()->point_cloud()->num_points(); // Decode data using the kd tree decoding into integer (portable) attributes. @@ -197,44 +200,51 @@ bool KdTreeAttributesDecoder::DecodePortableAttributes( switch (compression_level) { case 0: { DynamicIntegerPointsKdTreeDecoder<0> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 1: { DynamicIntegerPointsKdTreeDecoder<1> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 2: { DynamicIntegerPointsKdTreeDecoder<2> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 3: { DynamicIntegerPointsKdTreeDecoder<3> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 4: { DynamicIntegerPointsKdTreeDecoder<4> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 5: { DynamicIntegerPointsKdTreeDecoder<5> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 6: { DynamicIntegerPointsKdTreeDecoder<6> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } default: @@ -256,22 +266,26 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( if (att->data_type() == DT_FLOAT32) { const int num_components = att->num_components(); min_value.resize(num_components); - if (!in_buffer->Decode(&min_value[0], sizeof(float) * num_components)) + if (!in_buffer->Decode(&min_value[0], sizeof(float) * num_components)) { return false; + } float max_value_dif; - if (!in_buffer->Decode(&max_value_dif)) + if (!in_buffer->Decode(&max_value_dif)) { return false; + } uint8_t quantization_bits; - if (!in_buffer->Decode(&quantization_bits) || quantization_bits > 31) + if (!in_buffer->Decode(&quantization_bits) || quantization_bits > 31) { return false; + } AttributeQuantizationTransform transform; transform.SetParameters(quantization_bits, min_value.data(), num_components, max_value_dif); const int num_transforms = static_cast<int>(attribute_quantization_transforms_.size()); if (!transform.TransferToAttribute( - quantized_portable_attributes_[num_transforms].get())) + quantized_portable_attributes_[num_transforms].get())) { return false; + } attribute_quantization_transforms_.push_back(transform); } } @@ -299,6 +313,10 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( const DataType data_type = att->data_type(); const uint32_t data_size = (std::max)(0, DataTypeLength(data_type)); const uint32_t num_components = att->num_components(); + if (data_size > 4) { + return false; + } + atts[attribute_index] = std::make_tuple( att, total_dimensionality, data_type, data_size, num_components); // everything is treated as 32bit in the encoder. @@ -310,24 +328,30 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( att->SetIdentityMapping(); // Decode method uint8_t method; - if (!in_buffer->Decode(&method)) + if (!in_buffer->Decode(&method)) { return false; + } if (method == KdTreeAttributesEncodingMethod::kKdTreeQuantizationEncoding) { uint8_t compression_level = 0; - if (!in_buffer->Decode(&compression_level)) + if (!in_buffer->Decode(&compression_level)) { return false; + } uint32_t num_points = 0; - if (!in_buffer->Decode(&num_points)) + if (!in_buffer->Decode(&num_points)) { return false; + } att->Reset(num_points); FloatPointsTreeDecoder decoder; + decoder.set_num_points_from_header(num_points); PointAttributeVectorOutputIterator<float> out_it(atts); - if (!decoder.DecodePointCloud(in_buffer, out_it)) + if (!decoder.DecodePointCloud(in_buffer, out_it)) { return false; + } } else if (method == KdTreeAttributesEncodingMethod::kKdTreeIntegerEncoding) { uint8_t compression_level = 0; - if (!in_buffer->Decode(&compression_level)) + if (!in_buffer->Decode(&compression_level)) { return false; + } if (6 < compression_level) { LOGE("KdTreeAttributesDecoder: compression level %i not supported.\n", compression_level); @@ -335,8 +359,9 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( } uint32_t num_points; - if (!in_buffer->Decode(&num_points)) + if (!in_buffer->Decode(&num_points)) { return false; + } for (auto attribute_index = 0; static_cast<uint32_t>(attribute_index) < attribute_count; @@ -353,44 +378,51 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( switch (compression_level) { case 0: { DynamicIntegerPointsKdTreeDecoder<0> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 1: { DynamicIntegerPointsKdTreeDecoder<1> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 2: { DynamicIntegerPointsKdTreeDecoder<2> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 3: { DynamicIntegerPointsKdTreeDecoder<3> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 4: { DynamicIntegerPointsKdTreeDecoder<4> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 5: { DynamicIntegerPointsKdTreeDecoder<5> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } case 6: { DynamicIntegerPointsKdTreeDecoder<6> decoder(total_dimensionality); - if (!decoder.DecodePoints(in_buffer, out_it)) + if (!decoder.DecodePoints(in_buffer, out_it)) { return false; + } break; } default: @@ -445,16 +477,19 @@ bool KdTreeAttributesDecoder::TransformAttributesToOriginalFormat() { // Values are stored as unsigned in the attribute, make them signed again. if (att->data_type() == DT_INT32) { if (!TransformAttributeBackToSignedType<int32_t>( - att, num_processed_signed_components)) + att, num_processed_signed_components)) { return false; + } } else if (att->data_type() == DT_INT16) { if (!TransformAttributeBackToSignedType<int16_t>( - att, num_processed_signed_components)) + att, num_processed_signed_components)) { return false; + } } else if (att->data_type() == DT_INT8) { if (!TransformAttributeBackToSignedType<int8_t>( - att, num_processed_signed_components)) + att, num_processed_signed_components)) { return false; + } } num_processed_signed_components += att->num_components(); } else if (att->data_type() == DT_FLOAT32) { @@ -491,8 +526,9 @@ bool KdTreeAttributesDecoder::TransformAttributesToOriginalFormat() { int quant_val_id = 0; int out_byte_pos = 0; Dequantizer dequantizer; - if (!dequantizer.Init(transform.range(), max_quantized_value)) + if (!dequantizer.Init(transform.range(), max_quantized_value)) { return false; + } const uint32_t *const portable_attribute_data = reinterpret_cast<const uint32_t *>( src_att->GetAddress(AttributeValueIndex(0))); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_decoder.h b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.h index 87338d6b0d4..87338d6b0d4 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc index f2a8af23bfc..0f9c31565e5 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/compression/attributes/kd_tree_attributes_encoder.h" + #include "draco/compression/attributes/kd_tree_attributes_shared.h" #include "draco/compression/attributes/point_d_vector.h" #include "draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h" @@ -50,8 +51,9 @@ bool KdTreeAttributesEncoder::TransformAttributesToPortableFormat() { AttributeQuantizationTransform attribute_quantization_transform; const int quantization_bits = encoder()->options()->GetAttributeInt( att_id, "quantization_bits", -1); - if (quantization_bits < 1) + if (quantization_bits < 1) { return false; + } if (encoder()->options()->IsAttributeOptionSet(att_id, "quantization_origin") && encoder()->options()->IsAttributeOptionSet(att_id, @@ -91,8 +93,9 @@ bool KdTreeAttributesEncoder::TransformAttributesToPortableFormat() { ++avi) { att->ConvertValue<int32_t>(avi, &act_value[0]); for (int c = 0; c < att->num_components(); ++c) { - if (min_value[c] > act_value[c]) + if (min_value[c] > act_value[c]) { min_value[c] = act_value[c]; + } } } for (int c = 0; c < att->num_components(); ++c) { @@ -167,8 +170,9 @@ bool KdTreeAttributesEncoder::EncodePortableAttributes( return false; } - if (source_att == nullptr) + if (source_att == nullptr) { return false; + } // Copy source_att to the vector. if (source_att->data_type() == DT_UINT32) { @@ -233,50 +237,57 @@ bool KdTreeAttributesEncoder::EncodePortableAttributes( case 6: { DynamicIntegerPointsKdTreeEncoder<6> points_encoder(num_components_); if (!points_encoder.EncodePoints(point_vector.begin(), point_vector.end(), - num_bits, out_buffer)) + num_bits, out_buffer)) { return false; + } break; } case 5: { DynamicIntegerPointsKdTreeEncoder<5> points_encoder(num_components_); if (!points_encoder.EncodePoints(point_vector.begin(), point_vector.end(), - num_bits, out_buffer)) + num_bits, out_buffer)) { return false; + } break; } case 4: { DynamicIntegerPointsKdTreeEncoder<4> points_encoder(num_components_); if (!points_encoder.EncodePoints(point_vector.begin(), point_vector.end(), - num_bits, out_buffer)) + num_bits, out_buffer)) { return false; + } break; } case 3: { DynamicIntegerPointsKdTreeEncoder<3> points_encoder(num_components_); if (!points_encoder.EncodePoints(point_vector.begin(), point_vector.end(), - num_bits, out_buffer)) + num_bits, out_buffer)) { return false; + } break; } case 2: { DynamicIntegerPointsKdTreeEncoder<2> points_encoder(num_components_); if (!points_encoder.EncodePoints(point_vector.begin(), point_vector.end(), - num_bits, out_buffer)) + num_bits, out_buffer)) { return false; + } break; } case 1: { DynamicIntegerPointsKdTreeEncoder<1> points_encoder(num_components_); if (!points_encoder.EncodePoints(point_vector.begin(), point_vector.end(), - num_bits, out_buffer)) + num_bits, out_buffer)) { return false; + } break; } case 0: { DynamicIntegerPointsKdTreeEncoder<0> points_encoder(num_components_); if (!points_encoder.EncodePoints(point_vector.begin(), point_vector.end(), - num_bits, out_buffer)) + num_bits, out_buffer)) { return false; + } break; } // Compression level and/or encoding speed seem wrong. diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_encoder.h b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h index 8b4c4e2faab..8b4c4e2faab 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_shared.h b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_shared.h index 94841a91d99..94841a91d99 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/kd_tree_attributes_shared.h +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_shared.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/linear_sequencer.h b/extern/draco/draco/src/draco/compression/attributes/linear_sequencer.h index dc4dfffe9d5..7d9b5264199 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/linear_sequencer.h +++ b/extern/draco/draco/src/draco/compression/attributes/linear_sequencer.h @@ -32,8 +32,9 @@ class LinearSequencer : public PointsSequencer { protected: bool GenerateSequenceInternal() override { - if (num_points_ < 0) + if (num_points_ < 0) { return false; + } out_point_ids()->resize(num_points_); for (int i = 0; i < num_points_; ++i) { out_point_ids()->at(i) = PointIndex(i); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/mesh_attribute_indices_encoding_data.h b/extern/draco/draco/src/draco/compression/attributes/mesh_attribute_indices_encoding_data.h index 9a358e44733..9a358e44733 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/mesh_attribute_indices_encoding_data.h +++ b/extern/draco/draco/src/draco/compression/attributes/mesh_attribute_indices_encoding_data.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/normal_compression_utils.h b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h index 4e6ff1a2134..32e27c711e3 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/normal_compression_utils.h +++ b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h @@ -39,6 +39,7 @@ #define DRACO_COMPRESSION_ATTRIBUTES_NORMAL_COMPRESSION_UTILS_H_ #include <inttypes.h> + #include <algorithm> #include <cmath> @@ -55,8 +56,9 @@ class OctahedronToolBox { center_value_(-1) {} bool SetQuantizationBits(int32_t q) { - if (q < 2 || q > 30) + if (q < 2 || q > 30) { return false; + } quantization_bits_ = q; max_quantized_value_ = (1 << quantization_bits_) - 1; max_value_ = max_quantized_value_ - 1; @@ -157,8 +159,9 @@ class OctahedronToolBox { int_vec[2] = 0; } // Take care of the sign. - if (scaled_vector[2] < 0) + if (scaled_vector[2] < 0) { int_vec[2] *= -1; + } IntegerVectorToQuantizedOctahedralCoords(int_vec, out_s, out_t); } @@ -189,6 +192,8 @@ class OctahedronToolBox { } } + // TODO(b/149328891): Change function to not use templates as |T| is only + // float. template <typename T> void OctaherdalCoordsToUnitVector(T in_s, T in_t, T *out_vector) const { DRACO_DCHECK_GE(in_s, 0); @@ -304,18 +309,21 @@ class OctahedronToolBox { // For correction values. int32_t ModMax(int32_t x) const { - if (x > this->center_value()) + if (x > this->center_value()) { return x - this->max_quantized_value(); - if (x < -this->center_value()) + } + if (x < -this->center_value()) { return x + this->max_quantized_value(); + } return x; } // For correction values. int32_t MakePositive(int32_t x) const { DRACO_DCHECK_LE(x, this->center_value() * 2); - if (x < 0) + if (x < 0) { return x + this->max_quantized_value(); + } return x; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector.h b/extern/draco/draco/src/draco/compression/attributes/point_d_vector.h index ce99c8014d7..3b115d500cd 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector.h +++ b/extern/draco/draco/src/draco/compression/attributes/point_d_vector.h @@ -19,6 +19,7 @@ #include <cstring> #include <memory> #include <vector> + #include "draco/core/macros.h" namespace draco { @@ -42,8 +43,9 @@ class PseudoPointD { // Specifically copies referenced memory void swap(PseudoPointD &other) noexcept { - for (internal_t dim = 0; dim < dimension_; dim += 1) + for (internal_t dim = 0; dim < dimension_; dim += 1) { std::swap(mem_[dim], other.mem_[dim]); + } } PseudoPointD(const PseudoPointD &other) @@ -59,9 +61,11 @@ class PseudoPointD { } bool operator==(const PseudoPointD &other) const { - for (auto dim = 0; dim < dimension_; dim += 1) - if (mem_[dim] != other.mem_[dim]) + for (auto dim = 0; dim < dimension_; dim += 1) { + if (mem_[dim] != other.mem_[dim]) { return false; + } + } return true; } bool operator!=(const PseudoPointD &other) const { diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/points_sequencer.h b/extern/draco/draco/src/draco/compression/attributes/points_sequencer.h index 2f4f7e16d11..2f4f7e16d11 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/points_sequencer.h +++ b/extern/draco/draco/src/draco/compression/attributes/points_sequencer.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h index b64b23d25de..36c124baa83 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h @@ -18,13 +18,12 @@ #include <algorithm> #include <cmath> -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_shared.h" #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h" #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h" #include "draco/compression/bit_coders/rans_bit_decoder.h" #include "draco/core/varint_decoding.h" +#include "draco/draco_features.h" namespace draco { @@ -123,8 +122,9 @@ bool MeshPredictionSchemeConstrainedMultiParallelogramDecoder< ++num_parallelograms; // Stop processing when we reach the maximum number of allowed // parallelograms. - if (num_parallelograms == kMaxNumParallelograms) + if (num_parallelograms == kMaxNumParallelograms) { break; + } } // Proceed to the next corner attached to the vertex. First swing left @@ -154,8 +154,9 @@ bool MeshPredictionSchemeConstrainedMultiParallelogramDecoder< for (int i = 0; i < num_parallelograms; ++i) { const int context = num_parallelograms - 1; const int pos = is_crease_edge_pos[context]++; - if (is_crease_edge_[context].size() <= pos) + if (is_crease_edge_[context].size() <= pos) { return false; + } const bool is_crease = is_crease_edge_[context][pos]; if (!is_crease) { ++num_used_parallelograms; @@ -206,12 +207,15 @@ bool MeshPredictionSchemeConstrainedMultiParallelogramDecoder< // Encode selected edges using separate rans bit coder for each context. for (int i = 0; i < kMaxNumParallelograms; ++i) { uint32_t num_flags; - DecodeVarint<uint32_t>(&num_flags, buffer); + if (!DecodeVarint<uint32_t>(&num_flags, buffer)) { + return false; + } if (num_flags > 0) { is_crease_edge_[i].resize(num_flags); RAnsBitDecoder decoder; - if (!decoder.StartDecoding(buffer)) + if (!decoder.StartDecoding(buffer)) { return false; + } for (uint32_t j = 0; j < num_flags; ++j) { is_crease_edge_[i][j] = decoder.DecodeNextBit(); } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_encoder.h index 455c2ceb5ed..77df8ee24f1 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_encoder.h @@ -108,10 +108,12 @@ class MeshPredictionSchemeConstrainedMultiParallelogramEncoder int residual_error; bool operator<(const Error &e) const { - if (num_bits < e.num_bits) + if (num_bits < e.num_bits) { return true; - if (num_bits > e.num_bits) + } + if (num_bits > e.num_bits) { return false; + } return residual_error < e.residual_error; } }; @@ -231,8 +233,9 @@ bool MeshPredictionSchemeConstrainedMultiParallelogramEncoder< ++num_parallelograms; // Stop processing when we reach the maximum number of allowed // parallelograms. - if (num_parallelograms == kMaxNumParallelograms) + if (num_parallelograms == kMaxNumParallelograms) { break; + } } // Proceed to the next corner attached to the vertex. First swing left @@ -304,8 +307,9 @@ bool MeshPredictionSchemeConstrainedMultiParallelogramEncoder< } uint8_t configuration = 0; for (int j = 0; j < num_parallelograms; ++j) { - if (exluded_parallelograms[j]) + if (exluded_parallelograms[j]) { continue; + } for (int c = 0; c < num_components; ++c) { multi_pred_vals[c] += pred_vals[j][c]; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_shared.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_shared.h index c7a4e351aeb..c7a4e351aeb 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_shared.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_shared.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h index f712952556a..f712952556a 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h index 6694a981c10..6694a981c10 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_encoder.h index ab3c81a3901..ab3c81a3901 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h index cd8299627b7..da1387a3075 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h @@ -15,11 +15,10 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_GEOMETRIC_NORMAL_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_GEOMETRIC_NORMAL_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h" #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h" #include "draco/compression/bit_coders/rans_bit_decoder.h" +#include "draco/draco_features.h" namespace draco { @@ -52,12 +51,15 @@ class MeshPredictionSchemeGeometricNormalDecoder } bool IsInitialized() const override { - if (!predictor_.IsInitialized()) + if (!predictor_.IsInitialized()) { return false; - if (!this->mesh_data().IsInitialized()) + } + if (!this->mesh_data().IsInitialized()) { return false; - if (!octahedron_tool_box_.IsInitialized()) + } + if (!octahedron_tool_box_.IsInitialized()) { return false; + } return true; } @@ -70,10 +72,12 @@ class MeshPredictionSchemeGeometricNormalDecoder } bool SetParentAttribute(const PointAttribute *att) override { - if (att->attribute_type() != GeometryAttribute::POSITION) + if (att->attribute_type() != GeometryAttribute::POSITION) { return false; // Invalid attribute type. - if (att->num_components() != 3) + } + if (att->num_components() != 3) { return false; // Currently works only for 3 component positions. + } predictor_.SetPositionAttribute(*att); return true; } @@ -137,23 +141,28 @@ bool MeshPredictionSchemeGeometricNormalDecoder< DataTypeT, TransformT, MeshDataT>::DecodePredictionData(DecoderBuffer *buffer) { // Get data needed for transform - if (!this->transform().DecodeTransformData(buffer)) + if (!this->transform().DecodeTransformData(buffer)) { return false; + } #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { uint8_t prediction_mode; - buffer->Decode(&prediction_mode); + if (!buffer->Decode(&prediction_mode)) { + return false; + } if (!predictor_.SetNormalPredictionMode( - NormalPredictionMode(prediction_mode))) + NormalPredictionMode(prediction_mode))) { return false; + } } #endif // Init normal flips. - if (!flip_normal_bit_decoder_.StartDecoding(buffer)) + if (!flip_normal_bit_decoder_.StartDecoding(buffer)) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_encoder.h index ffddf0170d6..cf146f83ac9 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_encoder.h @@ -50,10 +50,12 @@ class MeshPredictionSchemeGeometricNormalEncoder } bool IsInitialized() const override { - if (!predictor_.IsInitialized()) + if (!predictor_.IsInitialized()) { return false; - if (!this->mesh_data().IsInitialized()) + } + if (!this->mesh_data().IsInitialized()) { return false; + } return true; } @@ -66,10 +68,12 @@ class MeshPredictionSchemeGeometricNormalEncoder } bool SetParentAttribute(const PointAttribute *att) override { - if (att->attribute_type() != GeometryAttribute::POSITION) + if (att->attribute_type() != GeometryAttribute::POSITION) { return false; // Invalid attribute type. - if (att->num_components() != 3) + } + if (att->num_components() != 3) { return false; // Currently works only for 3 component positions. + } predictor_.SetPositionAttribute(*att); return true; } @@ -162,8 +166,9 @@ template <typename DataTypeT, class TransformT, class MeshDataT> bool MeshPredictionSchemeGeometricNormalEncoder< DataTypeT, TransformT, MeshDataT>::EncodePredictionData(EncoderBuffer *buffer) { - if (!this->transform().EncodeTransformData(buffer)) + if (!this->transform().EncodeTransformData(buffer)) { return false; + } // Encode normal flips. flip_normal_bit_encoder_.EndEncoding(buffer); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h index bf1a6146111..bf1a6146111 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_base.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_base.h index 9a26551decf..a554dda9676 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_base.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_base.h @@ -45,10 +45,12 @@ class MeshPredictionSchemeGeometricNormalPredictorBase { entry_to_point_id_map_ = map; } bool IsInitialized() const { - if (pos_attribute_ == nullptr) + if (pos_attribute_ == nullptr) { return false; - if (entry_to_point_id_map_ == nullptr) + } + if (entry_to_point_id_map_ == nullptr) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h index a0cc802da03..fc82e0a8f76 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h @@ -16,10 +16,9 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_MULTI_PARALLELOGRAM_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_MULTI_PARALLELOGRAM_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h" #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h" +#include "draco/draco_features.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_encoder.h index 301b357d411..301b357d411 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h index 4d47ddf306e..4d47ddf306e 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_encoder.h index f00801932c2..f00801932c2 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h index c63c8d05ba6..485d457ccf6 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h @@ -47,8 +47,9 @@ inline bool ComputeParallelogramPrediction( const std::vector<int32_t> &vertex_to_data_map, const DataTypeT *in_data, int num_components, DataTypeT *out_prediction) { const CornerIndex oci = table->Opposite(ci); - if (oci == kInvalidCornerIndex) + if (oci == kInvalidCornerIndex) { return false; + } int vert_opp, vert_next, vert_prev; GetParallelogramEntries<CornerTableT>(oci, table, vertex_to_data_map, &vert_opp, &vert_next, &vert_prev); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_decoder.h index 2e389b2a2b4..02cf7e60f26 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_decoder.h @@ -18,12 +18,11 @@ #include <math.h> -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_decoder.h" #include "draco/compression/bit_coders/rans_bit_decoder.h" #include "draco/core/varint_decoding.h" #include "draco/core/vector_d.h" +#include "draco/draco_features.h" #include "draco/mesh/corner_table.h" namespace draco { @@ -60,10 +59,12 @@ class MeshPredictionSchemeTexCoordsDecoder } bool IsInitialized() const override { - if (pos_attribute_ == nullptr) + if (pos_attribute_ == nullptr) { return false; - if (!this->mesh_data().IsInitialized()) + } + if (!this->mesh_data().IsInitialized()) { return false; + } return true; } @@ -76,12 +77,15 @@ class MeshPredictionSchemeTexCoordsDecoder } bool SetParentAttribute(const PointAttribute *att) override { - if (att == nullptr) + if (att == nullptr) { return false; - if (att->attribute_type() != GeometryAttribute::POSITION) + } + if (att->attribute_type() != GeometryAttribute::POSITION) { return false; // Invalid attribute type. - if (att->num_components() != 3) + } + if (att->num_components() != 3) { return false; // Currently works only for 3 component positions. + } pos_attribute_ = att; return true; } @@ -144,22 +148,27 @@ bool MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT, MeshDataT>:: // Decode the delta coded orientations. uint32_t num_orientations = 0; if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { - if (!buffer->Decode(&num_orientations)) + if (!buffer->Decode(&num_orientations)) { return false; + } } else { - if (!DecodeVarint(&num_orientations, buffer)) + if (!DecodeVarint(&num_orientations, buffer)) { return false; + } } - if (num_orientations == 0) + if (num_orientations == 0) { return false; + } orientations_.resize(num_orientations); bool last_orientation = true; RAnsBitDecoder decoder; - if (!decoder.StartDecoding(buffer)) + if (!decoder.StartDecoding(buffer)) { return false; + } for (uint32_t i = 0; i < num_orientations; ++i) { - if (!decoder.DecodeNextBit()) + if (!decoder.DecodeNextBit()) { last_orientation = !last_orientation; + } orientations_[i] = last_orientation; } decoder.EndDecoding(); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_encoder.h index 0e938b9c388..813b72ae35f 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_encoder.h @@ -16,6 +16,7 @@ #define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_TEX_COORDS_ENCODER_H_ #include <math.h> + #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_encoder.h" #include "draco/compression/bit_coders/rans_bit_encoder.h" #include "draco/core/varint_encoding.h" @@ -55,10 +56,12 @@ class MeshPredictionSchemeTexCoordsEncoder } bool IsInitialized() const override { - if (pos_attribute_ == nullptr) + if (pos_attribute_ == nullptr) { return false; - if (!this->mesh_data().IsInitialized()) + } + if (!this->mesh_data().IsInitialized()) { return false; + } return true; } @@ -71,10 +74,12 @@ class MeshPredictionSchemeTexCoordsEncoder } bool SetParentAttribute(const PointAttribute *att) override { - if (att->attribute_type() != GeometryAttribute::POSITION) + if (att->attribute_type() != GeometryAttribute::POSITION) { return false; // Invalid attribute type. - if (att->num_components() != 3) + } + if (att->num_components() != 3) { return false; // Currently works only for 3 component positions. + } pos_attribute_ = att; return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_decoder.h index 0fee0ceb6e2..83d4966393f 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_decoder.h @@ -48,10 +48,12 @@ class MeshPredictionSchemeTexCoordsPortableDecoder } bool IsInitialized() const override { - if (!predictor_.IsInitialized()) + if (!predictor_.IsInitialized()) { return false; - if (!this->mesh_data().IsInitialized()) + } + if (!this->mesh_data().IsInitialized()) { return false; + } return true; } @@ -64,10 +66,12 @@ class MeshPredictionSchemeTexCoordsPortableDecoder } bool SetParentAttribute(const PointAttribute *att) override { - if (!att || att->attribute_type() != GeometryAttribute::POSITION) + if (!att || att->attribute_type() != GeometryAttribute::POSITION) { return false; // Invalid attribute type. - if (att->num_components() != 3) + } + if (att->num_components() != 3) { return false; // Currently works only for 3 component positions. + } predictor_.SetPositionAttribute(*att); return true; } @@ -84,6 +88,10 @@ bool MeshPredictionSchemeTexCoordsPortableDecoder< DataTypeT *out_data, int /* size */, int num_components, const PointIndex *entry_to_point_id_map) { + if (num_components != MeshPredictionSchemeTexCoordsPortablePredictor< + DataTypeT, MeshDataT>::kNumComponents) { + return false; + } predictor_.SetEntryToPointIdMap(entry_to_point_id_map); this->transform().Init(num_components); @@ -92,8 +100,9 @@ bool MeshPredictionSchemeTexCoordsPortableDecoder< for (int p = 0; p < corner_map_size; ++p) { const CornerIndex corner_id = this->mesh_data().data_to_corner_map()->at(p); if (!predictor_.template ComputePredictedValue<false>(corner_id, out_data, - p)) + p)) { return false; + } const int dst_offset = p * num_components; this->transform().ComputeOriginalValue(predictor_.predicted_value(), @@ -109,16 +118,19 @@ bool MeshPredictionSchemeTexCoordsPortableDecoder< *buffer) { // Decode the delta coded orientations. int32_t num_orientations = 0; - if (!buffer->Decode(&num_orientations) || num_orientations < 0) + if (!buffer->Decode(&num_orientations) || num_orientations < 0) { return false; + } predictor_.ResizeOrientations(num_orientations); bool last_orientation = true; RAnsBitDecoder decoder; - if (!decoder.StartDecoding(buffer)) + if (!decoder.StartDecoding(buffer)) { return false; + } for (int i = 0; i < num_orientations; ++i) { - if (!decoder.DecodeNextBit()) + if (!decoder.DecodeNextBit()) { last_orientation = !last_orientation; + } predictor_.set_orientation(i, last_orientation); } decoder.EndDecoding(); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_encoder.h index 04a66325183..741ec66dc2a 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_encoder.h @@ -51,10 +51,12 @@ class MeshPredictionSchemeTexCoordsPortableEncoder } bool IsInitialized() const override { - if (!predictor_.IsInitialized()) + if (!predictor_.IsInitialized()) { return false; - if (!this->mesh_data().IsInitialized()) + } + if (!this->mesh_data().IsInitialized()) { return false; + } return true; } @@ -67,10 +69,12 @@ class MeshPredictionSchemeTexCoordsPortableEncoder } bool SetParentAttribute(const PointAttribute *att) override { - if (att->attribute_type() != GeometryAttribute::POSITION) + if (att->attribute_type() != GeometryAttribute::POSITION) { return false; // Invalid attribute type. - if (att->num_components() != 3) + } + if (att->num_components() != 3) { return false; // Currently works only for 3 component positions. + } predictor_.SetPositionAttribute(*att); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h index f9357712638..5d8a5060133 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h @@ -16,6 +16,7 @@ #define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_TEX_COORDS_PORTABLE_PREDICTOR_H_ #include <math.h> + #include "draco/attributes/point_attribute.h" #include "draco/core/math_utils.h" #include "draco/core/vector_d.h" @@ -28,6 +29,8 @@ namespace draco { template <typename DataTypeT, class MeshDataT> class MeshPredictionSchemeTexCoordsPortablePredictor { public: + static constexpr int kNumComponents = 2; + explicit MeshPredictionSchemeTexCoordsPortablePredictor(const MeshDataT &md) : pos_attribute_(nullptr), entry_to_point_id_map_(nullptr), @@ -71,7 +74,6 @@ class MeshPredictionSchemeTexCoordsPortablePredictor { private: const PointAttribute *pos_attribute_; const PointIndex *entry_to_point_id_map_; - static constexpr int kNumComponents = 2; DataTypeT predicted_value_[kNumComponents]; // Encoded / decoded array of UV flips. // TODO(ostava): We should remove this and replace this with in-place encoding @@ -203,14 +205,16 @@ bool MeshPredictionSchemeTexCoordsPortablePredictor< } } else { // When decoding the data, we already know which orientation to use. - if (orientations_.empty()) + if (orientations_.empty()) { return false; + } const bool orientation = orientations_.back(); orientations_.pop_back(); - if (orientation) + if (orientation) { predicted_uv = (x_uv + cx_uv) / pn_norm2_squared; - else + } else { predicted_uv = (x_uv - cx_uv) / pn_norm2_squared; + } } predicted_value_[0] = static_cast<int>(predicted_uv[0]); predicted_value_[1] = static_cast<int>(predicted_uv[1]); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder.h index 9a14ff8d7d2..064e1b44fe1 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder.h @@ -46,8 +46,9 @@ class PredictionSchemeDecoder : public PredictionSchemeTypedDecoderInterface< : attribute_(attribute), transform_(transform) {} bool DecodePredictionData(DecoderBuffer *buffer) override { - if (!transform_.DecodeTransformData(buffer)) + if (!transform_.DecodeTransformData(buffer)) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h index db835554385..cf2a6ba6b3b 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h @@ -18,9 +18,8 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_DECODER_FACTORY_H_ #define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_DECODER_FACTORY_H_ -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h" +#include "draco/draco_features.h" #ifdef DRACO_NORMAL_ENCODING_SUPPORTED #include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h" #endif @@ -154,8 +153,9 @@ std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>> CreatePredictionSchemeForDecoder(PredictionSchemeMethod method, int att_id, const PointCloudDecoder *decoder, const TransformT &transform) { - if (method == PREDICTION_NONE) + if (method == PREDICTION_NONE) { return nullptr; + } const PointAttribute *const att = decoder->point_cloud()->attribute(att_id); if (decoder->GetGeometryType() == TRIANGULAR_MESH) { // Cast the decoder to mesh decoder. This is not necessarily safe if there @@ -170,8 +170,9 @@ CreatePredictionSchemeForDecoder(PredictionSchemeMethod method, int att_id, MeshDecoder, PredictionSchemeDecoder<DataTypeT, TransformT>, MeshPredictionSchemeDecoderFactory<DataTypeT>>( mesh_decoder, method, att_id, transform, decoder->bitstream_version()); - if (ret) + if (ret) { return ret; + } // Otherwise try to create another prediction scheme. } // Create delta decoder. diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_interface.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_interface.h index 6f19f7fdb99..6f19f7fdb99 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_interface.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_interface.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoding_transform.h index 47c1532ad98..47c1532ad98 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoding_transform.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_decoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_decoder.h index ae72c71208a..ae72c71208a 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_encoder.h index 324afafa637..324afafa637 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_delta_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder.h index 548a54d4e02..2a211a9fc20 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder.h @@ -46,8 +46,9 @@ class PredictionSchemeEncoder : public PredictionSchemeTypedEncoderInterface< : attribute_(attribute), transform_(transform) {} bool EncodePredictionData(EncoderBuffer *buffer) override { - if (!transform_.EncodeTransformData(buffer)) + if (!transform_.EncodeTransformData(buffer)) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc index 6b74e571c6d..428340da013 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc @@ -62,10 +62,12 @@ PredictionSchemeMethod GetPredictionMethodFromOptions( int att_id, const EncoderOptions &options) { const int pred_type = options.GetAttributeInt(att_id, "prediction_scheme", -1); - if (pred_type == -1) + if (pred_type == -1) { return PREDICTION_UNDEFINED; - if (pred_type < 0 || pred_type >= NUM_PREDICTION_SCHEMES) + } + if (pred_type < 0 || pred_type >= NUM_PREDICTION_SCHEMES) { return PREDICTION_NONE; + } return static_cast<PredictionSchemeMethod>(pred_type); } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h index 4cc40010773..40a7683aa0d 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h @@ -86,8 +86,9 @@ CreatePredictionSchemeForEncoder(PredictionSchemeMethod method, int att_id, if (method == PREDICTION_UNDEFINED) { method = SelectPredictionMethod(att_id, encoder); } - if (method == PREDICTION_NONE) + if (method == PREDICTION_NONE) { return nullptr; // No prediction is used. + } if (encoder->GetGeometryType() == TRIANGULAR_MESH) { // Cast the encoder to mesh encoder. This is not necessarily safe if there // is some other encoder decides to use TRIANGULAR_MESH as the return type, @@ -100,8 +101,9 @@ CreatePredictionSchemeForEncoder(PredictionSchemeMethod method, int att_id, MeshEncoder, PredictionSchemeEncoder<DataTypeT, TransformT>, MeshPredictionSchemeEncoderFactory<DataTypeT>>( mesh_encoder, method, att_id, transform, kDracoMeshBitstreamVersion); - if (ret) + if (ret) { return ret; + } // Otherwise try to create another prediction scheme. } // Create delta encoder. diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h index ab64bce7114..ab64bce7114 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoding_transform.h index 0929492aaec..0929492aaec 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoding_transform.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_factory.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_factory.h index 9fce686ae41..b36c4c8a273 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_factory.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_factory.h @@ -61,8 +61,9 @@ std::unique_ptr<PredictionSchemeT> CreateMeshPredictionScheme( &encoding_data->vertex_to_encoded_attribute_value_index_map); MeshPredictionSchemeFactoryT factory; auto ret = factory(method, att, transform, md, bitstream_version); - if (ret) + if (ret) { return ret; + } } else { typedef MeshPredictionSchemeData<CornerTable> MeshData; MeshData md; @@ -71,8 +72,9 @@ std::unique_ptr<PredictionSchemeT> CreateMeshPredictionScheme( &encoding_data->vertex_to_encoded_attribute_value_index_map); MeshPredictionSchemeFactoryT factory; auto ret = factory(method, att, transform, md, bitstream_version); - if (ret) + if (ret) { return ret; + } } } return nullptr; diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h index c9b3706930f..c9b3706930f 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h index 14ecb84654b..5a6c7c2dd45 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h @@ -44,18 +44,23 @@ class PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform bool DecodeTransformData(DecoderBuffer *buffer) { DataTypeT max_quantized_value, center_value; - if (!buffer->Decode(&max_quantized_value)) + if (!buffer->Decode(&max_quantized_value)) { return false; - if (!buffer->Decode(¢er_value)) + } + if (!buffer->Decode(¢er_value)) { return false; + } (void)center_value; - if (!this->set_max_quantized_value(max_quantized_value)) + if (!this->set_max_quantized_value(max_quantized_value)) { return false; + } // Account for reading wrong values, e.g., due to fuzzing. - if (this->quantization_bits() < 2) + if (this->quantization_bits() < 2) { return false; - if (this->quantization_bits() > 30) + } + if (this->quantization_bits() > 30) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_encoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_encoding_transform.h index 0dc96967b10..0dc96967b10 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_encoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_encoding_transform.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_base.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_base.h index 981077294f8..4a1e3a67b83 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_base.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_base.h @@ -90,8 +90,9 @@ class PredictionSchemeNormalOctahedronCanonicalizedTransformBase } bool IsInBottomLeft(const Point2 &p) const { - if (p[0] == 0 && p[1] == 0) + if (p[0] == 0 && p[1] == 0) { return true; + } return (p[0] < 0 && p[1] <= 0); } }; diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h index dbb788a33e0..a1bc4a327ac 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h @@ -18,13 +18,12 @@ #include <cmath> -#include "draco/draco_features.h" - #include "draco/compression/attributes/normal_compression_utils.h" #include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_base.h" #include "draco/core/decoder_buffer.h" #include "draco/core/macros.h" #include "draco/core/vector_d.h" +#include "draco/draco_features.h" namespace draco { @@ -45,11 +44,13 @@ class PredictionSchemeNormalOctahedronDecodingTransform void Init(int num_components) {} bool DecodeTransformData(DecoderBuffer *buffer) { DataTypeT max_quantized_value, center_value; - if (!buffer->Decode(&max_quantized_value)) + if (!buffer->Decode(&max_quantized_value)) { return false; + } if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { - if (!buffer->Decode(¢er_value)) + if (!buffer->Decode(¢er_value)) { return false; + } } (void)center_value; return this->set_max_quantized_value(max_quantized_value); diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_encoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_encoding_transform.h index 4abfef66903..4abfef66903 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_encoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_encoding_transform.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_base.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_base.h index ff71fe86fdf..c9dd7d67bf4 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_base.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_base.h @@ -60,8 +60,9 @@ class PredictionSchemeNormalOctahedronTransformBase { protected: inline bool set_max_quantized_value(DataTypeT max_quantized_value) { - if (max_quantized_value % 2 == 0) + if (max_quantized_value % 2 == 0) { return false; + } int q = MostSignificantBit(max_quantized_value) + 1; return octahedron_tool_box_.SetQuantizationBits(q); } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h index bd40df8d2f9..0a14d0d9ba4 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h @@ -39,25 +39,30 @@ class PredictionSchemeWrapDecodingTransform predicted_vals = this->ClampPredictedValue(predicted_vals); for (int i = 0; i < this->num_components(); ++i) { out_original_vals[i] = predicted_vals[i] + corr_vals[i]; - if (out_original_vals[i] > this->max_value()) + if (out_original_vals[i] > this->max_value()) { out_original_vals[i] -= this->max_dif(); - else if (out_original_vals[i] < this->min_value()) + } else if (out_original_vals[i] < this->min_value()) { out_original_vals[i] += this->max_dif(); + } } } bool DecodeTransformData(DecoderBuffer *buffer) { DataTypeT min_value, max_value; - if (!buffer->Decode(&min_value)) + if (!buffer->Decode(&min_value)) { return false; - if (!buffer->Decode(&max_value)) + } + if (!buffer->Decode(&max_value)) { return false; - if (min_value > max_value) + } + if (min_value > max_value) { return false; + } this->set_min_value(min_value); this->set_max_value(max_value); - if (!this->InitCorrectionBounds()) + if (!this->InitCorrectionBounds()) { return false; + } return true; } }; diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_encoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_encoding_transform.h index 8cd241f2e0a..1f5e8b13584 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_encoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_encoding_transform.h @@ -32,15 +32,17 @@ class PredictionSchemeWrapEncodingTransform void Init(const DataTypeT *orig_data, int size, int num_components) { PredictionSchemeWrapTransformBase<DataTypeT>::Init(num_components); // Go over the original values and compute the bounds. - if (size == 0) + if (size == 0) { return; + } DataTypeT min_value = orig_data[0]; DataTypeT max_value = min_value; for (int i = 1; i < size; ++i) { - if (orig_data[i] < min_value) + if (orig_data[i] < min_value) { min_value = orig_data[i]; - else if (orig_data[i] > max_value) + } else if (orig_data[i] > max_value) { max_value = orig_data[i]; + } } this->set_min_value(min_value); this->set_max_value(max_value); @@ -58,10 +60,11 @@ class PredictionSchemeWrapEncodingTransform out_corr_vals[i] = original_vals[i] - predicted_vals[i]; // Wrap around if needed. DataTypeT &corr_val = out_corr_vals[i]; - if (corr_val < this->min_correction()) + if (corr_val < this->min_correction()) { corr_val += this->max_dif(); - else if (corr_val > this->max_correction()) + } else if (corr_val > this->max_correction()) { corr_val -= this->max_dif(); + } } } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h index cf522269f1f..26f61fbaf6a 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h @@ -15,6 +15,7 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_WRAP_TRANSFORM_BASE_H_ #define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_WRAP_TRANSFORM_BASE_H_ +#include <limits> #include <vector> #include "draco/compression/config/compression_shared.h" @@ -61,12 +62,13 @@ class PredictionSchemeWrapTransformBase { inline const DataTypeT *ClampPredictedValue( const DataTypeT *predicted_val) const { for (int i = 0; i < this->num_components(); ++i) { - if (predicted_val[i] > max_value_) + if (predicted_val[i] > max_value_) { clamped_value_[i] = max_value_; - else if (predicted_val[i] < min_value_) + } else if (predicted_val[i] < min_value_) { clamped_value_[i] = min_value_; - else + } else { clamped_value_[i] = predicted_val[i]; + } } return &clamped_value_[0]; } @@ -81,13 +83,15 @@ class PredictionSchemeWrapTransformBase { bool InitCorrectionBounds() { const int64_t dif = static_cast<int64_t>(max_value_) - static_cast<int64_t>(min_value_); - if (dif < 0 || dif >= std::numeric_limits<DataTypeT>::max()) + if (dif < 0 || dif >= std::numeric_limits<DataTypeT>::max()) { return false; + } max_dif_ = 1 + static_cast<DataTypeT>(dif); max_correction_ = max_dif_ / 2; min_correction_ = -max_correction_; - if ((max_dif_ & 1) == 0) + if ((max_dif_ & 1) == 0) { max_correction_ -= 1; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoder.cc index 9e33cef3428..b4ba24f2d31 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoder.cc @@ -36,10 +36,13 @@ bool SequentialAttributeDecoder::InitializeStandalone( bool SequentialAttributeDecoder::DecodePortableAttribute( const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { - if (attribute_->num_components() <= 0 || !attribute_->Reset(point_ids.size())) + if (attribute_->num_components() <= 0 || + !attribute_->Reset(point_ids.size())) { return false; - if (!DecodeValues(point_ids, in_buffer)) + } + if (!DecodeValues(point_ids, in_buffer)) { return false; + } return true; } @@ -74,8 +77,9 @@ bool SequentialAttributeDecoder::InitPredictionScheme( for (int i = 0; i < ps->GetNumParentAttributes(); ++i) { const int att_id = decoder_->point_cloud()->GetNamedAttributeId( ps->GetParentAttributeType(i)); - if (att_id == -1) + if (att_id == -1) { return false; // Requested attribute does not exist. + } #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { if (!ps->SetParentAttribute(decoder_->point_cloud()->attribute(att_id))) { @@ -102,8 +106,9 @@ bool SequentialAttributeDecoder::DecodeValues( int out_byte_pos = 0; // Decode raw attribute values in their original format. for (int i = 0; i < num_values; ++i) { - if (!in_buffer->Decode(value_data, entry_size)) + if (!in_buffer->Decode(value_data, entry_size)) { return false; + } attribute_->buffer()->Write(out_byte_pos, value_data, entry_size); out_byte_pos += entry_size; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoder.h index 721a587fc2a..d48119465a9 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoder.h @@ -15,10 +15,9 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_ATTRIBUTE_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_ATTRIBUTE_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h" #include "draco/compression/point_cloud/point_cloud_decoder.h" +#include "draco/draco_features.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc index 2676eb7905c..0e5e26bcaa2 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc @@ -27,36 +27,42 @@ SequentialAttributeDecodersController::SequentialAttributeDecodersController( bool SequentialAttributeDecodersController::DecodeAttributesDecoderData( DecoderBuffer *buffer) { - if (!AttributesDecoder::DecodeAttributesDecoderData(buffer)) + if (!AttributesDecoder::DecodeAttributesDecoderData(buffer)) { return false; + } // Decode unique ids of all sequential encoders and create them. const int32_t num_attributes = GetNumAttributes(); sequential_decoders_.resize(num_attributes); for (int i = 0; i < num_attributes; ++i) { uint8_t decoder_type; - if (!buffer->Decode(&decoder_type)) + if (!buffer->Decode(&decoder_type)) { return false; + } // Create the decoder from the id. sequential_decoders_[i] = CreateSequentialDecoder(decoder_type); - if (!sequential_decoders_[i]) + if (!sequential_decoders_[i]) { return false; - if (!sequential_decoders_[i]->Init(GetDecoder(), GetAttributeId(i))) + } + if (!sequential_decoders_[i]->Init(GetDecoder(), GetAttributeId(i))) { return false; + } } return true; } bool SequentialAttributeDecodersController::DecodeAttributes( DecoderBuffer *buffer) { - if (!sequencer_ || !sequencer_->GenerateSequence(&point_ids_)) + if (!sequencer_ || !sequencer_->GenerateSequence(&point_ids_)) { return false; + } // Initialize point to attribute value mapping for all decoded attributes. const int32_t num_attributes = GetNumAttributes(); for (int i = 0; i < num_attributes; ++i) { PointAttribute *const pa = GetDecoder()->point_cloud()->attribute(GetAttributeId(i)); - if (!sequencer_->UpdatePointToAttributeIndexMapping(pa)) + if (!sequencer_->UpdatePointToAttributeIndexMapping(pa)) { return false; + } } return AttributesDecoder::DecodeAttributes(buffer); } @@ -66,8 +72,9 @@ bool SequentialAttributeDecodersController::DecodePortableAttributes( const int32_t num_attributes = GetNumAttributes(); for (int i = 0; i < num_attributes; ++i) { if (!sequential_decoders_[i]->DecodePortableAttribute(point_ids_, - in_buffer)) + in_buffer)) { return false; + } } return true; } @@ -77,8 +84,9 @@ bool SequentialAttributeDecodersController:: const int32_t num_attributes = GetNumAttributes(); for (int i = 0; i < num_attributes; ++i) { if (!sequential_decoders_[i]->DecodeDataNeededByPortableTransform( - point_ids_, in_buffer)) + point_ids_, in_buffer)) { return false; + } } return true; } @@ -106,8 +114,9 @@ bool SequentialAttributeDecodersController:: } } if (!sequential_decoders_[i]->TransformAttributeToOriginalFormat( - point_ids_)) + point_ids_)) { return false; + } } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.h b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoders_controller.h index 9fd5e490741..abc1f368523 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_decoders_controller.h @@ -37,8 +37,9 @@ class SequentialAttributeDecodersController : public AttributesDecoder { const PointAttribute *GetPortableAttribute( int32_t point_attribute_id) override { const int32_t loc_id = GetLocalIdForPointAttribute(point_attribute_id); - if (loc_id < 0) + if (loc_id < 0) { return nullptr; + } return sequential_decoders_[loc_id]->GetPortableAttribute(); } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoder.cc index 95547c005e7..6bde3eeb3ba 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoder.cc @@ -46,8 +46,9 @@ bool SequentialAttributeEncoder::TransformAttributeToPortableFormat( bool SequentialAttributeEncoder::EncodePortableAttribute( const std::vector<PointIndex> &point_ids, EncoderBuffer *out_buffer) { // Lossless encoding of the input values. - if (!EncodeValues(point_ids, out_buffer)) + if (!EncodeValues(point_ids, out_buffer)) { return false; + } return true; } @@ -80,8 +81,9 @@ bool SequentialAttributeEncoder::InitPredictionScheme( for (int i = 0; i < ps->GetNumParentAttributes(); ++i) { const int att_id = encoder_->point_cloud()->GetNamedAttributeId( ps->GetParentAttributeType(i)); - if (att_id == -1) + if (att_id == -1) { return false; // Requested attribute does not exist. + } parent_attributes_.push_back(att_id); encoder_->MarkParentAttribute(att_id); } @@ -93,10 +95,12 @@ bool SequentialAttributeEncoder::SetPredictionSchemeParentAttributes( for (int i = 0; i < ps->GetNumParentAttributes(); ++i) { const int att_id = encoder_->point_cloud()->GetNamedAttributeId( ps->GetParentAttributeType(i)); - if (att_id == -1) + if (att_id == -1) { return false; // Requested attribute does not exist. - if (!ps->SetParentAttribute(encoder_->GetPortableAttribute(att_id))) + } + if (!ps->SetParentAttribute(encoder_->GetPortableAttribute(att_id))) { return false; + } } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoder.h index 540ba947077..00f62db8959 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoder.h @@ -64,8 +64,9 @@ class SequentialAttributeEncoder { int GetParentAttributeId(int i) const { return parent_attributes_[i]; } const PointAttribute *GetPortableAttribute() const { - if (portable_attribute_ != nullptr) + if (portable_attribute_ != nullptr) { return portable_attribute_.get(); + } return attribute(); } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc index b40cef842ae..521935c1e99 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc @@ -31,23 +31,27 @@ SequentialAttributeEncodersController::SequentialAttributeEncodersController( bool SequentialAttributeEncodersController::Init(PointCloudEncoder *encoder, const PointCloud *pc) { - if (!AttributesEncoder::Init(encoder, pc)) + if (!AttributesEncoder::Init(encoder, pc)) { return false; - if (!CreateSequentialEncoders()) + } + if (!CreateSequentialEncoders()) { return false; + } // Initialize all value encoders. for (uint32_t i = 0; i < num_attributes(); ++i) { const int32_t att_id = GetAttributeId(i); - if (!sequential_encoders_[i]->Init(encoder, att_id)) + if (!sequential_encoders_[i]->Init(encoder, att_id)) { return false; + } } return true; } bool SequentialAttributeEncodersController::EncodeAttributesEncoderData( EncoderBuffer *out_buffer) { - if (!AttributesEncoder::EncodeAttributesEncoderData(out_buffer)) + if (!AttributesEncoder::EncodeAttributesEncoderData(out_buffer)) { return false; + } // Encode a unique id of every sequential encoder. for (uint32_t i = 0; i < sequential_encoders_.size(); ++i) { out_buffer->Encode(sequential_encoders_[i]->GetUniqueId()); @@ -57,8 +61,9 @@ bool SequentialAttributeEncodersController::EncodeAttributesEncoderData( bool SequentialAttributeEncodersController::EncodeAttributes( EncoderBuffer *buffer) { - if (!sequencer_ || !sequencer_->GenerateSequence(&point_ids_)) + if (!sequencer_ || !sequencer_->GenerateSequence(&point_ids_)) { return false; + } return AttributesEncoder::EncodeAttributes(buffer); } @@ -66,8 +71,9 @@ bool SequentialAttributeEncodersController:: TransformAttributesToPortableFormat() { for (uint32_t i = 0; i < sequential_encoders_.size(); ++i) { if (!sequential_encoders_[i]->TransformAttributeToPortableFormat( - point_ids_)) + point_ids_)) { return false; + } } return true; } @@ -76,8 +82,9 @@ bool SequentialAttributeEncodersController::EncodePortableAttributes( EncoderBuffer *out_buffer) { for (uint32_t i = 0; i < sequential_encoders_.size(); ++i) { if (!sequential_encoders_[i]->EncodePortableAttribute(point_ids_, - out_buffer)) + out_buffer)) { return false; + } } return true; } @@ -86,8 +93,9 @@ bool SequentialAttributeEncodersController:: EncodeDataNeededByPortableTransforms(EncoderBuffer *out_buffer) { for (uint32_t i = 0; i < sequential_encoders_.size(); ++i) { if (!sequential_encoders_[i]->EncodeDataNeededByPortableTransform( - out_buffer)) + out_buffer)) { return false; + } } return true; } @@ -96,11 +104,13 @@ bool SequentialAttributeEncodersController::CreateSequentialEncoders() { sequential_encoders_.resize(num_attributes()); for (uint32_t i = 0; i < num_attributes(); ++i) { sequential_encoders_[i] = CreateSequentialEncoder(i); - if (sequential_encoders_[i] == nullptr) + if (sequential_encoders_[i] == nullptr) { return false; + } if (i < sequential_encoder_marked_as_parent_.size()) { - if (sequential_encoder_marked_as_parent_[i]) + if (sequential_encoder_marked_as_parent_[i]) { sequential_encoders_[i]->MarkParentAttribute(); + } } } return true; diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.h b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.h index d5574abef8d..13c2704ec0a 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.h @@ -42,23 +42,26 @@ class SequentialAttributeEncodersController : public AttributesEncoder { int NumParentAttributes(int32_t point_attribute_id) const override { const int32_t loc_id = GetLocalIdForPointAttribute(point_attribute_id); - if (loc_id < 0) + if (loc_id < 0) { return 0; + } return sequential_encoders_[loc_id]->NumParentAttributes(); } int GetParentAttributeId(int32_t point_attribute_id, int32_t parent_i) const override { const int32_t loc_id = GetLocalIdForPointAttribute(point_attribute_id); - if (loc_id < 0) + if (loc_id < 0) { return -1; + } return sequential_encoders_[loc_id]->GetParentAttributeId(parent_i); } bool MarkParentAttribute(int32_t point_attribute_id) override { const int32_t loc_id = GetLocalIdForPointAttribute(point_attribute_id); - if (loc_id < 0) + if (loc_id < 0) { return false; + } // Mark the attribute encoder as parent (even when if it is not created // yet). if (sequential_encoder_marked_as_parent_.size() <= loc_id) { @@ -66,8 +69,9 @@ class SequentialAttributeEncodersController : public AttributesEncoder { } sequential_encoder_marked_as_parent_[loc_id] = true; - if (sequential_encoders_.size() <= loc_id) + if (sequential_encoders_.size() <= loc_id) { return true; // Sequential encoders not generated yet. + } sequential_encoders_[loc_id]->MarkParentAttribute(); return true; } @@ -75,8 +79,9 @@ class SequentialAttributeEncodersController : public AttributesEncoder { const PointAttribute *GetPortableAttribute( int32_t point_attribute_id) override { const int32_t loc_id = GetLocalIdForPointAttribute(point_attribute_id); - if (loc_id < 0) + if (loc_id < 0) { return nullptr; + } return sequential_encoders_[loc_id]->GetPortableAttribute(); } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc index 8d9210af912..d01fb26aad4 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc @@ -24,8 +24,9 @@ SequentialIntegerAttributeDecoder::SequentialIntegerAttributeDecoder() {} bool SequentialIntegerAttributeDecoder::Init(PointCloudDecoder *decoder, int attribute_id) { - if (!SequentialAttributeDecoder::Init(decoder, attribute_id)) + if (!SequentialAttributeDecoder::Init(decoder, attribute_id)) { return false; + } return true; } @@ -33,8 +34,9 @@ bool SequentialIntegerAttributeDecoder::TransformAttributeToOriginalFormat( const std::vector<PointIndex> &point_ids) { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder() && - decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) + decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { return true; // Don't revert the transform here for older files. + } #endif return StoreValues(static_cast<uint32_t>(point_ids.size())); } @@ -43,30 +45,37 @@ bool SequentialIntegerAttributeDecoder::DecodeValues( const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { // Decode prediction scheme. int8_t prediction_scheme_method; - in_buffer->Decode(&prediction_scheme_method); + if (!in_buffer->Decode(&prediction_scheme_method)) { + return false; + } if (prediction_scheme_method != PREDICTION_NONE) { int8_t prediction_transform_type; - in_buffer->Decode(&prediction_transform_type); + if (!in_buffer->Decode(&prediction_transform_type)) { + return false; + } prediction_scheme_ = CreateIntPredictionScheme( static_cast<PredictionSchemeMethod>(prediction_scheme_method), static_cast<PredictionSchemeTransformType>(prediction_transform_type)); } if (prediction_scheme_) { - if (!InitPredictionScheme(prediction_scheme_.get())) + if (!InitPredictionScheme(prediction_scheme_.get())) { return false; + } } - if (!DecodeIntegerValues(point_ids, in_buffer)) + if (!DecodeIntegerValues(point_ids, in_buffer)) { return false; + } #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED const int32_t num_values = static_cast<uint32_t>(point_ids.size()); if (decoder() && decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { // For older files, revert the transform right after we decode the data. - if (!StoreValues(num_values)) + if (!StoreValues(num_values)) { return false; + } } #endif return true; @@ -76,8 +85,9 @@ std::unique_ptr<PredictionSchemeTypedDecoderInterface<int32_t>> SequentialIntegerAttributeDecoder::CreateIntPredictionScheme( PredictionSchemeMethod method, PredictionSchemeTransformType transform_type) { - if (transform_type != PREDICTION_TRANSFORM_WRAP) + if (transform_type != PREDICTION_TRANSFORM_WRAP) { return nullptr; // For now we support only wrap transform. + } return CreatePredictionSchemeForDecoder< int32_t, PredictionSchemeWrapDecodingTransform<int32_t>>( method, attribute_id(), decoder()); @@ -86,44 +96,55 @@ SequentialIntegerAttributeDecoder::CreateIntPredictionScheme( bool SequentialIntegerAttributeDecoder::DecodeIntegerValues( const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { const int num_components = GetNumValueComponents(); - if (num_components <= 0) + if (num_components <= 0) { return false; + } const size_t num_entries = point_ids.size(); const size_t num_values = num_entries * num_components; PreparePortableAttribute(static_cast<int>(num_entries), num_components); int32_t *const portable_attribute_data = GetPortableAttributeData(); - if (portable_attribute_data == nullptr) + if (portable_attribute_data == nullptr) { return false; + } uint8_t compressed; - if (!in_buffer->Decode(&compressed)) + if (!in_buffer->Decode(&compressed)) { return false; + } if (compressed > 0) { // Decode compressed values. if (!DecodeSymbols(static_cast<uint32_t>(num_values), num_components, in_buffer, - reinterpret_cast<uint32_t *>(portable_attribute_data))) + reinterpret_cast<uint32_t *>(portable_attribute_data))) { return false; + } } else { // Decode the integer data directly. // Get the number of bytes for a given entry. uint8_t num_bytes; - if (!in_buffer->Decode(&num_bytes)) + if (!in_buffer->Decode(&num_bytes)) { return false; + } if (num_bytes == DataTypeLength(DT_INT32)) { if (portable_attribute()->buffer()->data_size() < - sizeof(int32_t) * num_values) + sizeof(int32_t) * num_values) { return false; + } if (!in_buffer->Decode(portable_attribute_data, - sizeof(int32_t) * num_values)) + sizeof(int32_t) * num_values)) { return false; + } } else { - if (portable_attribute()->buffer()->data_size() < num_bytes * num_values) + if (portable_attribute()->buffer()->data_size() < + num_bytes * num_values) { return false; + } if (in_buffer->remaining_size() < - static_cast<int64_t>(num_bytes) * static_cast<int64_t>(num_values)) + static_cast<int64_t>(num_bytes) * static_cast<int64_t>(num_values)) { return false; + } for (size_t i = 0; i < num_values; ++i) { - in_buffer->Decode(portable_attribute_data + i, num_bytes); + if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) + return false; } } } @@ -138,8 +159,9 @@ bool SequentialIntegerAttributeDecoder::DecodeIntegerValues( // If the data was encoded with a prediction scheme, we must revert it. if (prediction_scheme_) { - if (!prediction_scheme_->DecodePredictionData(in_buffer)) + if (!prediction_scheme_->DecodePredictionData(in_buffer)) { return false; + } if (num_values > 0) { if (!prediction_scheme_->ComputeOriginalValues( diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.h index 150ae1f831f..ef48ed817a5 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.h @@ -15,10 +15,9 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_INTEGER_ATTRIBUTE_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_INTEGER_ATTRIBUTE_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/prediction_scheme_decoder.h" #include "draco/compression/attributes/sequential_attribute_decoder.h" +#include "draco/draco_features.h" namespace draco { @@ -56,8 +55,9 @@ class SequentialIntegerAttributeDecoder : public SequentialAttributeDecoder { void PreparePortableAttribute(int num_entries, int num_components); int32_t *GetPortableAttributeData() { - if (portable_attribute()->size() == 0) + if (portable_attribute()->size() == 0) { return nullptr; + } return reinterpret_cast<int32_t *>( portable_attribute()->GetAddress(AttributeValueIndex(0))); } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc index 0cae81d9f95..2889e0521a0 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc @@ -25,8 +25,9 @@ SequentialIntegerAttributeEncoder::SequentialIntegerAttributeEncoder() {} bool SequentialIntegerAttributeEncoder::Init(PointCloudEncoder *encoder, int attribute_id) { - if (!SequentialAttributeEncoder::Init(encoder, attribute_id)) + if (!SequentialAttributeEncoder::Init(encoder, attribute_id)) { return false; + } if (GetUniqueId() == SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER) { // When encoding integers, this encoder currently works only for integer // attributes up to 32 bits. @@ -58,11 +59,13 @@ bool SequentialIntegerAttributeEncoder::Init(PointCloudEncoder *encoder, bool SequentialIntegerAttributeEncoder::TransformAttributeToPortableFormat( const std::vector<PointIndex> &point_ids) { if (encoder()) { - if (!PrepareValues(point_ids, encoder()->point_cloud()->num_points())) + if (!PrepareValues(point_ids, encoder()->point_cloud()->num_points())) { return false; + } } else { - if (!PrepareValues(point_ids, 0)) + if (!PrepareValues(point_ids, 0)) { return false; + } } // Update point to attribute mapping with the portable attribute if the @@ -100,8 +103,9 @@ bool SequentialIntegerAttributeEncoder::EncodeValues( const std::vector<PointIndex> &point_ids, EncoderBuffer *out_buffer) { // Initialize general quantization data. const PointAttribute *const attrib = attribute(); - if (attrib->size() == 0) + if (attrib->size() == 0) { return true; + } int8_t prediction_scheme_method = PREDICTION_NONE; if (prediction_scheme_) { @@ -202,8 +206,9 @@ bool SequentialIntegerAttributeEncoder::PrepareValues( for (PointIndex pi : point_ids) { const AttributeValueIndex att_id = attrib->mapped_index(pi); if (!attrib->ConvertValue<int32_t>(att_id, - portable_attribute_data + dst_index)) + portable_attribute_data + dst_index)) { return false; + } dst_index += num_components; } return true; diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_encoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.h index c1d6222ef40..c1d6222ef40 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc index 2f208d50dbe..017344393dc 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/compression/attributes/sequential_normal_attribute_decoder.h" + #include "draco/attributes/attribute_octahedron_transform.h" #include "draco/compression/attributes/normal_compression_utils.h" @@ -26,11 +27,13 @@ bool SequentialNormalAttributeDecoder::Init(PointCloudDecoder *decoder, if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) return false; // Currently, this encoder works only for 3-component normal vectors. - if (attribute()->num_components() != 3) + if (attribute()->num_components() != 3) { return false; + } // Also the data type must be DT_FLOAT32. - if (attribute()->data_type() != DT_FLOAT32) + if (attribute()->data_type() != DT_FLOAT32) { return false; + } return true; } @@ -39,8 +42,9 @@ bool SequentialNormalAttributeDecoder::DecodeIntegerValues( #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { uint8_t quantization_bits; - if (!in_buffer->Decode(&quantization_bits)) + if (!in_buffer->Decode(&quantization_bits)) { return false; + } quantization_bits_ = quantization_bits; } #endif @@ -53,8 +57,9 @@ bool SequentialNormalAttributeDecoder::DecodeDataNeededByPortableTransform( if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) { // For newer file version, decode attribute transform data here. uint8_t quantization_bits; - if (!in_buffer->Decode(&quantization_bits)) + if (!in_buffer->Decode(&quantization_bits)) { return false; + } quantization_bits_ = quantization_bits; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h index d6439fcd6cf..860eacb4c84 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h @@ -15,12 +15,11 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h" #include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h" #include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h" #include "draco/compression/attributes/sequential_integer_attribute_decoder.h" +#include "draco/draco_features.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc index af207a87111..23fa8bb7b39 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/compression/attributes/sequential_normal_attribute_encoder.h" + #include "draco/compression/attributes/normal_compression_utils.h" namespace draco { @@ -22,14 +23,16 @@ bool SequentialNormalAttributeEncoder::Init(PointCloudEncoder *encoder, if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id)) return false; // Currently this encoder works only for 3-component normal vectors. - if (attribute()->num_components() != 3) + if (attribute()->num_components() != 3) { return false; + } // Initialize AttributeOctahedronTransform. const int quantization_bits = encoder->options()->GetAttributeInt( attribute_id, "quantization_bits", -1); - if (quantization_bits < 1) + if (quantization_bits < 1) { return false; + } attribute_octahedron_transform_.SetParameters(quantization_bits); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_encoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.h index 53705c5982b..53705c5982b 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_normal_attribute_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc index dfaf2edbe8e..bf925c4a595 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc @@ -24,13 +24,15 @@ SequentialQuantizationAttributeDecoder::SequentialQuantizationAttributeDecoder() bool SequentialQuantizationAttributeDecoder::Init(PointCloudDecoder *decoder, int attribute_id) { - if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) + if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) { return false; + } const PointAttribute *const attribute = decoder->point_cloud()->attribute(attribute_id); // Currently we can quantize only floating point arguments. - if (attribute->data_type() != DT_FLOAT32) + if (attribute->data_type() != DT_FLOAT32) { return false; + } return true; } @@ -38,8 +40,9 @@ bool SequentialQuantizationAttributeDecoder::DecodeIntegerValues( const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0) && - !DecodeQuantizedDataInfo()) + !DecodeQuantizedDataInfo()) { return false; + } #endif return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids, in_buffer); @@ -50,8 +53,9 @@ bool SequentialQuantizationAttributeDecoder:: const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) { // Decode quantization data here only for files with bitstream version 2.0+ - if (!DecodeQuantizedDataInfo()) + if (!DecodeQuantizedDataInfo()) { return false; + } } // Store the decoded transform data in portable attribute; @@ -69,14 +73,17 @@ bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() { const int num_components = attribute()->num_components(); min_value_ = std::unique_ptr<float[]>(new float[num_components]); if (!decoder()->buffer()->Decode(min_value_.get(), - sizeof(float) * num_components)) + sizeof(float) * num_components)) { return false; - if (!decoder()->buffer()->Decode(&max_value_dif_)) + } + if (!decoder()->buffer()->Decode(&max_value_dif_)) { return false; + } uint8_t quantization_bits; if (!decoder()->buffer()->Decode(&quantization_bits) || - quantization_bits > 31) + quantization_bits > 31) { return false; + } quantization_bits_ = quantization_bits; return true; } @@ -92,8 +99,9 @@ bool SequentialQuantizationAttributeDecoder::DequantizeValues( int quant_val_id = 0; int out_byte_pos = 0; Dequantizer dequantizer; - if (!dequantizer.Init(max_value_dif_, max_quantized_value)) + if (!dequantizer.Init(max_value_dif_, max_quantized_value)) { return false; + } const int32_t *const portable_attribute_data = GetPortableAttributeData(); for (uint32_t i = 0; i < num_values; ++i) { for (int c = 0; c < num_components; ++c) { diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h index 27d88be72bd..c0b7637a750 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h @@ -15,9 +15,8 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/attributes/sequential_integer_attribute_decoder.h" +#include "draco/draco_features.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc index 9110450061c..cd5b8b141e0 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc @@ -23,19 +23,22 @@ SequentialQuantizationAttributeEncoder:: bool SequentialQuantizationAttributeEncoder::Init(PointCloudEncoder *encoder, int attribute_id) { - if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id)) + if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id)) { return false; + } // This encoder currently works only for floating point attributes. const PointAttribute *const attribute = encoder->point_cloud()->attribute(attribute_id); - if (attribute->data_type() != DT_FLOAT32) + if (attribute->data_type() != DT_FLOAT32) { return false; + } // Initialize AttributeQuantizationTransform. const int quantization_bits = encoder->options()->GetAttributeInt( attribute_id, "quantization_bits", -1); - if (quantization_bits < 1) + if (quantization_bits < 1) { return false; + } if (encoder->options()->IsAttributeOptionSet(attribute_id, "quantization_origin") && encoder->options()->IsAttributeOptionSet(attribute_id, @@ -52,8 +55,10 @@ bool SequentialQuantizationAttributeEncoder::Init(PointCloudEncoder *encoder, attribute->num_components(), range); } else { // Compute quantization settings from the attribute values. - attribute_quantization_transform_.ComputeParameters(*attribute, - quantization_bits); + if (!attribute_quantization_transform_.ComputeParameters( + *attribute, quantization_bits)) { + return false; + } } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_encoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.h index e9762bdd6d0..e9762bdd6d0 100644 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_quantization_attribute_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_coding_shared.h b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_coding_shared.h index faacbd5b940..faacbd5b940 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_coding_shared.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_coding_shared.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.cc index 87ff7007a3d..056842c4a99 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.cc @@ -26,15 +26,18 @@ bool AdaptiveRAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) { Clear(); uint32_t size_in_bytes; - if (!source_buffer->Decode(&size_in_bytes)) + if (!source_buffer->Decode(&size_in_bytes)) { return false; - if (size_in_bytes > source_buffer->remaining_size()) + } + if (size_in_bytes > source_buffer->remaining_size()) { return false; + } if (ans_read_init(&ans_decoder_, reinterpret_cast<uint8_t *>( const_cast<char *>(source_buffer->data_head())), - size_in_bytes) != 0) + size_in_bytes) != 0) { return false; + } source_buffer->Advance(size_in_bytes); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.h b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.h index a1ea011dd6a..a1ea011dd6a 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.cc index 5ce9dc388b8..5ce9dc388b8 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.h b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.h index 9b1832844ad..9b1832844ad 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/adaptive_rans_bit_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_decoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_decoder.cc index 515ea9b52ee..2abe3382a4c 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_decoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_decoder.cc @@ -23,19 +23,23 @@ DirectBitDecoder::~DirectBitDecoder() { Clear(); } bool DirectBitDecoder::StartDecoding(DecoderBuffer *source_buffer) { Clear(); uint32_t size_in_bytes; - if (!source_buffer->Decode(&size_in_bytes)) + if (!source_buffer->Decode(&size_in_bytes)) { return false; + } // Check that size_in_bytes is > 0 and a multiple of 4 as the encoder always // encodes 32 bit elements. - if (size_in_bytes == 0 || size_in_bytes & 0x3) + if (size_in_bytes == 0 || size_in_bytes & 0x3) { return false; - if (size_in_bytes > source_buffer->remaining_size()) + } + if (size_in_bytes > source_buffer->remaining_size()) { return false; + } const uint32_t num_32bit_elements = size_in_bytes / 4; bits_.resize(num_32bit_elements); - if (!source_buffer->Decode(bits_.data(), size_in_bytes)) + if (!source_buffer->Decode(bits_.data(), size_in_bytes)) { return false; + } pos_ = bits_.begin(); num_used_bits_ = 0; return true; diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_decoder.h b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_decoder.h index b9fbc2d6fed..b9fbc2d6fed 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_decoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_encoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_encoder.cc index d39143cf56a..d39143cf56a 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_encoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_encoder.h b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_encoder.h index 705b2ca93c2..705b2ca93c2 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/direct_bit_encoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/direct_bit_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/folded_integer_bit_decoder.h b/extern/draco/draco/src/draco/compression/bit_coders/folded_integer_bit_decoder.h index 9f8bedd1eb0..c14058b6569 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/folded_integer_bit_decoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/folded_integer_bit_decoder.h @@ -32,8 +32,9 @@ class FoldedBit32Decoder { // Sets |source_buffer| as the buffer to decode bits from. bool StartDecoding(DecoderBuffer *source_buffer) { for (int i = 0; i < 32; i++) { - if (!folded_number_decoders_[i].StartDecoding(source_buffer)) + if (!folded_number_decoders_[i].StartDecoding(source_buffer)) { return false; + } } return bit_decoder_.StartDecoding(source_buffer); } diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/folded_integer_bit_encoder.h b/extern/draco/draco/src/draco/compression/bit_coders/folded_integer_bit_encoder.h index 375b38a61fb..375b38a61fb 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/folded_integer_bit_encoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/folded_integer_bit_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_decoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_decoder.cc index 023e0dbc192..a9b8fb9e91e 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_decoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_decoder.cc @@ -27,30 +27,35 @@ RAnsBitDecoder::~RAnsBitDecoder() { Clear(); } bool RAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) { Clear(); - if (!source_buffer->Decode(&prob_zero_)) + if (!source_buffer->Decode(&prob_zero_)) { return false; + } uint32_t size_in_bytes; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (source_buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { - if (!source_buffer->Decode(&size_in_bytes)) + if (!source_buffer->Decode(&size_in_bytes)) { return false; + } } else #endif { - if (!DecodeVarint(&size_in_bytes, source_buffer)) + if (!DecodeVarint(&size_in_bytes, source_buffer)) { return false; + } } - if (size_in_bytes > source_buffer->remaining_size()) + if (size_in_bytes > source_buffer->remaining_size()) { return false; + } if (ans_read_init(&ans_decoder_, reinterpret_cast<uint8_t *>( const_cast<char *>(source_buffer->data_head())), - size_in_bytes) != 0) + size_in_bytes) != 0) { return false; + } source_buffer->Advance(size_in_bytes); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_decoder.h b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_decoder.h index 1fbf6a1324a..25d243eac16 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_decoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_decoder.h @@ -18,10 +18,9 @@ #include <vector> -#include "draco/draco_features.h" - #include "draco/compression/entropy/ans.h" #include "draco/core/decoder_buffer.h" +#include "draco/draco_features.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_encoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_encoder.cc index ea2972fe262..8d00ea35292 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_encoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_encoder.cc @@ -72,8 +72,9 @@ void RAnsBitEncoder::EncodeLeastSignificantBits32(int nbits, uint32_t value) { void RAnsBitEncoder::EndEncoding(EncoderBuffer *target_buffer) { uint64_t total = bit_counts_[1] + bit_counts_[0]; - if (total == 0) + if (total == 0) { total++; + } // The probability interval [0,1] is mapped to values of [0, 256]. However, // the coding scheme can not deal with probabilities of 0 or 1, which is why @@ -83,8 +84,9 @@ void RAnsBitEncoder::EndEncoding(EncoderBuffer *target_buffer) { ((bit_counts_[0] / static_cast<double>(total)) * 256.0) + 0.5); uint8_t zero_prob = 255; - if (zero_prob_raw < 255) + if (zero_prob_raw < 255) { zero_prob = static_cast<uint8_t>(zero_prob_raw); + } zero_prob += (zero_prob == 0); diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_encoder.h b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_encoder.h index 1993dd3d3c2..1993dd3d3c2 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_bit_encoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/rans_bit_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_decoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_decoder.cc index 6b35ae3f87f..8ed50ef92ec 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_decoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_decoder.cc @@ -6,12 +6,14 @@ namespace draco { bool SymbolBitDecoder::StartDecoding(DecoderBuffer *source_buffer) { uint32_t size; - if (!source_buffer->Decode(&size)) + if (!source_buffer->Decode(&size)) { return false; + } symbols_.resize(size); - if (!DecodeSymbols(size, 1, source_buffer, symbols_.data())) + if (!DecodeSymbols(size, 1, source_buffer, symbols_.data())) { return false; + } std::reverse(symbols_.begin(), symbols_.end()); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_decoder.h b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_decoder.h index 909d7174fb5..909d7174fb5 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_decoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_encoder.cc b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_encoder.cc index 83834236fa5..83834236fa5 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_encoder.cc +++ b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_encoder.h b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_encoder.h index 7f1570c1a7c..7f1570c1a7c 100644 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/symbol_bit_encoder.h +++ b/extern/draco/draco/src/draco/compression/bit_coders/symbol_bit_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/config/compression_shared.h b/extern/draco/draco/src/draco/compression/config/compression_shared.h index 5204fbc1f3e..40061d3cd48 100644 --- a/extern/draco/dracoenc/src/draco/compression/config/compression_shared.h +++ b/extern/draco/draco/src/draco/compression/config/compression_shared.h @@ -18,7 +18,6 @@ #include <stdint.h> #include "draco/core/macros.h" - #include "draco/draco_features.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/config/decoder_options.h b/extern/draco/draco/src/draco/compression/config/decoder_options.h index 3b3889993e2..3b3889993e2 100644 --- a/extern/draco/dracoenc/src/draco/compression/config/decoder_options.h +++ b/extern/draco/draco/src/draco/compression/config/decoder_options.h diff --git a/extern/draco/dracoenc/src/draco/compression/config/draco_options.h b/extern/draco/draco/src/draco/compression/config/draco_options.h index c77f5df4014..0d1247b2ad1 100644 --- a/extern/draco/dracoenc/src/draco/compression/config/draco_options.h +++ b/extern/draco/draco/src/draco/compression/config/draco_options.h @@ -159,8 +159,9 @@ int DracoOptions<AttributeKeyT>::GetAttributeInt(const AttributeKeyT &att_key, const std::string &name, int default_val) const { const Options *const att_options = FindAttributeOptions(att_key); - if (att_options && att_options->IsOptionSet(name)) + if (att_options && att_options->IsOptionSet(name)) { return att_options->GetInt(name, default_val); + } return global_options_.GetInt(name, default_val); } @@ -176,8 +177,9 @@ float DracoOptions<AttributeKeyT>::GetAttributeFloat( const AttributeKeyT &att_key, const std::string &name, float default_val) const { const Options *const att_options = FindAttributeOptions(att_key); - if (att_options && att_options->IsOptionSet(name)) + if (att_options && att_options->IsOptionSet(name)) { return att_options->GetFloat(name, default_val); + } return global_options_.GetFloat(name, default_val); } @@ -192,8 +194,9 @@ bool DracoOptions<AttributeKeyT>::GetAttributeBool(const AttributeKeyT &att_key, const std::string &name, bool default_val) const { const Options *const att_options = FindAttributeOptions(att_key); - if (att_options && att_options->IsOptionSet(name)) + if (att_options && att_options->IsOptionSet(name)) { return att_options->GetBool(name, default_val); + } return global_options_.GetBool(name, default_val); } @@ -210,8 +213,9 @@ bool DracoOptions<AttributeKeyT>::GetAttributeVector( const AttributeKey &att_key, const std::string &name, int num_dims, DataTypeT *val) const { const Options *const att_options = FindAttributeOptions(att_key); - if (att_options && att_options->IsOptionSet(name)) + if (att_options && att_options->IsOptionSet(name)) { return att_options->GetVector(name, num_dims, val); + } return global_options_.GetVector(name, num_dims, val); } @@ -227,8 +231,9 @@ template <typename AttributeKeyT> bool DracoOptions<AttributeKeyT>::IsAttributeOptionSet( const AttributeKey &att_key, const std::string &name) const { const Options *const att_options = FindAttributeOptions(att_key); - if (att_options) + if (att_options) { return att_options->IsOptionSet(name); + } return global_options_.IsOptionSet(name); } diff --git a/extern/draco/dracoenc/src/draco/compression/config/encoder_options.h b/extern/draco/draco/src/draco/compression/config/encoder_options.h index aacd58e0187..ed1b020683d 100644 --- a/extern/draco/dracoenc/src/draco/compression/config/encoder_options.h +++ b/extern/draco/draco/src/draco/compression/config/encoder_options.h @@ -15,11 +15,10 @@ #ifndef DRACO_COMPRESSION_CONFIG_ENCODER_OPTIONS_H_ #define DRACO_COMPRESSION_CONFIG_ENCODER_OPTIONS_H_ -#include "draco/draco_features.h" - #include "draco/attributes/geometry_attribute.h" #include "draco/compression/config/draco_options.h" #include "draco/compression/config/encoding_features.h" +#include "draco/draco_features.h" namespace draco { @@ -56,8 +55,9 @@ class EncoderOptionsBase : public DracoOptions<AttributeKeyT> { const int encoding_speed = this->GetGlobalInt("encoding_speed", -1); const int decoding_speed = this->GetGlobalInt("decoding_speed", -1); const int max_speed = std::max(encoding_speed, decoding_speed); - if (max_speed == -1) + if (max_speed == -1) { return 5; // Default value. + } return max_speed; } diff --git a/extern/draco/dracoenc/src/draco/compression/config/encoding_features.h b/extern/draco/draco/src/draco/compression/config/encoding_features.h index d6a8b7128a8..d6a8b7128a8 100644 --- a/extern/draco/dracoenc/src/draco/compression/config/encoding_features.h +++ b/extern/draco/draco/src/draco/compression/config/encoding_features.h diff --git a/extern/draco/dracoenc/src/draco/compression/decode.cc b/extern/draco/draco/src/draco/compression/decode.cc index ab70ef1ec60..ab70ef1ec60 100644 --- a/extern/draco/dracoenc/src/draco/compression/decode.cc +++ b/extern/draco/draco/src/draco/compression/decode.cc diff --git a/extern/draco/dracoenc/src/draco/compression/decode.h b/extern/draco/draco/src/draco/compression/decode.h index 0216d72586a..5f3fad26bb4 100644 --- a/extern/draco/dracoenc/src/draco/compression/decode.h +++ b/extern/draco/draco/src/draco/compression/decode.h @@ -15,12 +15,11 @@ #ifndef DRACO_COMPRESSION_DECODE_H_ #define DRACO_COMPRESSION_DECODE_H_ -#include "draco/draco_features.h" - #include "draco/compression/config/compression_shared.h" #include "draco/compression/config/decoder_options.h" #include "draco/core/decoder_buffer.h" #include "draco/core/status_or.h" +#include "draco/draco_features.h" #include "draco/mesh/mesh.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/encode.cc b/extern/draco/draco/src/draco/compression/encode.cc index 5de05ace81f..f380aec1591 100644 --- a/extern/draco/dracoenc/src/draco/compression/encode.cc +++ b/extern/draco/draco/src/draco/compression/encode.cc @@ -85,8 +85,9 @@ void Encoder::SetEncodingMethod(int encoding_method) { Status Encoder::SetAttributePredictionScheme(GeometryAttribute::Type type, int prediction_scheme_method) { Status status = CheckPredictionScheme(type, prediction_scheme_method); - if (!status.ok()) + if (!status.ok()) { return status; + } options().SetAttributeInt(type, "prediction_scheme", prediction_scheme_method); return status; diff --git a/extern/draco/dracoenc/src/draco/compression/encode.h b/extern/draco/draco/src/draco/compression/encode.h index bce8b34c238..bce8b34c238 100644 --- a/extern/draco/dracoenc/src/draco/compression/encode.h +++ b/extern/draco/draco/src/draco/compression/encode.h diff --git a/extern/draco/dracoenc/src/draco/compression/encode_base.h b/extern/draco/draco/src/draco/compression/encode_base.h index 451d970eb6f..0c63a972bf4 100644 --- a/extern/draco/dracoenc/src/draco/compression/encode_base.h +++ b/extern/draco/draco/src/draco/compression/encode_base.h @@ -68,24 +68,29 @@ class EncoderBase { Status CheckPredictionScheme(GeometryAttribute::Type att_type, int prediction_scheme) const { // Out of bound checks: - if (prediction_scheme < PREDICTION_NONE) + if (prediction_scheme < PREDICTION_NONE) { return Status(Status::DRACO_ERROR, "Invalid prediction scheme requested."); - if (prediction_scheme >= NUM_PREDICTION_SCHEMES) + } + if (prediction_scheme >= NUM_PREDICTION_SCHEMES) { return Status(Status::DRACO_ERROR, "Invalid prediction scheme requested."); + } // Deprecated prediction schemes: - if (prediction_scheme == MESH_PREDICTION_TEX_COORDS_DEPRECATED) + if (prediction_scheme == MESH_PREDICTION_TEX_COORDS_DEPRECATED) { return Status(Status::DRACO_ERROR, "MESH_PREDICTION_TEX_COORDS_DEPRECATED is deprecated."); - if (prediction_scheme == MESH_PREDICTION_MULTI_PARALLELOGRAM) + } + if (prediction_scheme == MESH_PREDICTION_MULTI_PARALLELOGRAM) { return Status(Status::DRACO_ERROR, "MESH_PREDICTION_MULTI_PARALLELOGRAM is deprecated."); + } // Attribute specific checks: if (prediction_scheme == MESH_PREDICTION_TEX_COORDS_PORTABLE) { - if (att_type != GeometryAttribute::TEX_COORD) + if (att_type != GeometryAttribute::TEX_COORD) { return Status(Status::DRACO_ERROR, "Invalid prediction scheme for attribute type."); + } } if (prediction_scheme == MESH_PREDICTION_GEOMETRIC_NORMAL) { if (att_type != GeometryAttribute::NORMAL) { diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/ans.h b/extern/draco/draco/src/draco/compression/entropy/ans.h index 310ae256667..c765256b96e 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/ans.h +++ b/extern/draco/draco/src/draco/compression/entropy/ans.h @@ -255,11 +255,12 @@ static inline void uabs_write(struct AnsCoder *ans, int val, AnsP8 p0) { ans->buf[ans->buf_offset++] = ans->state % DRACO_ANS_IO_BASE; ans->state /= DRACO_ANS_IO_BASE; } - if (!val) + if (!val) { ans->state = DRACO_ANS_DIV(ans->state * DRACO_ANS_P8_PRECISION, p0); - else + } else { ans->state = DRACO_ANS_DIV((ans->state + 1) * DRACO_ANS_P8_PRECISION + p - 1, p) - 1; + } } static inline int uabs_read(struct AnsDecoder *ans, AnsP8 p0) { @@ -276,10 +277,11 @@ static inline int uabs_read(struct AnsDecoder *ans, AnsP8 p0) { xp = sp / DRACO_ANS_P8_PRECISION; // s = xp1 - xp; s = (sp & 0xFF) >= p0; - if (UNPREDICTABLE(s)) + if (UNPREDICTABLE(s)) { ans->state = xp; - else + } else { ans->state = state - xp; + } return s; } @@ -297,29 +299,33 @@ static inline int uabs_read_bit(struct AnsDecoder *ans) { static inline int ans_read_init(struct AnsDecoder *const ans, const uint8_t *const buf, int offset) { unsigned x; - if (offset < 1) + if (offset < 1) { return 1; + } ans->buf = buf; x = buf[offset - 1] >> 6; if (x == 0) { ans->buf_offset = offset - 1; ans->state = buf[offset - 1] & 0x3F; } else if (x == 1) { - if (offset < 2) + if (offset < 2) { return 1; + } ans->buf_offset = offset - 2; ans->state = mem_get_le16(buf + offset - 2) & 0x3FFF; } else if (x == 2) { - if (offset < 3) + if (offset < 3) { return 1; + } ans->buf_offset = offset - 3; ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF; } else { return 1; } ans->state += DRACO_ANS_L_BASE; - if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE) + if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE) { return 1; + } return 0; } @@ -415,21 +421,24 @@ class RAnsDecoder { // error. inline int read_init(const uint8_t *const buf, int offset) { unsigned x; - if (offset < 1) + if (offset < 1) { return 1; + } ans_.buf = buf; x = buf[offset - 1] >> 6; if (x == 0) { ans_.buf_offset = offset - 1; ans_.state = buf[offset - 1] & 0x3F; } else if (x == 1) { - if (offset < 2) + if (offset < 2) { return 1; + } ans_.buf_offset = offset - 2; ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF; } else if (x == 2) { - if (offset < 3) + if (offset < 3) { return 1; + } ans_.buf_offset = offset - 3; ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF; } else if (x == 3) { @@ -439,8 +448,9 @@ class RAnsDecoder { return 1; } ans_.state += l_rans_base; - if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) + if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) { return 1; + } return 0; } diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_coding.h b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h index 0a68e29fe26..0a68e29fe26 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_coding.h +++ b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_decoder.h b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_decoder.h index 1b5f1c8b715..10cdc6781a0 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_decoder.h +++ b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_decoder.h @@ -15,12 +15,11 @@ #ifndef DRACO_COMPRESSION_ENTROPY_RANS_SYMBOL_DECODER_H_ #define DRACO_COMPRESSION_ENTROPY_RANS_SYMBOL_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/config/compression_shared.h" #include "draco/compression/entropy/rans_symbol_coding.h" #include "draco/core/decoder_buffer.h" #include "draco/core/varint_decoding.h" +#include "draco/draco_features.h" namespace draco { @@ -59,30 +58,35 @@ template <int unique_symbols_bit_length_t> bool RAnsSymbolDecoder<unique_symbols_bit_length_t>::Create( DecoderBuffer *buffer) { // Check that the DecoderBuffer version is set. - if (buffer->bitstream_version() == 0) + if (buffer->bitstream_version() == 0) { return false; - // Decode the number of alphabet symbols. + } + // Decode the number of alphabet symbols. #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!buffer->Decode(&num_symbols_)) + if (!buffer->Decode(&num_symbols_)) { return false; + } } else #endif { - if (!DecodeVarint(&num_symbols_, buffer)) + if (!DecodeVarint(&num_symbols_, buffer)) { return false; + } } probability_table_.resize(num_symbols_); - if (num_symbols_ == 0) + if (num_symbols_ == 0) { return true; + } // Decode the table. for (uint32_t i = 0; i < num_symbols_; ++i) { uint8_t prob_data = 0; // Decode the first byte and extract the number of extra bytes we need to // get, or the offset to the next symbol with non-zero probability. - if (!buffer->Decode(&prob_data)) + if (!buffer->Decode(&prob_data)) { return false; + } // Token is stored in the first two bits of the first byte. Values 0-2 are // used to indicate the number of extra bytes, and value 3 is a special // symbol used to denote run-length coding of zero probability entries. @@ -90,8 +94,9 @@ bool RAnsSymbolDecoder<unique_symbols_bit_length_t>::Create( const int token = prob_data & 3; if (token == 3) { const uint32_t offset = prob_data >> 2; - if (i + offset >= num_symbols_) + if (i + offset >= num_symbols_) { return false; + } // Set zero probability for all symbols in the specified range. for (uint32_t j = 0; j < offset + 1; ++j) { probability_table_[i + j] = 0; @@ -102,8 +107,9 @@ bool RAnsSymbolDecoder<unique_symbols_bit_length_t>::Create( uint32_t prob = prob_data >> 2; for (int b = 0; b < extra_bytes; ++b) { uint8_t eb; - if (!buffer->Decode(&eb)) + if (!buffer->Decode(&eb)) { return false; + } // Shift 8 bits for each extra byte and subtract 2 for the two first // bits. prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2); @@ -111,8 +117,9 @@ bool RAnsSymbolDecoder<unique_symbols_bit_length_t>::Create( probability_table_[i] = prob; } } - if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) + if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_)) { return false; + } return true; } @@ -123,23 +130,27 @@ bool RAnsSymbolDecoder<unique_symbols_bit_length_t>::StartDecoding( // Decode the number of bytes encoded by the encoder. #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!buffer->Decode(&bytes_encoded)) + if (!buffer->Decode(&bytes_encoded)) { return false; + } } else #endif { - if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) + if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer)) { return false; + } } - if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) + if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size())) { return false; + } const uint8_t *const data_head = reinterpret_cast<const uint8_t *>(buffer->data_head()); // Advance the buffer past the rANS data. buffer->Advance(bytes_encoded); - if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) + if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_encoder.h b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h index 4b0ed091af0..4e07ec87123 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_encoder.h +++ b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h @@ -91,8 +91,9 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create( int max_valid_symbol = 0; for (int i = 0; i < num_symbols; ++i) { total_freq += frequencies[i]; - if (frequencies[i] > 0) + if (frequencies[i] > 0) { max_valid_symbol = i; + } } num_symbols = max_valid_symbol + 1; num_symbols_ = num_symbols; @@ -111,8 +112,9 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create( // RAns probability in range of [1, rans_precision - 1]. uint32_t rans_prob = static_cast<uint32_t>(prob * rans_precision_d + 0.5f); - if (rans_prob == 0 && freq > 0) + if (rans_prob == 0 && freq > 0) { rans_prob = 1; + } probability_table_[i].prob = rans_prob; total_rans_prob += rans_prob; } @@ -140,25 +142,30 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create( for (int j = num_symbols - 1; j > 0; --j) { int symbol_id = sorted_probabilities[j]; if (probability_table_[symbol_id].prob <= 1) { - if (j == num_symbols - 1) + if (j == num_symbols - 1) { return false; // Most frequent symbol would be empty. + } break; } const int32_t new_prob = static_cast<int32_t>( floor(act_rel_error_d * static_cast<double>(probability_table_[symbol_id].prob))); int32_t fix = probability_table_[symbol_id].prob - new_prob; - if (fix == 0u) + if (fix == 0u) { fix = 1; - if (fix >= static_cast<int32_t>(probability_table_[symbol_id].prob)) + } + if (fix >= static_cast<int32_t>(probability_table_[symbol_id].prob)) { fix = probability_table_[symbol_id].prob - 1; - if (fix > error) + } + if (fix > error) { fix = error; + } probability_table_[symbol_id].prob -= fix; total_rans_prob -= fix; error -= fix; - if (total_rans_prob == rans_precision_) + if (total_rans_prob == rans_precision_) { break; + } } } } @@ -170,8 +177,9 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create( probability_table_[i].cum_prob = total_prob; total_prob += probability_table_[i].prob; } - if (total_prob != rans_precision_) + if (total_prob != rans_precision_) { return false; + } // Estimate the number of bits needed to encode the input. // From Shannon entropy the total number of bits N is: @@ -180,15 +188,17 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create( // symbol's frequency in the input data. double num_bits = 0; for (int i = 0; i < num_symbols; ++i) { - if (probability_table_[i].prob == 0) + if (probability_table_[i].prob == 0) { continue; + } const double norm_prob = static_cast<double>(probability_table_[i].prob) / rans_precision_d; num_bits += static_cast<double>(frequencies[i]) * log2(norm_prob); } num_expected_bits_ = static_cast<uint64_t>(ceil(-num_bits)); - if (!EncodeTable(buffer)) + if (!EncodeTable(buffer)) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/shannon_entropy.cc b/extern/draco/draco/src/draco/compression/entropy/shannon_entropy.cc index 5050c11188c..137eafe5fac 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/shannon_entropy.cc +++ b/extern/draco/draco/src/draco/compression/entropy/shannon_entropy.cc @@ -27,20 +27,23 @@ int64_t ComputeShannonEntropy(const uint32_t *symbols, int num_symbols, log2(static_cast<double>(symbol_frequencies[i]) / num_symbols_d); } } - if (out_num_unique_symbols) + if (out_num_unique_symbols) { *out_num_unique_symbols = num_unique_symbols; + } // Entropy is always negative. return static_cast<int64_t>(-total_bits); } double ComputeBinaryShannonEntropy(uint32_t num_values, uint32_t num_true_values) { - if (num_values == 0) + if (num_values == 0) { return 0; + } // We can exit early if the data set has 0 entropy. - if (num_true_values == 0 || num_values == num_true_values) + if (num_true_values == 0 || num_values == num_true_values) { return 0; + } const double true_freq = static_cast<double>(num_true_values) / static_cast<double>(num_values); const double false_freq = 1.0 - true_freq; @@ -120,8 +123,9 @@ ShannonEntropyTracker::EntropyData ShannonEntropyTracker::UpdateSymbols( int64_t ShannonEntropyTracker::GetNumberOfDataBits( const EntropyData &entropy_data) { - if (entropy_data.num_values < 2) + if (entropy_data.num_values < 2) { return 0; + } // We need to compute the number of bits required to represent the stream // using the entropy norm. Note that: // diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/shannon_entropy.h b/extern/draco/draco/src/draco/compression/entropy/shannon_entropy.h index 85165f4cb8d..85165f4cb8d 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/shannon_entropy.h +++ b/extern/draco/draco/src/draco/compression/entropy/shannon_entropy.h diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_decoding.cc b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc index 39a1eb0ff24..93d29971c89 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_decoding.cc +++ b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc @@ -31,12 +31,14 @@ bool DecodeRawSymbols(uint32_t num_values, DecoderBuffer *src_buffer, bool DecodeSymbols(uint32_t num_values, int num_components, DecoderBuffer *src_buffer, uint32_t *out_values) { - if (num_values == 0) + if (num_values == 0) { return true; + } // Decode which scheme to use. uint8_t scheme; - if (!src_buffer->Decode(&scheme)) + if (!src_buffer->Decode(&scheme)) { return false; + } if (scheme == SYMBOL_CODING_TAGGED) { return DecodeTaggedSymbols<RAnsSymbolDecoder>(num_values, num_components, src_buffer, out_values); @@ -52,14 +54,17 @@ bool DecodeTaggedSymbols(uint32_t num_values, int num_components, DecoderBuffer *src_buffer, uint32_t *out_values) { // Decode the encoded data. SymbolDecoderT<5> tag_decoder; - if (!tag_decoder.Create(src_buffer)) + if (!tag_decoder.Create(src_buffer)) { return false; + } - if (!tag_decoder.StartDecoding(src_buffer)) + if (!tag_decoder.StartDecoding(src_buffer)) { return false; + } - if (num_values > 0 && tag_decoder.num_symbols() == 0) + if (num_values > 0 && tag_decoder.num_symbols() == 0) { return false; // Wrong number of symbols. + } // src_buffer now points behind the encoded tag data (to the place where the // values are encoded). @@ -71,8 +76,9 @@ bool DecodeTaggedSymbols(uint32_t num_values, int num_components, // Decode the actual value. for (int j = 0; j < num_components; ++j) { uint32_t val; - if (!src_buffer->DecodeLeastSignificantBits32(bit_length, &val)) + if (!src_buffer->DecodeLeastSignificantBits32(bit_length, &val)) { return false; + } out_values[value_id++] = val; } } @@ -85,14 +91,17 @@ template <class SymbolDecoderT> bool DecodeRawSymbolsInternal(uint32_t num_values, DecoderBuffer *src_buffer, uint32_t *out_values) { SymbolDecoderT decoder; - if (!decoder.Create(src_buffer)) + if (!decoder.Create(src_buffer)) { return false; + } - if (num_values > 0 && decoder.num_symbols() == 0) + if (num_values > 0 && decoder.num_symbols() == 0) { return false; // Wrong number of symbols. + } - if (!decoder.StartDecoding(src_buffer)) + if (!decoder.StartDecoding(src_buffer)) { return false; + } for (uint32_t i = 0; i < num_values; ++i) { // Decode a symbol into the value. const uint32_t value = decoder.DecodeSymbol(); @@ -106,8 +115,9 @@ template <template <int> class SymbolDecoderT> bool DecodeRawSymbols(uint32_t num_values, DecoderBuffer *src_buffer, uint32_t *out_values) { uint8_t max_bit_length; - if (!src_buffer->Decode(&max_bit_length)) + if (!src_buffer->Decode(&max_bit_length)) { return false; + } switch (max_bit_length) { case 1: return DecodeRawSymbolsInternal<SymbolDecoderT<1>>(num_values, src_buffer, diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_decoding.h b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.h index ea11165c347..ea11165c347 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_decoding.h +++ b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.h diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_encoding.cc b/extern/draco/draco/src/draco/compression/entropy/symbol_encoding.cc index 9a5868c40a5..710c96284da 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_encoding.cc +++ b/extern/draco/draco/src/draco/compression/entropy/symbol_encoding.cc @@ -36,8 +36,9 @@ void SetSymbolEncodingMethod(Options *options, SymbolCodingMethod method) { bool SetSymbolEncodingCompressionLevel(Options *options, int compression_level) { - if (compression_level < 0 || compression_level > 10) + if (compression_level < 0 || compression_level > 10) { return false; + } options->SetInt("symbol_encoding_compression_level", compression_level); return true; } @@ -56,8 +57,9 @@ static void ComputeBitLengths(const uint32_t *symbols, int num_values, // Get the maximum value for a given entry across all attribute components. uint32_t max_component_value = symbols[i]; for (int j = 1; j < num_components; ++j) { - if (max_component_value < symbols[i + j]) + if (max_component_value < symbols[i + j]) { max_component_value = symbols[i + j]; + } } int value_msb_pos = 0; if (max_component_value > 0) { @@ -113,12 +115,15 @@ bool EncodeRawSymbols(const uint32_t *symbols, int num_values, bool EncodeSymbols(const uint32_t *symbols, int num_values, int num_components, const Options *options, EncoderBuffer *target_buffer) { - if (num_values < 0) + if (num_values < 0) { return false; - if (num_values == 0) + } + if (num_values == 0) { return true; - if (num_components <= 0) + } + if (num_components <= 0) { num_components = 1; + } std::vector<uint32_t> bit_lengths; uint32_t max_value; ComputeBitLengths(symbols, num_values, num_components, &bit_lengths, @@ -275,8 +280,9 @@ bool EncodeRawSymbols(const uint32_t *symbols, int num_values, } int unique_symbols_bit_length = symbol_bits + 1; // Currently, we don't support encoding of more than 2^18 unique symbols. - if (unique_symbols_bit_length > kMaxRawEncodingBitLength) + if (unique_symbols_bit_length > kMaxRawEncodingBitLength) { return false; + } int compression_level = kDefaultSymbolCodingCompressionLevel; if (options != nullptr && options->IsOptionSet("symbol_encoding_compression_level")) { diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_encoding.h b/extern/draco/draco/src/draco/compression/entropy/symbol_encoding.h index 839b28b17a5..839b28b17a5 100644 --- a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_encoding.h +++ b/extern/draco/draco/src/draco/compression/entropy/symbol_encoding.h diff --git a/extern/draco/dracoenc/src/draco/compression/expert_encode.cc b/extern/draco/draco/src/draco/compression/expert_encode.cc index 112e6ae3d3e..4c70a72a765 100644 --- a/extern/draco/dracoenc/src/draco/compression/expert_encode.cc +++ b/extern/draco/draco/src/draco/compression/expert_encode.cc @@ -30,8 +30,9 @@ ExpertEncoder::ExpertEncoder(const Mesh &mesh) : point_cloud_(&mesh), mesh_(&mesh) {} Status ExpertEncoder::EncodeToBuffer(EncoderBuffer *out_buffer) { - if (point_cloud_ == nullptr) + if (point_cloud_ == nullptr) { return Status(Status::DRACO_ERROR, "Invalid input geometry."); + } if (mesh_ == nullptr) { return EncodePointCloudToBuffer(*point_cloud_, out_buffer); } @@ -62,13 +63,16 @@ Status ExpertEncoder::EncodePointCloudToBuffer(const PointCloud &pc, if (kd_tree_possible && att->data_type() != DT_FLOAT32 && att->data_type() != DT_UINT32 && att->data_type() != DT_UINT16 && att->data_type() != DT_UINT8 && att->data_type() != DT_INT32 && - att->data_type() != DT_INT16 && att->data_type() != DT_INT8) + att->data_type() != DT_INT16 && att->data_type() != DT_INT8) { kd_tree_possible = false; + } if (kd_tree_possible && att->data_type() == DT_FLOAT32 && - options().GetAttributeInt(0, "quantization_bits", -1) <= 0) + options().GetAttributeInt(0, "quantization_bits", -1) <= 0) { kd_tree_possible = false; // Quantization not enabled. - if (!kd_tree_possible) + } + if (!kd_tree_possible) { break; + } } if (kd_tree_possible) { @@ -167,8 +171,9 @@ Status ExpertEncoder::SetAttributePredictionScheme( auto att_type = att->attribute_type(); const Status status = CheckPredictionScheme(att_type, prediction_scheme_method); - if (!status.ok()) + if (!status.ok()) { return status; + } options().SetAttributeInt(attribute_id, "prediction_scheme", prediction_scheme_method); return status; diff --git a/extern/draco/dracoenc/src/draco/compression/expert_encode.h b/extern/draco/draco/src/draco/compression/expert_encode.h index a1aa7b8b3a8..a1aa7b8b3a8 100644 --- a/extern/draco/dracoenc/src/draco/compression/expert_encode.h +++ b/extern/draco/draco/src/draco/compression/expert_encode.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_decoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_decoder.cc index 01913dcd047..6e48e56fb98 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_decoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_decoder.cc @@ -25,10 +25,12 @@ Status MeshDecoder::Decode(const DecoderOptions &options, } bool MeshDecoder::DecodeGeometryData() { - if (mesh_ == nullptr) + if (mesh_ == nullptr) { return false; - if (!DecodeConnectivity()) + } + if (!DecodeConnectivity()) { return false; + } return PointCloudDecoder::DecodeGeometryData(); } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_decoder.h index 397a679d440..397a679d440 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_decoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder.cc index e164f82b12b..427dd59f5df 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/compression/mesh/mesh_edgebreaker_decoder.h" + #include "draco/compression/mesh/mesh_edgebreaker_decoder_impl.h" #include "draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h" #include "draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h" @@ -27,8 +28,9 @@ bool MeshEdgebreakerDecoder::CreateAttributesDecoder(int32_t att_decoder_id) { bool MeshEdgebreakerDecoder::InitializeDecoder() { uint8_t traversal_decoder_type; - if (!buffer()->Decode(&traversal_decoder_type)) + if (!buffer()->Decode(&traversal_decoder_type)) { return false; + } impl_ = nullptr; if (traversal_decoder_type == MESH_EDGEBREAKER_STANDARD_ENCODING) { #ifdef DRACO_STANDARD_EDGEBREAKER_SUPPORTED @@ -51,8 +53,9 @@ bool MeshEdgebreakerDecoder::InitializeDecoder() { if (!impl_) { return false; } - if (!impl_->Init(this)) + if (!impl_->Init(this)) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder.h index c3569405220..5c161794298 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder.h @@ -15,10 +15,9 @@ #ifndef DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_DECODER_H_ #define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/mesh/mesh_decoder.h" #include "draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h" +#include "draco/draco_features.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc index 9b91a6f07c4..50d1971c15b 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc @@ -65,14 +65,16 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeCornerTable( int att_id) const { for (uint32_t i = 0; i < attribute_data_.size(); ++i) { const int decoder_id = attribute_data_[i].decoder_id; - if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) + if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) { continue; + } const AttributesDecoderInterface *const dec = decoder_->attributes_decoder(decoder_id); for (int j = 0; j < dec->GetNumAttributes(); ++j) { if (dec->GetAttributeId(j) == att_id) { - if (attribute_data_[i].is_connectivity_used) + if (attribute_data_[i].is_connectivity_used) { return &attribute_data_[i].connectivity_data; + } return nullptr; } } @@ -86,13 +88,15 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeEncodingData( int att_id) const { for (uint32_t i = 0; i < attribute_data_.size(); ++i) { const int decoder_id = attribute_data_[i].decoder_id; - if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) + if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) { continue; + } const AttributesDecoderInterface *const dec = decoder_->attributes_decoder(decoder_id); for (int j = 0; j < dec->GetNumAttributes(); ++j) { - if (dec->GetAttributeId(j) == att_id) + if (dec->GetAttributeId(j) == att_id) { return &attribute_data_[i].encoding_data; + } } } return &pos_encoding_data_; @@ -124,11 +128,13 @@ template <class TraversalDecoder> bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder( int32_t att_decoder_id) { int8_t att_data_id; - if (!decoder_->buffer()->Decode(&att_data_id)) + if (!decoder_->buffer()->Decode(&att_data_id)) { return false; + } uint8_t decoder_type; - if (!decoder_->buffer()->Decode(&decoder_type)) + if (!decoder_->buffer()->Decode(&decoder_type)) { return false; + } if (att_data_id >= 0) { if (att_data_id >= attribute_data_.size()) { @@ -137,22 +143,25 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder( // Ensure that the attribute data is not mapped to a different attributes // decoder already. - if (attribute_data_[att_data_id].decoder_id >= 0) + if (attribute_data_[att_data_id].decoder_id >= 0) { return false; + } attribute_data_[att_data_id].decoder_id = att_decoder_id; } else { // Assign the attributes decoder to |pos_encoding_data_|. - if (pos_data_decoder_id_ >= 0) + if (pos_data_decoder_id_ >= 0) { return false; // Some other decoder is already using the data. Error. + } pos_data_decoder_id_ = att_decoder_id; } MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST; if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) { uint8_t traversal_method_encoded; - if (!decoder_->buffer()->Decode(&traversal_method_encoded)) + if (!decoder_->buffer()->Decode(&traversal_method_encoded)) { return false; + } traversal_method = static_cast<MeshTraversalMethod>(traversal_method_encoded); } @@ -186,10 +195,12 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder( return false; // Unsupported method } } else { - if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) + if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) { return false; // Unsupported method. - if (att_data_id < 0) + } + if (att_data_id < 0) { return false; // Attribute data must be specified. + } // Per-corner attribute decoder. @@ -216,8 +227,9 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder( sequencer = std::move(traversal_sequencer); } - if (!sequencer) + if (!sequencer) { return false; + } std::unique_ptr<SequentialAttributeDecodersController> att_controller( new SequentialAttributeDecodersController(std::move(sequencer))); @@ -234,11 +246,13 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { uint32_t num_new_verts; if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_->buffer()->Decode(&num_new_verts)) + if (!decoder_->buffer()->Decode(&num_new_verts)) { return false; + } } else { - if (!DecodeVarint(&num_new_verts, decoder_->buffer())) + if (!DecodeVarint(&num_new_verts, decoder_->buffer())) { return false; + } } num_new_vertices_ = num_new_verts; } @@ -247,50 +261,58 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { uint32_t num_encoded_vertices; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_->buffer()->Decode(&num_encoded_vertices)) + if (!decoder_->buffer()->Decode(&num_encoded_vertices)) { return false; + } } else #endif { - if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) + if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) { return false; + } } num_encoded_vertices_ = num_encoded_vertices; uint32_t num_faces; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_->buffer()->Decode(&num_faces)) + if (!decoder_->buffer()->Decode(&num_faces)) { return false; + } } else #endif { - if (!DecodeVarint(&num_faces, decoder_->buffer())) + if (!DecodeVarint(&num_faces, decoder_->buffer())) { return false; + } } - if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) + if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) { return false; // Draco cannot handle this many faces. + } if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) { return false; // There cannot be more vertices than 3 * num_faces. } uint8_t num_attribute_data; - if (!decoder_->buffer()->Decode(&num_attribute_data)) + if (!decoder_->buffer()->Decode(&num_attribute_data)) { return false; + } uint32_t num_encoded_symbols; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_->buffer()->Decode(&num_encoded_symbols)) + if (!decoder_->buffer()->Decode(&num_encoded_symbols)) { return false; + } } else #endif { - if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) + if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) { return false; + } } if (num_faces < num_encoded_symbols) { @@ -311,14 +333,16 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { uint32_t num_encoded_split_symbols; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) + if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) { return false; + } } else #endif { - if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) + if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) { return false; + } } if (num_encoded_split_symbols > num_encoded_symbols) { @@ -328,8 +352,9 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { // Decode topology (connectivity). vertex_traversal_length_.clear(); corner_table_ = std::unique_ptr<CornerTable>(new CornerTable()); - if (corner_table_ == nullptr) + if (corner_table_ == nullptr) { return false; + } processed_corner_ids_.clear(); processed_corner_ids_.reserve(num_faces); processed_connectivity_corners_.clear(); @@ -347,9 +372,10 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { // Add one attribute data for each attribute decoder. attribute_data_.resize(num_attribute_data); - if (!corner_table_->Reset(num_faces, - num_encoded_vertices_ + num_encoded_split_symbols)) + if (!corner_table_->Reset( + num_faces, num_encoded_vertices_ + num_encoded_split_symbols)) { return false; + } // Start with all vertices marked as holes (boundaries). // Only vertices decoded with TOPOLOGY_C symbol (and the initial face) will @@ -363,15 +389,18 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { uint32_t encoded_connectivity_size; if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) + if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) { return false; + } } else { - if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) + if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) { return false; + } } if (encoded_connectivity_size == 0 || - encoded_connectivity_size > decoder_->buffer()->remaining_size()) + encoded_connectivity_size > decoder_->buffer()->remaining_size()) { return false; + } DecoderBuffer event_buffer; event_buffer.Init( decoder_->buffer()->data_head() + encoded_connectivity_size, @@ -380,14 +409,16 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { // Decode hole and topology split events. topology_split_decoded_bytes = DecodeHoleAndTopologySplitEvents(&event_buffer); - if (topology_split_decoded_bytes == -1) + if (topology_split_decoded_bytes == -1) { return false; + } } else #endif { - if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) + if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) { return false; + } } traversal_decoder_.Init(this); @@ -397,12 +428,14 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { traversal_decoder_.SetNumAttributeData(num_attribute_data); DecoderBuffer traversal_end_buffer; - if (!traversal_decoder_.Start(&traversal_end_buffer)) + if (!traversal_decoder_.Start(&traversal_end_buffer)) { return false; + } const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols); - if (num_connectivity_verts == -1) + if (num_connectivity_verts == -1) { return false; + } // Set the main buffer to the end of the traversal. decoder_->buffer()->Init(traversal_end_buffer.data_head(), @@ -421,16 +454,18 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) { for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) { - if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) + if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) { return false; + } } } else #endif { for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) { - if (!DecodeAttributeConnectivitiesOnFace(ci)) + if (!DecodeAttributeConnectivitiesOnFace(ci)) { return false; + } } } } @@ -456,12 +491,14 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { // it). int32_t att_connectivity_verts = attribute_data_[i].connectivity_data.num_vertices(); - if (att_connectivity_verts < corner_table_->num_vertices()) + if (att_connectivity_verts < corner_table_->num_vertices()) { att_connectivity_verts = corner_table_->num_vertices(); + } attribute_data_[i].encoding_data.Init(att_connectivity_verts); } - if (!AssignPointsToCorners(num_connectivity_verts)) + if (!AssignPointsToCorners(num_connectivity_verts)) { return false; + } return true; } @@ -523,8 +560,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( // Find the corner "b" from the corner "a" which is the corner on the // top of the active stack. - if (active_corner_stack.empty()) + if (active_corner_stack.empty()) { return -1; + } const CornerIndex corner_a = active_corner_stack.back(); const VertexIndex vertex_x = @@ -565,8 +603,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( // . . // . . // * - if (active_corner_stack.empty()) + if (active_corner_stack.empty()) { return -1; + } const CornerIndex corner_a = active_corner_stack.back(); // First corner on the new face is either corner "l" or "r". @@ -587,8 +626,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( // Update vertex mapping. const VertexIndex new_vert_index = corner_table_->AddNewVertex(); - if (corner_table_->num_vertices() > max_num_vertices) + if (corner_table_->num_vertices() > max_num_vertices) { return -1; // Unexpected number of decoded vertices. + } corner_table_->MapCornerToVertex(opp_corner, new_vert_index); corner_table_->SetLeftMostCorner(new_vert_index, opp_corner); @@ -614,8 +654,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( // \ / S \ / // *.......* // - if (active_corner_stack.empty()) + if (active_corner_stack.empty()) { return -1; + } const CornerIndex corner_b = active_corner_stack.back(); active_corner_stack.pop_back(); @@ -626,8 +667,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( // Topology split event. Move the retrieved edge to the stack. active_corner_stack.push_back(it->second); } - if (active_corner_stack.empty()) + if (active_corner_stack.empty()) { return -1; + } const CornerIndex corner_a = active_corner_stack.back(); if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex || @@ -669,8 +711,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( // Make sure the old vertex n is now mapped to an invalid corner (make it // isolated). corner_table_->MakeVertexIsolated(vertex_n); - if (remove_invalid_vertices) + if (remove_invalid_vertices) { invalid_vertices.push_back(vertex_n); + } active_corner_stack.back() = corner; } else if (symbol == TOPOLOGY_E) { const CornerIndex corner(3 * face.value()); @@ -682,8 +725,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( corner_table_->MapCornerToVertex(corner + 2, corner_table_->AddNewVertex()); - if (corner_table_->num_vertices() > max_num_vertices) + if (corner_table_->num_vertices() > max_num_vertices) { return -1; // Unexpected number of decoded vertices. + } corner_table_->SetLeftMostCorner(first_vert_index, corner); corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1); @@ -713,8 +757,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( int encoder_split_symbol_id; while (IsTopologySplit(encoder_symbol_id, &split_edge, &encoder_split_symbol_id)) { - if (encoder_split_symbol_id < 0) + if (encoder_split_symbol_id < 0) { return -1; // Wrong split symbol id. + } // Symbol was part of a topology split. Now we need to determine which // edge should be added to the active edges stack. const CornerIndex act_top_corner = active_corner_stack.back(); @@ -742,8 +787,9 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( } } } - if (corner_table_->num_vertices() > max_num_vertices) + if (corner_table_->num_vertices() > max_num_vertices) { return -1; // Unexpected number of decoded vertices. + } // Decode start faces and connect them to the faces from the active stack. while (active_corner_stack.size() > 0) { const CornerIndex corner = active_corner_stack.back(); @@ -817,21 +863,23 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( init_corners_.push_back(corner); } } - if (num_faces != corner_table_->num_faces()) + if (num_faces != corner_table_->num_faces()) { return -1; // Unexpected number of decoded faces. + } int num_vertices = corner_table_->num_vertices(); // If any vertex was marked as isolated, we want to remove it from the corner // table to ensure that all vertices in range <0, num_vertices> are valid. - for (const VertexIndex invalid_vert : invalid_vertices) { + for (const VertexIndex& invalid_vert : invalid_vertices) { // Find the last valid vertex and swap it with the isolated vertex. VertexIndex src_vert(num_vertices - 1); while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) { // The last vertex is invalid, proceed to the previous one. src_vert = VertexIndex(--num_vertices - 1); } - if (src_vert < invalid_vert) + if (src_vert < invalid_vert) { continue; // No need to swap anything. + } // Remap all corners mapped to |src_vert| to |invalid_vert|. VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert); @@ -861,29 +909,36 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( uint32_t num_topology_splits; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_buffer->Decode(&num_topology_splits)) + if (!decoder_buffer->Decode(&num_topology_splits)) { return -1; + } } else #endif { - if (!DecodeVarint(&num_topology_splits, decoder_buffer)) + if (!DecodeVarint(&num_topology_splits, decoder_buffer)) { return -1; + } } if (num_topology_splits > 0) { - if (num_topology_splits > static_cast<uint32_t>(corner_table_->num_faces())) + if (num_topology_splits > + static_cast<uint32_t>(corner_table_->num_faces())) { return -1; + } #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) { for (uint32_t i = 0; i < num_topology_splits; ++i) { TopologySplitEventData event_data; - if (!decoder_buffer->Decode(&event_data.split_symbol_id)) + if (!decoder_buffer->Decode(&event_data.split_symbol_id)) { return -1; - if (!decoder_buffer->Decode(&event_data.source_symbol_id)) + } + if (!decoder_buffer->Decode(&event_data.source_symbol_id)) { return -1; + } uint8_t edge_data; - if (!decoder_buffer->Decode(&edge_data)) + if (!decoder_buffer->Decode(&edge_data)) { return -1; + } event_data.source_edge = edge_data & 1; topology_split_data_.push_back(event_data); } @@ -900,8 +955,9 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( DecodeVarint<uint32_t>(&delta, decoder_buffer); event_data.source_symbol_id = delta + last_source_symbol_id; DecodeVarint<uint32_t>(&delta, decoder_buffer); - if (delta > event_data.source_symbol_id) + if (delta > event_data.source_symbol_id) { return -1; + } event_data.split_symbol_id = event_data.source_symbol_id - static_cast<int32_t>(delta); last_source_symbol_id = event_data.source_symbol_id; @@ -925,11 +981,13 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( uint32_t num_hole_events = 0; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!decoder_buffer->Decode(&num_hole_events)) + if (!decoder_buffer->Decode(&num_hole_events)) { return -1; + } } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) { - if (!DecodeVarint(&num_hole_events, decoder_buffer)) + if (!DecodeVarint(&num_hole_events, decoder_buffer)) { return -1; + } } #endif if (num_hole_events > 0) { @@ -937,8 +995,9 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) { for (uint32_t i = 0; i < num_hole_events; ++i) { HoleEventData event_data; - if (!decoder_buffer->Decode(&event_data)) + if (!decoder_buffer->Decode(&event_data)) { return -1; + } hole_event_data_.push_back(event_data); } @@ -981,8 +1040,9 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>:: for (uint32_t i = 0; i < attribute_data_.size(); ++i) { const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i); - if (is_seam) + if (is_seam) { attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); + } } } return true; @@ -1009,13 +1069,15 @@ bool MeshEdgebreakerDecoderImpl< } const FaceIndex opp_face_id = corner_table_->Face(opp_corner); // Don't decode edges when the opposite face has been already processed. - if (opp_face_id < src_face_id) + if (opp_face_id < src_face_id) { continue; + } for (uint32_t i = 0; i < attribute_data_.size(); ++i) { const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i); - if (is_seam) + if (is_seam) { attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); + } } } return true; @@ -1055,8 +1117,9 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners( std::vector<int32_t> corner_to_point_map(corner_table_->num_corners()); for (int v = 0; v < corner_table_->num_vertices(); ++v) { CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v)); - if (c == kInvalidCornerIndex) + if (c == kInvalidCornerIndex) { continue; // Isolated vertex. + } CornerIndex deduplication_first_corner = c; if (is_vert_hole_[v]) { // If the vertex is on a boundary, start deduplication from the left most @@ -1066,8 +1129,9 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners( // If we are not on the boundary we need to find the first seam (of any // attribute). for (uint32_t i = 0; i < attribute_data_.size(); ++i) { - if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) + if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) { continue; // No seam for this attribute, ignore it. + } // Else there needs to be at least one seam edge. // At this point, we use identity mapping between corners and point ids. @@ -1076,8 +1140,9 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners( CornerIndex act_c = corner_table_->SwingRight(c); bool seam_found = false; while (act_c != c) { - if (act_c == kInvalidCornerIndex) + if (act_c == kInvalidCornerIndex) { return false; + } if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) { // Attribute seam found. Stop. deduplication_first_corner = act_c; @@ -1086,8 +1151,9 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners( } act_c = corner_table_->SwingRight(act_c); } - if (seam_found) + if (seam_found) { break; // No reason to process other attributes if we found a seam. + } } } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.h index 5299a189d48..78053f91dbe 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.h @@ -17,14 +17,13 @@ #include <unordered_map> #include <unordered_set> -#include "draco/compression/mesh/traverser/mesh_traversal_sequencer.h" - -#include "draco/draco_features.h" #include "draco/compression/attributes/mesh_attribute_indices_encoding_data.h" #include "draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h" #include "draco/compression/mesh/mesh_edgebreaker_shared.h" +#include "draco/compression/mesh/traverser/mesh_traversal_sequencer.h" #include "draco/core/decoder_buffer.h" +#include "draco/draco_features.h" #include "draco/mesh/corner_table.h" #include "draco/mesh/mesh_attribute_corner_table.h" @@ -85,8 +84,9 @@ class MeshEdgebreakerDecoderImpl : public MeshEdgebreakerDecoderImplInterface { // symbol. bool IsTopologySplit(int encoder_symbol_id, EdgeFaceName *out_face_edge, int *out_encoder_split_symbol_id) { - if (topology_split_data_.size() == 0) + if (topology_split_data_.size() == 0) { return false; + } if (topology_split_data_.back().source_symbol_id > static_cast<uint32_t>(encoder_symbol_id)) { // Something is wrong; if the desired source symbol is greater than the @@ -97,8 +97,9 @@ class MeshEdgebreakerDecoderImpl : public MeshEdgebreakerDecoderImplInterface { *out_encoder_split_symbol_id = -1; return true; } - if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) + if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) { return false; + } *out_face_edge = static_cast<EdgeFaceName>(topology_split_data_.back().source_edge); *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id; @@ -123,8 +124,9 @@ class MeshEdgebreakerDecoderImpl : public MeshEdgebreakerDecoderImplInterface { bool AssignPointsToCorners(int num_connectivity_verts); bool IsFaceVisited(CornerIndex corner_id) const { - if (corner_id < 0) + if (corner_id < 0) { return true; // Invalid corner signalizes that the face does not exist. + } return visited_faces_[corner_table_->Face(corner_id).value()]; } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h index 31fabf252d8..31fabf252d8 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc index 54fd55a483c..5aff5d8cc10 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc @@ -59,23 +59,27 @@ bool MeshEdgebreakerEncoder::InitializeEncoder() { new MeshEdgebreakerEncoderImpl< MeshEdgebreakerTraversalValenceEncoder>()); } - if (!impl_) + if (!impl_) { return false; - if (!impl_->Init(this)) + } + if (!impl_->Init(this)) { return false; + } return true; } bool MeshEdgebreakerEncoder::GenerateAttributesEncoder(int32_t att_id) { - if (!impl_->GenerateAttributesEncoder(att_id)) + if (!impl_->GenerateAttributesEncoder(att_id)) { return false; + } return true; } bool MeshEdgebreakerEncoder::EncodeAttributesEncoderIdentifier( int32_t att_encoder_id) { - if (!impl_->EncodeAttributesEncoderIdentifier(att_encoder_id)) + if (!impl_->EncodeAttributesEncoderIdentifier(att_encoder_id)) { return false; + } return true; } @@ -84,11 +88,13 @@ Status MeshEdgebreakerEncoder::EncodeConnectivity() { } void MeshEdgebreakerEncoder::ComputeNumberOfEncodedPoints() { - if (!impl_) + if (!impl_) { return; + } const CornerTable *const corner_table = impl_->GetCornerTable(); - if (!corner_table) + if (!corner_table) { return; + } size_t num_points = corner_table->num_vertices() - corner_table->NumIsolatedVertices(); @@ -96,22 +102,26 @@ void MeshEdgebreakerEncoder::ComputeNumberOfEncodedPoints() { // Gather all corner tables for all non-position attributes. std::vector<const MeshAttributeCornerTable *> attribute_corner_tables; for (int i = 0; i < mesh()->num_attributes(); ++i) { - if (mesh()->attribute(i)->attribute_type() == GeometryAttribute::POSITION) + if (mesh()->attribute(i)->attribute_type() == + GeometryAttribute::POSITION) { continue; + } const MeshAttributeCornerTable *const att_corner_table = GetAttributeCornerTable(i); // Attribute corner table may not be used in some configurations. For // these cases we can assume the attribute connectivity to be the same as // the connectivity of the position data. - if (att_corner_table) + if (att_corner_table) { attribute_corner_tables.push_back(att_corner_table); + } } // Add a new point based on the configuration of interior attribute seams // (replicating what the decoder would do). for (VertexIndex vi(0); vi < corner_table->num_vertices(); ++vi) { - if (corner_table->IsVertexIsolated(vi)) + if (corner_table->IsVertexIsolated(vi)) { continue; + } // Go around all corners of the vertex and keep track of the observed // attribute seams. const CornerIndex first_corner_index = corner_table->LeftMostCorner(vi); @@ -144,8 +154,9 @@ void MeshEdgebreakerEncoder::ComputeNumberOfEncodedPoints() { ++num_attribute_seams; } - if (corner_index == first_corner_index) + if (corner_index == first_corner_index) { break; + } // Proceed to the next corner last_corner_index = corner_index; @@ -170,11 +181,13 @@ void MeshEdgebreakerEncoder::ComputeNumberOfEncodedPoints() { } void MeshEdgebreakerEncoder::ComputeNumberOfEncodedFaces() { - if (!impl_) + if (!impl_) { return; + } const CornerTable *const corner_table = impl_->GetCornerTable(); - if (!corner_table) + if (!corner_table) { return; + } set_num_encoded_faces(corner_table->num_faces() - corner_table->NumDegeneratedFaces()); } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.h index 70d4d5061a7..70d4d5061a7 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc index f69ec993f9e..0791dc6705a 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc @@ -67,8 +67,9 @@ MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetAttributeCornerTable( int att_id) const { for (uint32_t i = 0; i < attribute_data_.size(); ++i) { if (attribute_data_[i].attribute_index == att_id) { - if (attribute_data_[i].is_connectivity_used) + if (attribute_data_[i].is_connectivity_used) { return &attribute_data_[i].connectivity_data; + } return nullptr; } } @@ -80,8 +81,9 @@ const MeshAttributeIndicesEncodingData * MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetAttributeEncodingData( int att_id) const { for (uint32_t i = 0; i < attribute_data_.size(); ++i) { - if (attribute_data_[i].attribute_index == att_id) + if (attribute_data_[i].attribute_index == att_id) { return &attribute_data_[i].encoding_data; + } } return &pos_encoding_data_; } @@ -212,8 +214,9 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::GenerateAttributesEncoder( sequencer = std::move(traversal_sequencer); } - if (!sequencer) + if (!sequencer) { return false; + } if (att_data_id == -1) { pos_traversal_method_ = traversal_method; @@ -316,11 +319,13 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { processed_connectivity_corners_.reserve(corner_table_->num_faces()); pos_encoding_data_.num_values = 0; - if (!FindHoles()) + if (!FindHoles()) { return Status(Status::DRACO_ERROR, "Failed to process mesh holes."); + } - if (!InitAttributeData()) + if (!InitAttributeData()) { return Status(Status::DRACO_ERROR, "Failed to initialize attribute data."); + } const uint8_t num_attribute_data = static_cast<uint8_t>(attribute_data_.size()); @@ -336,10 +341,12 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { for (int c_id = 0; c_id < num_corners; ++c_id) { CornerIndex corner_index(c_id); const FaceIndex face_id = corner_table_->Face(corner_index); - if (visited_faces_[face_id.value()]) + if (visited_faces_[face_id.value()]) { continue; // Face has been already processed. - if (corner_table_->IsDegenerated(face_id)) + } + if (corner_table_->IsDegenerated(face_id)) { continue; // Ignore degenerated faces. + } CornerIndex start_corner; const bool interior_config = @@ -375,8 +382,10 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { const FaceIndex opp_face_id = corner_table_->Face(opp_id); if (opp_face_id != kInvalidFaceIndex && !visited_faces_[opp_face_id.value()]) { - if (!EncodeConnectivityFromCorner(opp_id)) - return Status(Status::DRACO_ERROR, "Failed to encode mesh component."); + if (!EncodeConnectivityFromCorner(opp_id)) { + return Status(Status::DRACO_ERROR, + "Failed to encode mesh component."); + } } } else { // Boundary configuration. We start on a boundary rather than on a face. @@ -384,8 +393,9 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { EncodeHole(corner_table_->Next(start_corner), true); // Start processing the face opposite to the boundary edge (the face // containing the start_corner). - if (!EncodeConnectivityFromCorner(start_corner)) + if (!EncodeConnectivityFromCorner(start_corner)) { return Status(Status::DRACO_ERROR, "Failed to encode mesh component."); + } } } // Reverse the order of connectivity corners to match the order in which @@ -416,8 +426,9 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { EncodeVarint(num_split_symbols_, encoder_->buffer()); // Append the traversal buffer. - if (!EncodeSplitData()) + if (!EncodeSplitData()) { return Status(Status::DRACO_ERROR, "Failed to encode split data."); + } encoder_->buffer()->Encode(traversal_encoder_.buffer().data(), traversal_encoder_.buffer().size()); @@ -542,17 +553,19 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivityFromCorner( if (IsRightFaceVisited(corner_id)) { // Right face has been already visited. // Check whether there is a topology split event. - if (right_face_id != kInvalidFaceIndex) + if (right_face_id != kInvalidFaceIndex) { CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, face_id.value(), RIGHT_FACE_EDGE, right_face_id.value()); + } if (IsLeftFaceVisited(corner_id)) { // Both neighboring faces are visited. End reached. // Check whether there is a topology split event on the left face. - if (left_face_id != kInvalidFaceIndex) + if (left_face_id != kInvalidFaceIndex) { CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, face_id.value(), LEFT_FACE_EDGE, left_face_id.value()); + } traversal_encoder_.EncodeSymbol(TOPOLOGY_E); corner_traversal_stack_.pop_back(); break; // Break from the while (num_visited_faces < num_faces) loop. @@ -565,10 +578,11 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivityFromCorner( // Right face was not visited. if (IsLeftFaceVisited(corner_id)) { // Check whether there is a topology split event on the left face. - if (left_face_id != kInvalidFaceIndex) + if (left_face_id != kInvalidFaceIndex) { CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, face_id.value(), LEFT_FACE_EDGE, left_face_id.value()); + } traversal_encoder_.EncodeSymbol(TOPOLOGY_L); // Left face visited, go to the right one. corner_id = right_corner_id; @@ -669,8 +683,9 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::IsRightFaceVisited( CornerIndex corner_id) const { const CornerIndex next_corner_id = corner_table_->Next(corner_id); const CornerIndex opp_corner_id = corner_table_->Opposite(next_corner_id); - if (opp_corner_id != kInvalidCornerIndex) + if (opp_corner_id != kInvalidCornerIndex) { return visited_faces_[corner_table_->Face(opp_corner_id).value()]; + } // Else we are on a boundary. return true; } @@ -680,8 +695,9 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::IsLeftFaceVisited( CornerIndex corner_id) const { const CornerIndex prev_corner_id = corner_table_->Previous(corner_id); const CornerIndex opp_corner_id = corner_table_->Opposite(prev_corner_id); - if (opp_corner_id != kInvalidCornerIndex) + if (opp_corner_id != kInvalidCornerIndex) { return visited_faces_[corner_table_->Face(opp_corner_id).value()]; + } // Else we are on a boundary. return true; } @@ -692,8 +708,9 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::FindHoles() { const int num_corners = corner_table_->num_corners(); // Go over all corners and detect non-visited open boundaries for (CornerIndex i(0); i < num_corners; ++i) { - if (corner_table_->IsDegenerated(corner_table_->Face(i))) + if (corner_table_->IsDegenerated(corner_table_->Face(i))) { continue; // Don't process corners assigned to degenerated faces. + } if (corner_table_->Opposite(i) == kInvalidCornerIndex) { // No opposite corner means no opposite face, so the opposite edge // of the corner is an open boundary. @@ -733,8 +750,9 @@ template <class TraversalEncoder> int MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetSplitSymbolIdOnFace( int face_id) const { auto it = face_to_split_symbol_map_.find(face_id); - if (it == face_to_split_symbol_map_.end()) + if (it == face_to_split_symbol_map_.end()) { return -1; + } return it->second; } @@ -745,8 +763,9 @@ void MeshEdgebreakerEncoderImpl< EdgeFaceName src_edge, int neighbor_face_id) { const int symbol_id = GetSplitSymbolIdOnFace(neighbor_face_id); - if (symbol_id == -1) + if (symbol_id == -1) { return; // Not a split symbol, no topology split event could happen. + } TopologySplitEventData event_data; event_data.split_symbol_id = symbol_id; @@ -757,20 +776,23 @@ void MeshEdgebreakerEncoderImpl< template <class TraversalEncoder> bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::InitAttributeData() { - if (use_single_connectivity_) + if (use_single_connectivity_) { return true; // All attributes use the same connectivity. + } const int num_attributes = mesh_->num_attributes(); // Ignore the position attribute. It's decoded separately. attribute_data_.resize(num_attributes - 1); - if (num_attributes == 1) + if (num_attributes == 1) { return true; + } int data_index = 0; for (int i = 0; i < num_attributes; ++i) { const int32_t att_index = i; if (mesh_->attribute(att_index)->attribute_type() == - GeometryAttribute::POSITION) + GeometryAttribute::POSITION) { continue; + } const PointAttribute *const att = mesh_->attribute(att_index); attribute_data_[data_index].attribute_index = att_index; attribute_data_[data_index] @@ -802,12 +824,14 @@ bool MeshEdgebreakerEncoderImpl< visited_faces_[src_face_id.value()] = true; for (int c = 0; c < 3; ++c) { const CornerIndex opp_corner = corner_table_->Opposite(corners[c]); - if (opp_corner == kInvalidCornerIndex) + if (opp_corner == kInvalidCornerIndex) { continue; // Don't encode attribute seams on boundary edges. + } const FaceIndex opp_face_id = corner_table_->Face(opp_corner); // Don't encode edges when the opposite face has been already processed. - if (visited_faces_[opp_face_id.value()]) + if (visited_faces_[opp_face_id.value()]) { continue; + } for (uint32_t i = 0; i < attribute_data_.size(); ++i) { if (attribute_data_[i].connectivity_data.IsCornerOppositeToSeamEdge( diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h index fb33771637e..fb33771637e 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h index 627d5126296..627d5126296 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_shared.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h index cb3c29dd669..cb3c29dd669 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_shared.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h index 128d7f5d988..ce91adc8747 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h @@ -15,12 +15,11 @@ #ifndef DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_DECODER_H_ #define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/bit_coders/rans_bit_decoder.h" #include "draco/compression/mesh/mesh_edgebreaker_decoder.h" #include "draco/compression/mesh/mesh_edgebreaker_decoder_impl_interface.h" #include "draco/compression/mesh/mesh_edgebreaker_shared.h" +#include "draco/draco_features.h" namespace draco { @@ -60,14 +59,17 @@ class MeshEdgebreakerTraversalDecoder { bool Start(DecoderBuffer *out_buffer) { // Decode symbols from the main buffer decoder and face configurations from // the start_face_buffer decoder. - if (!DecodeTraversalSymbols()) + if (!DecodeTraversalSymbols()) { return false; + } - if (!DecodeStartFaces()) + if (!DecodeStartFaces()) { return false; + } - if (!DecodeAttributeSeams()) + if (!DecodeAttributeSeams()) { return false; + } *out_buffer = buffer_; return true; } @@ -118,8 +120,9 @@ class MeshEdgebreakerTraversalDecoder { // Called when the traversal is finished. void Done() { - if (symbol_buffer_.bit_decoder_active()) + if (symbol_buffer_.bit_decoder_active()) { symbol_buffer_.EndBitDecoding(); + } #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { start_face_buffer_.EndBitDecoding(); @@ -137,11 +140,13 @@ class MeshEdgebreakerTraversalDecoder { bool DecodeTraversalSymbols() { uint64_t traversal_size; symbol_buffer_ = buffer_; - if (!symbol_buffer_.StartBitDecoding(true, &traversal_size)) + if (!symbol_buffer_.StartBitDecoding(true, &traversal_size)) { return false; + } buffer_ = symbol_buffer_; - if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) + if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) { return false; + } buffer_.Advance(traversal_size); return true; } @@ -152,11 +157,13 @@ class MeshEdgebreakerTraversalDecoder { if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { start_face_buffer_ = buffer_; uint64_t traversal_size; - if (!start_face_buffer_.StartBitDecoding(true, &traversal_size)) + if (!start_face_buffer_.StartBitDecoding(true, &traversal_size)) { return false; + } buffer_ = start_face_buffer_; - if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) + if (traversal_size > static_cast<uint64_t>(buffer_.remaining_size())) { return false; + } buffer_.Advance(traversal_size); return true; } @@ -170,8 +177,9 @@ class MeshEdgebreakerTraversalDecoder { attribute_connectivity_decoders_ = std::unique_ptr<BinaryDecoder[]>( new BinaryDecoder[num_attribute_data_]); for (int i = 0; i < num_attribute_data_; ++i) { - if (!attribute_connectivity_decoders_[i].StartDecoding(&buffer_)) + if (!attribute_connectivity_decoders_[i].StartDecoding(&buffer_)) { return false; + } } } return true; diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_encoder.h index 08cb66e4cdc..08cb66e4cdc 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_encoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h index d3289e28c76..3f9004585c6 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h @@ -16,9 +16,8 @@ #ifndef DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_DECODER_H_ #define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h" +#include "draco/draco_features.h" namespace draco { @@ -41,17 +40,20 @@ class MeshEdgebreakerTraversalPredictiveDecoder void SetNumEncodedVertices(int num_vertices) { num_vertices_ = num_vertices; } bool Start(DecoderBuffer *out_buffer) { - if (!MeshEdgebreakerTraversalDecoder::Start(out_buffer)) + if (!MeshEdgebreakerTraversalDecoder::Start(out_buffer)) { return false; + } int32_t num_split_symbols; if (!out_buffer->Decode(&num_split_symbols) || num_split_symbols < 0) return false; - if (num_split_symbols >= num_vertices_) + if (num_split_symbols >= num_vertices_) { return false; + } // Set the valences of all initial vertices to 0. vertex_valences_.resize(num_vertices_, 0); - if (!prediction_decoder_.StartDecoding(out_buffer)) + if (!prediction_decoder_.StartDecoding(out_buffer)) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_encoder.h index 118687cc769..eb937fe8080 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_encoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_predictive_encoder.h @@ -36,8 +36,9 @@ class MeshEdgebreakerTraversalPredictiveEncoder num_symbols_(0) {} bool Init(MeshEdgebreakerEncoderImplInterface *encoder) { - if (!MeshEdgebreakerTraversalEncoder::Init(encoder)) + if (!MeshEdgebreakerTraversalEncoder::Init(encoder)) { return false; + } corner_table_ = encoder->GetCornerTable(); // Initialize valences of all vertices. vertex_valences_.resize(corner_table_->num_vertices()); diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h index 4da9d0e3a8b..621883a5f1f 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h @@ -15,11 +15,10 @@ #ifndef DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_VALENCE_DECODER_H_ #define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_VALENCE_DECODER_H_ -#include "draco/draco_features.h" - #include "draco/compression/entropy/symbol_decoding.h" #include "draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h" #include "draco/core/varint_decoding.h" +#include "draco/draco_features.h" namespace draco { @@ -46,32 +45,39 @@ class MeshEdgebreakerTraversalValenceDecoder bool Start(DecoderBuffer *out_buffer) { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) { - if (!MeshEdgebreakerTraversalDecoder::DecodeTraversalSymbols()) + if (!MeshEdgebreakerTraversalDecoder::DecodeTraversalSymbols()) { return false; + } } #endif - if (!MeshEdgebreakerTraversalDecoder::DecodeStartFaces()) + if (!MeshEdgebreakerTraversalDecoder::DecodeStartFaces()) { return false; - if (!MeshEdgebreakerTraversalDecoder::DecodeAttributeSeams()) + } + if (!MeshEdgebreakerTraversalDecoder::DecodeAttributeSeams()) { return false; + } *out_buffer = *buffer(); #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) { uint32_t num_split_symbols; if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 0)) { - if (!out_buffer->Decode(&num_split_symbols)) + if (!out_buffer->Decode(&num_split_symbols)) { return false; + } } else { - if (!DecodeVarint(&num_split_symbols, out_buffer)) + if (!DecodeVarint(&num_split_symbols, out_buffer)) { return false; + } } - if (num_split_symbols >= static_cast<uint32_t>(num_vertices_)) + if (num_split_symbols >= static_cast<uint32_t>(num_vertices_)) { return false; + } int8_t mode; - if (!out_buffer->Decode(&mode)) + if (!out_buffer->Decode(&mode)) { return false; + } if (mode == EDGEBREAKER_VALENCE_MODE_2_7) { min_valence_ = 2; max_valence_ = 7; @@ -87,8 +93,9 @@ class MeshEdgebreakerTraversalValenceDecoder max_valence_ = 7; } - if (num_vertices_ < 0) + if (num_vertices_ < 0) { return false; + } // Set the valences of all initial vertices to 0. vertex_valences_.resize(num_vertices_, 0); @@ -114,8 +121,9 @@ class MeshEdgebreakerTraversalValenceDecoder // First check if we have a valid context. if (active_context_ != -1) { const int context_counter = --context_counters_[active_context_]; - if (context_counter < 0) + if (context_counter < 0) { return TOPOLOGY_INVALID; + } const int symbol_id = context_symbols_[active_context_][context_counter]; last_symbol_ = edge_breaker_symbol_to_topology_id[symbol_id]; } else { diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_encoder.h index ef3a86bf983..c492c84bb45 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_encoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_encoder.h @@ -43,8 +43,9 @@ class MeshEdgebreakerTraversalValenceEncoder max_valence_(7) {} bool Init(MeshEdgebreakerEncoderImplInterface *encoder) { - if (!MeshEdgebreakerTraversalEncoder::Init(encoder)) + if (!MeshEdgebreakerTraversalEncoder::Init(encoder)) { return false; + } min_valence_ = 2; max_valence_ = 7; corner_table_ = encoder->GetCornerTable(); @@ -117,8 +118,9 @@ class MeshEdgebreakerTraversalValenceEncoder int num_left_faces = 0; CornerIndex act_c = corner_table_->Opposite(prev); while (act_c != kInvalidCornerIndex) { - if (encoder_impl()->IsFaceEncoded(corner_table_->Face(act_c))) + if (encoder_impl()->IsFaceEncoded(corner_table_->Face(act_c))) { break; // Stop when we reach the first visited face. + } ++num_left_faces; act_c = corner_table_->Opposite(corner_table_->Next(act_c)); } @@ -132,8 +134,9 @@ class MeshEdgebreakerTraversalValenceEncoder act_c = corner_table_->Opposite(next); while (act_c != kInvalidCornerIndex) { - if (encoder_impl()->IsFaceEncoded(corner_table_->Face(act_c))) + if (encoder_impl()->IsFaceEncoded(corner_table_->Face(act_c))) { break; // Stop when we reach the first visited face. + } ++num_right_faces; // Map corners on the right side to the newly created vertex. corner_to_vertex_map_[corner_table_->Next(act_c)] = new_vert_id; diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_encoder.cc index 2da5de1fc82..483ea02a7bc 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_encoder.cc @@ -25,8 +25,9 @@ void MeshEncoder::SetMesh(const Mesh &m) { Status MeshEncoder::EncodeGeometryData() { DRACO_RETURN_IF_ERROR(EncodeConnectivity()); - if (options()->GetGlobalBool("store_number_of_encoded_faces", false)) + if (options()->GetGlobalBool("store_number_of_encoded_faces", false)) { ComputeNumberOfEncodedFaces(); + } return OkStatus(); } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_encoder.h index 30ec4fa3492..30ec4fa3492 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_decoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc index de71700e160..53f5e8651b8 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_decoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc @@ -28,34 +28,42 @@ bool MeshSequentialDecoder::DecodeConnectivity() { uint32_t num_points; #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { - if (!buffer()->Decode(&num_faces)) + if (!buffer()->Decode(&num_faces)) { return false; - if (!buffer()->Decode(&num_points)) + } + if (!buffer()->Decode(&num_points)) { return false; + } } else #endif { - if (!DecodeVarint(&num_faces, buffer())) + if (!DecodeVarint(&num_faces, buffer())) { return false; - if (!DecodeVarint(&num_points, buffer())) + } + if (!DecodeVarint(&num_points, buffer())) { return false; + } } // Check that num_faces and num_points are valid values. const uint64_t faces_64 = static_cast<uint64_t>(num_faces); const uint64_t points_64 = static_cast<uint64_t>(num_points); // Compressed sequential encoding can only handle (2^32 - 1) / 3 indices. - if (faces_64 > 0xffffffff / 3) + if (faces_64 > 0xffffffff / 3) { return false; - if (points_64 > faces_64 * 3) + } + if (points_64 > faces_64 * 3) { return false; + } uint8_t connectivity_method; - if (!buffer()->Decode(&connectivity_method)) + if (!buffer()->Decode(&connectivity_method)) { return false; + } if (connectivity_method == 0) { - if (!DecodeAndDecompressIndices(num_faces)) + if (!DecodeAndDecompressIndices(num_faces)) { return false; + } } else { if (num_points < 256) { // Decode indices as uint8_t. @@ -63,8 +71,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { Mesh::Face face; for (int j = 0; j < 3; ++j) { uint8_t val; - if (!buffer()->Decode(&val)) + if (!buffer()->Decode(&val)) { return false; + } face[j] = val; } mesh()->AddFace(face); @@ -75,8 +84,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { Mesh::Face face; for (int j = 0; j < 3; ++j) { uint16_t val; - if (!buffer()->Decode(&val)) + if (!buffer()->Decode(&val)) { return false; + } face[j] = val; } mesh()->AddFace(face); @@ -88,8 +98,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { Mesh::Face face; for (int j = 0; j < 3; ++j) { uint32_t val; - if (!DecodeVarint(&val, buffer())) + if (!DecodeVarint(&val, buffer())) { return false; + } face[j] = val; } mesh()->AddFace(face); @@ -100,8 +111,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { Mesh::Face face; for (int j = 0; j < 3; ++j) { uint32_t val; - if (!buffer()->Decode(&val)) + if (!buffer()->Decode(&val)) { return false; + } face[j] = val; } mesh()->AddFace(face); @@ -125,8 +137,9 @@ bool MeshSequentialDecoder::CreateAttributesDecoder(int32_t att_decoder_id) { bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces) { // Get decoded indices differences that were encoded with an entropy code. std::vector<uint32_t> indices_buffer(num_faces * 3); - if (!DecodeSymbols(num_faces * 3, 1, buffer(), indices_buffer.data())) + if (!DecodeSymbols(num_faces * 3, 1, buffer(), indices_buffer.data())) { return false; + } // Reconstruct the indices from the differences. // See MeshSequentialEncoder::CompressAndEncodeIndices() for more details. int32_t last_index_value = 0; @@ -136,8 +149,9 @@ bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces) { for (int j = 0; j < 3; ++j) { const uint32_t encoded_val = indices_buffer[vertex_index++]; int32_t index_diff = (encoded_val >> 1); - if (encoded_val & 1) + if (encoded_val & 1) { index_diff = -index_diff; + } const int32_t index_value = index_diff + last_index_value; face[j] = index_value; last_index_value = index_value; diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.h index 3a86c75d5e9..3a86c75d5e9 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_decoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc index b53ff0c25a6..02ac7779ea3 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc @@ -37,8 +37,9 @@ Status MeshSequentialEncoder::EncodeConnectivity() { if (options()->GetGlobalBool("compress_connectivity", false)) { // 0 = Encode compressed indices. buffer()->Encode(static_cast<uint8_t>(0)); - if (!CompressAndEncodeIndices()) + if (!CompressAndEncodeIndices()) { return Status(Status::DRACO_ERROR, "Failed to compress connectivity."); + } } else { // 1 = Encode indices directly. buffer()->Encode(static_cast<uint8_t>(1)); diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h index 672609642b0..672609642b0 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/depth_first_traverser.h b/extern/draco/draco/src/draco/compression/mesh/traverser/depth_first_traverser.h index 84420cb3888..0b387ec3a70 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/depth_first_traverser.h +++ b/extern/draco/draco/src/draco/compression/mesh/traverser/depth_first_traverser.h @@ -57,8 +57,9 @@ class DepthFirstTraverser void OnTraversalEnd() {} bool TraverseFromCorner(CornerIndex corner_id) { - if (this->IsFaceVisited(corner_id)) + if (this->IsFaceVisited(corner_id)) { return true; // Already traversed. + } corner_traversal_stack_.clear(); corner_traversal_stack_.push_back(corner_id); @@ -68,8 +69,9 @@ class DepthFirstTraverser this->corner_table()->Vertex(this->corner_table()->Next(corner_id)); const VertexIndex prev_vert = this->corner_table()->Vertex(this->corner_table()->Previous(corner_id)); - if (next_vert == kInvalidVertexIndex || prev_vert == kInvalidVertexIndex) + if (next_vert == kInvalidVertexIndex || prev_vert == kInvalidVertexIndex) { return false; + } if (!this->IsVertexVisited(next_vert)) { this->MarkVertexVisited(next_vert); this->traversal_observer().OnNewVertexVisited( @@ -96,8 +98,9 @@ class DepthFirstTraverser this->MarkFaceVisited(face_id); this->traversal_observer().OnNewFaceVisited(face_id); const VertexIndex vert_id = this->corner_table()->Vertex(corner_id); - if (vert_id == kInvalidVertexIndex) + if (vert_id == kInvalidVertexIndex) { return false; + } if (!this->IsVertexVisited(vert_id)) { const bool on_boundary = this->corner_table()->IsOnBoundary(vert_id); this->MarkVertexVisited(vert_id); diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/max_prediction_degree_traverser.h b/extern/draco/draco/src/draco/compression/mesh/traverser/max_prediction_degree_traverser.h index b60d2c159f2..514193eae73 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/max_prediction_degree_traverser.h +++ b/extern/draco/draco/src/draco/compression/mesh/traverser/max_prediction_degree_traverser.h @@ -63,8 +63,9 @@ class MaxPredictionDegreeTraverser void OnTraversalEnd() {} bool TraverseFromCorner(CornerIndex corner_id) { - if (prediction_degree_.size() == 0) + if (prediction_degree_.size() == 0) { return true; + } // Traversal starts from the |corner_id|. It's going to follow either the // right or the left neighboring faces to |corner_id| based on their @@ -184,8 +185,9 @@ class MaxPredictionDegreeTraverser inline void AddCornerToTraversalStack(CornerIndex ci, int priority) { traversal_stacks_[priority].push_back(ci); // Make sure that the best available priority is up to date. - if (priority < best_priority_) + if (priority < best_priority_) { best_priority_ = priority; + } } // Returns the priority of traversing edge leading to |corner_id|. @@ -199,8 +201,9 @@ class MaxPredictionDegreeTraverser priority = (degree > 1 ? 1 : 2); } // Clamp the priority to the maximum number of buckets. - if (priority >= kMaxPriority) + if (priority >= kMaxPriority) { priority = kMaxPriority - 1; + } return priority; } diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h index e66dd14b238..e66dd14b238 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h +++ b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h index fbcda53b792..ebe1d5f7a9e 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h +++ b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h @@ -56,12 +56,13 @@ class MeshTraversalSequencer : public PointsSequencer { const PointIndex point_id = face[p]; const VertexIndex vert_id = corner_table->Vertex(CornerIndex(3 * f.value() + p)); - if (vert_id == kInvalidVertexIndex) + if (vert_id == kInvalidVertexIndex) { return false; + } const AttributeValueIndex att_entry_id( encoding_data_ ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]); - if (att_entry_id.value() >= num_points) { + if (point_id >= num_points || att_entry_id.value() >= num_points) { // There cannot be more attribute values than the number of points. return false; } @@ -80,14 +81,16 @@ class MeshTraversalSequencer : public PointsSequencer { traverser_.OnTraversalStart(); if (corner_order_) { for (uint32_t i = 0; i < corner_order_->size(); ++i) { - if (!ProcessCorner(corner_order_->at(i))) + if (!ProcessCorner(corner_order_->at(i))) { return false; + } } } else { const int32_t num_faces = traverser_.corner_table()->num_faces(); for (int i = 0; i < num_faces; ++i) { - if (!ProcessCorner(CornerIndex(3 * i))) + if (!ProcessCorner(CornerIndex(3 * i))) { return false; + } } } traverser_.OnTraversalEnd(); diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/traverser_base.h b/extern/draco/draco/src/draco/compression/mesh/traverser/traverser_base.h index 643c5db565b..f2f8da79d09 100644 --- a/extern/draco/dracoenc/src/draco/compression/mesh/traverser/traverser_base.h +++ b/extern/draco/draco/src/draco/compression/mesh/traverser/traverser_base.h @@ -43,15 +43,17 @@ class TraverserBase { const CornerTable &GetCornerTable() const { return *corner_table_; } inline bool IsFaceVisited(FaceIndex face_id) const { - if (face_id == kInvalidFaceIndex) + if (face_id == kInvalidFaceIndex) { return true; // Invalid faces are always considered as visited. + } return is_face_visited_[face_id.value()]; } // Returns true if the face containing the given corner was visited. inline bool IsFaceVisited(CornerIndex corner_id) const { - if (corner_id == kInvalidCornerIndex) + if (corner_id == kInvalidCornerIndex) { return true; // Invalid faces are always considered as visited. + } return is_face_visited_[corner_id.value() / 3]; } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.cc index de46f05af67..de46f05af67 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h index 61a153560ae..87bc2b7ef3e 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h @@ -155,25 +155,36 @@ template <int compression_level_t> template <class OutputIteratorT> bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodePoints( DecoderBuffer *buffer, OutputIteratorT &oit) { - buffer->Decode(&bit_length_); - if (bit_length_ > 32) + if (!buffer->Decode(&bit_length_)) { return false; - buffer->Decode(&num_points_); - if (num_points_ == 0) + } + if (bit_length_ > 32) { + return false; + } + if (!buffer->Decode(&num_points_)) { + return false; + } + if (num_points_ == 0) { return true; + } num_decoded_points_ = 0; - if (!numbers_decoder_.StartDecoding(buffer)) + if (!numbers_decoder_.StartDecoding(buffer)) { return false; - if (!remaining_bits_decoder_.StartDecoding(buffer)) + } + if (!remaining_bits_decoder_.StartDecoding(buffer)) { return false; - if (!axis_decoder_.StartDecoding(buffer)) + } + if (!axis_decoder_.StartDecoding(buffer)) { return false; - if (!half_decoder_.StartDecoding(buffer)) + } + if (!half_decoder_.StartDecoding(buffer)) { return false; + } - if (!DecodeInternal(num_points_, oit)) + if (!DecodeInternal(num_points_, oit)) { return false; + } numbers_decoder_.EndDecoding(); remaining_bits_decoder_.EndDecoding(); @@ -187,8 +198,9 @@ template <int compression_level_t> uint32_t DynamicIntegerPointsKdTreeDecoder<compression_level_t>::GetAxis( uint32_t num_remaining_points, const VectorUint32 &levels, uint32_t last_axis) { - if (!Policy::select_axis) + if (!Policy::select_axis) { return DRACO_INCREMENT_MOD(last_axis, dimension_); + } uint32_t best_axis = 0; if (num_remaining_points < 64) { @@ -226,12 +238,14 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal( const VectorUint32 &old_base = base_stack_[stack_pos]; const VectorUint32 &levels = levels_stack_[stack_pos]; - if (num_remaining_points > num_points) + if (num_remaining_points > num_points) { return false; + } const uint32_t axis = GetAxis(num_remaining_points, levels, last_axis); - if (axis >= dimension_) + if (axis >= dimension_) { return false; + } const uint32_t level = levels[axis]; @@ -258,9 +272,10 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal( for (uint32_t j = 0; j < dimension_; j++) { p_[axes_[j]] = 0; const uint32_t num_remaining_bits = bit_length_ - levels[axes_[j]]; - if (num_remaining_bits) + if (num_remaining_bits) { remaining_bits_decoder_.DecodeLeastSignificantBits32( num_remaining_bits, &p_[axes_[j]]); + } p_[axes_[j]] = old_base[axes_[j]] | p_[axes_[j]]; } *oit = p_; @@ -270,8 +285,9 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal( continue; } - if (num_decoded_points_ > num_points_) + if (num_decoded_points_ > num_points_) { return false; + } const int num_remaining_bits = bit_length_ - level; const uint32_t modifier = 1 << (num_remaining_bits - 1); @@ -286,16 +302,20 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal( uint32_t first_half = num_remaining_points / 2 - number; uint32_t second_half = num_remaining_points - first_half; - if (first_half != second_half) - if (!half_decoder_.DecodeNextBit()) + if (first_half != second_half) { + if (!half_decoder_.DecodeNextBit()) { std::swap(first_half, second_half); + } + } levels_stack_[stack_pos][axis] += 1; levels_stack_[stack_pos + 1] = levels_stack_[stack_pos]; // copy - if (first_half) + if (first_half) { status_stack.push(DecodingStatus(first_half, axis, stack_pos)); - if (second_half) + } + if (second_half) { status_stack.push(DecodingStatus(second_half, axis, stack_pos + 1)); + } } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.cc index e7abf52c4a2..e7abf52c4a2 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h index 47ac653c85f..14fa32d7083 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h @@ -191,8 +191,9 @@ bool DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodePoints( buffer->Encode(bit_length_); buffer->Encode(num_points_); - if (num_points_ == 0) + if (num_points_ == 0) { return true; + } numbers_encoder_.StartEncoding(); remaining_bits_encoder_.StartEncoding(); @@ -215,8 +216,9 @@ DynamicIntegerPointsKdTreeEncoder<compression_level_t>::GetAndEncodeAxis( RandomAccessIteratorT begin, RandomAccessIteratorT end, const VectorUint32 &old_base, const VectorUint32 &levels, uint32_t last_axis) { - if (!Policy::select_axis) + if (!Policy::select_axis) { return DRACO_INCREMENT_MOD(last_axis, dimension_); + } // For many points this function selects the axis that should be used // for the split by keeping as many points as possible bundled. @@ -296,8 +298,9 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal( const uint32_t num_remaining_points = static_cast<uint32_t>(end - begin); // If this happens all axis are subdivided to the end. - if ((bit_length_ - level) == 0) + if ((bit_length_ - level) == 0) { continue; + } // Fast encoding of remaining bits if number of points is 1 or 2. // Doing this also for 2 gives a slight additional speed up. @@ -338,8 +341,9 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal( const uint32_t second_half = static_cast<uint32_t>(end - split); const bool left = first_half < second_half; - if (first_half != second_half) + if (first_half != second_half) { half_encoder_.EncodeBit(left); + } if (left) { EncodeNumber(required_bits, num_remaining_points / 2 - first_half); @@ -349,10 +353,12 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal( levels_stack_[stack_pos][axis] += 1; levels_stack_[stack_pos + 1] = levels_stack_[stack_pos]; // copy - if (split != begin) + if (split != begin) { status_stack.push(Status(begin, split, axis, stack_pos)); - if (split != end) + } + if (split != end) { status_stack.push(Status(split, end, axis, stack_pos + 1)); + } } } extern template class DynamicIntegerPointsKdTreeEncoder<0>; diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc index 98526c4e63d..9e8d895f176 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc @@ -62,23 +62,20 @@ class ConversionOutputIterator { }; FloatPointsTreeDecoder::FloatPointsTreeDecoder() - : num_points_(0), compression_level_(0) { + : num_points_(0), compression_level_(0), num_points_from_header_(0) { qinfo_.quantization_bits = 0; qinfo_.range = 0; } bool FloatPointsTreeDecoder::DecodePointCloudKdTreeInternal( DecoderBuffer *buffer, std::vector<Point3ui> *qpoints) { - if (!buffer->Decode(&qinfo_.quantization_bits)) - return false; - if (qinfo_.quantization_bits > 31) - return false; - if (!buffer->Decode(&qinfo_.range)) - return false; - if (!buffer->Decode(&num_points_)) - return false; - if (!buffer->Decode(&compression_level_)) + if (!buffer->Decode(&qinfo_.quantization_bits)) return false; + if (qinfo_.quantization_bits > 31) return false; + if (!buffer->Decode(&qinfo_.range)) return false; + if (!buffer->Decode(&num_points_)) return false; + if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_) return false; + if (!buffer->Decode(&compression_level_)) return false; // Only allow compression level in [0..6]. if (6 < compression_level_) { @@ -135,8 +132,9 @@ bool FloatPointsTreeDecoder::DecodePointCloudKdTreeInternal( } } - if (qpoints->size() != num_points_) + if (qpoints->size() != num_points_) { return false; + } return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h index d3425696a5a..4f09ed2c31d 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h @@ -43,8 +43,9 @@ class FloatPointsTreeDecoder { template <class OutputIteratorT> bool DecodePointCloud(const char *data, size_t data_size, OutputIteratorT out) { - if (data == 0 || data_size <= 0) + if (data == 0 || data_size <= 0) { return false; + } DecoderBuffer buffer; buffer.Init(data, data_size); @@ -65,6 +66,10 @@ class FloatPointsTreeDecoder { } } + void set_num_points_from_header(uint32_t num_points) { + num_points_from_header_ = num_points; + } + private: bool DecodePointCloudKdTreeInternal(DecoderBuffer *buffer, std::vector<Point3ui> *qpoints); @@ -74,6 +79,11 @@ class FloatPointsTreeDecoder { PointCloudCompressionMethod method_; uint32_t num_points_; uint32_t compression_level_; + + // Member variable to check if the number of points from the file header + // matches the number of points in the compression header. If + // |num_points_from_header_| is 0, do not perform the check. Defaults to 0. + uint32_t num_points_from_header_; }; #ifndef DRACO_OLD_GCC @@ -93,26 +103,30 @@ bool FloatPointsTreeDecoder::DecodePointCloud(DecoderBuffer *buffer, std::vector<Point3ui> qpoints; uint32_t decoded_version; - if (!buffer->Decode(&decoded_version)) + if (!buffer->Decode(&decoded_version)) { return false; + } if (decoded_version == 3) { int8_t method_number; - if (!buffer->Decode(&method_number)) + if (!buffer->Decode(&method_number)) { return false; + } method_ = static_cast<PointCloudCompressionMethod>(method_number); if (method_ == KDTREE) { - if (!DecodePointCloudKdTreeInternal(buffer, &qpoints)) + if (!DecodePointCloudKdTreeInternal(buffer, &qpoints)) { return false; + } } else { // Unsupported method. fprintf(stderr, "Method not supported. \n"); return false; } } else if (decoded_version == 2) { // Version 2 only uses KDTREE method. - if (!DecodePointCloudKdTreeInternal(buffer, &qpoints)) + if (!DecodePointCloudKdTreeInternal(buffer, &qpoints)) { return false; + } } else { // Unsupported version. fprintf(stderr, "Version not supported. \n"); return false; diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.cc index 317430f2b8e..317430f2b8e 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h index 1fd807427f5..26ba94f1f59 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h @@ -105,11 +105,13 @@ bool FloatPointsTreeEncoder::EncodePointCloud(InputIteratorT points_begin, buffer()->Encode(qinfo_.range); buffer()->Encode(num_points_); - if (method_ == KDTREE) + if (method_ == KDTREE) { buffer()->Encode(compression_level_); + } - if (num_points_ == 0) + if (num_points_ == 0) { return true; + } if (method_ == KDTREE) { return EncodePointCloudKdTreeInternal(&qpoints); diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.cc index d0428a28e6a..d0428a28e6a 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h index 06ee718e0f5..94e523cadaf 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h @@ -153,19 +153,28 @@ template <class PointDiT, int compression_level_t> template <class OutputIteratorT> bool IntegerPointsKdTreeDecoder<PointDiT, compression_level_t>::DecodePoints( DecoderBuffer *buffer, OutputIteratorT oit) { - buffer->Decode(&bit_length_); - buffer->Decode(&num_points_); - if (num_points_ == 0) + if (!buffer->Decode(&bit_length_)) { + return false; + } + if (!buffer->Decode(&num_points_)) { + return false; + } + if (num_points_ == 0) { return true; + } - if (!numbers_decoder_.StartDecoding(buffer)) + if (!numbers_decoder_.StartDecoding(buffer)) { return false; - if (!remaining_bits_decoder_.StartDecoding(buffer)) + } + if (!remaining_bits_decoder_.StartDecoding(buffer)) { return false; - if (!axis_decoder_.StartDecoding(buffer)) + } + if (!axis_decoder_.StartDecoding(buffer)) { return false; - if (!half_decoder_.StartDecoding(buffer)) + } + if (!half_decoder_.StartDecoding(buffer)) { return false; + } DecodeInternal(num_points_, PointTraits<PointDiT>::Origin(), PointTraits<PointDiT>::ZeroArray(), 0, oit); @@ -182,8 +191,9 @@ template <class PointDiT, int compression_level_t> uint32_t IntegerPointsKdTreeDecoder<PointDiT, compression_level_t>::GetAxis( uint32_t num_remaining_points, const PointDiT & /* base */, std::array<uint32_t, D> levels, uint32_t last_axis) { - if (!Policy::select_axis) + if (!Policy::select_axis) { return DRACO_INCREMENT_MOD(last_axis, D); + } uint32_t best_axis = 0; if (num_remaining_points < 64) { @@ -247,9 +257,10 @@ void IntegerPointsKdTreeDecoder<PointDiT, compression_level_t>::DecodeInternal( // Get remaining bits, mind the carry if not starting at x. PointDiT p = PointTraits<PointDiT>::Origin(); for (int j = 0; j < static_cast<int>(D); j++) { - if (num_remaining_bits[j]) + if (num_remaining_bits[j]) { remaining_bits_decoder_.DecodeLeastSignificantBits32( num_remaining_bits[j], &p[axes[j]]); + } p[axes[j]] = old_base[axes[j]] | p[axes[j]]; } *oit++ = p; @@ -270,15 +281,19 @@ void IntegerPointsKdTreeDecoder<PointDiT, compression_level_t>::DecodeInternal( uint32_t first_half = num_remaining_points / 2 - number; uint32_t second_half = num_remaining_points - first_half; - if (first_half != second_half) - if (!half_decoder_.DecodeNextBit()) + if (first_half != second_half) { + if (!half_decoder_.DecodeNextBit()) { std::swap(first_half, second_half); + } + } levels[axis] += 1; - if (first_half) + if (first_half) { status_q.push(DecodingStatus(first_half, old_base, levels, axis)); - if (second_half) + } + if (second_half) { status_q.push(DecodingStatus(second_half, new_base, levels, axis)); + } } } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.cc index ee10595003b..ee10595003b 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h index 9a3e8d76f8c..b8811092ed7 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h @@ -204,8 +204,9 @@ bool IntegerPointsKdTreeEncoder<PointDiT, compression_level_t>::EncodePoints( buffer->Encode(bit_length_); buffer->Encode(num_points_); - if (num_points_ == 0) + if (num_points_ == 0) { return true; + } numbers_encoder_.StartEncoding(); remaining_bits_encoder_.StartEncoding(); @@ -228,8 +229,9 @@ uint32_t IntegerPointsKdTreeEncoder<PointDiT, compression_level_t>::GetAxis( RandomAccessIteratorT begin, RandomAccessIteratorT end, const PointDiT &old_base, std::array<uint32_t, D> levels, uint32_t last_axis) { - if (!Policy::select_axis) + if (!Policy::select_axis) { return DRACO_INCREMENT_MOD(last_axis, D); + } // For many points this function selects the axis that should be used // for the split by keeping as many points as possible bundled. @@ -256,8 +258,9 @@ uint32_t IntegerPointsKdTreeEncoder<PointDiT, compression_level_t>::GetAxis( PointDiT split(old_base); for (int i = 0; i < D; i++) { - if (num_remaining_bits[i]) + if (num_remaining_bits[i]) { split[i] += 1 << (num_remaining_bits[i] - 1); + } } std::array<uint32_t, D> deviations = PointTraits<PointDiT>::ZeroArray(); @@ -316,8 +319,9 @@ void IntegerPointsKdTreeEncoder<PointDiT, compression_level_t>::EncodeInternal( const uint32_t num_remaining_points = end - begin; // If this happens all axis are subdivided to the end. - if ((bit_length_ - level) == 0) + if ((bit_length_ - level) == 0) { continue; + } // Fast encoding of remaining bits if number of points is 1. // Doing this also for 2 gives a slight additional speed up. @@ -361,8 +365,9 @@ void IntegerPointsKdTreeEncoder<PointDiT, compression_level_t>::EncodeInternal( const uint32_t second_half = end - split; const bool left = first_half < second_half; - if (first_half != second_half) + if (first_half != second_half) { half_encoder_.EncodeBit(left); + } if (left) { EncodeNumber(required_bits, num_remaining_points / 2 - first_half); @@ -371,12 +376,14 @@ void IntegerPointsKdTreeEncoder<PointDiT, compression_level_t>::EncodeInternal( } levels[axis] += 1; - if (split != begin) + if (split != begin) { status_q.push(EncodingStatus<RandomAccessIteratorT>( begin, split, old_base, levels, axis)); - if (split != end) + } + if (split != end) { status_q.push(EncodingStatus<RandomAccessIteratorT>(split, end, new_base, levels, axis)); + } } } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h index 9541c966856..9541c966856 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_types.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/point_cloud_types.h index 3ed1d13e054..893efbefa32 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_types.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/point_cloud_types.h @@ -16,6 +16,7 @@ #define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_POINT_CLOUD_TYPES_H_ #include <inttypes.h> + #include <vector> #include "draco/core/vector_d.h" diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/quantize_points_3.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h index 771173032f6..01943ad9e6c 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/quantize_points_3.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h @@ -16,6 +16,7 @@ #define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_QUANTIZE_POINTS_3_H_ #include <inttypes.h> + #include "draco/compression/point_cloud/algorithms/point_cloud_types.h" #include "draco/core/quantization_utils.h" diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/queuing_policy.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/queuing_policy.h index 2db0ea213b8..2db0ea213b8 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/queuing_policy.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/queuing_policy.h diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc index cf5d997e67a..5196edf960c 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc @@ -28,20 +28,27 @@ PointCloudDecoder::PointCloudDecoder() Status PointCloudDecoder::DecodeHeader(DecoderBuffer *buffer, DracoHeader *out_header) { constexpr char kIoErrorMsg[] = "Failed to parse Draco header."; - if (!buffer->Decode(out_header->draco_string, 5)) + if (!buffer->Decode(out_header->draco_string, 5)) { return Status(Status::IO_ERROR, kIoErrorMsg); - if (memcmp(out_header->draco_string, "DRACO", 5) != 0) + } + if (memcmp(out_header->draco_string, "DRACO", 5) != 0) { return Status(Status::DRACO_ERROR, "Not a Draco file."); - if (!buffer->Decode(&(out_header->version_major))) + } + if (!buffer->Decode(&(out_header->version_major))) { return Status(Status::IO_ERROR, kIoErrorMsg); - if (!buffer->Decode(&(out_header->version_minor))) + } + if (!buffer->Decode(&(out_header->version_minor))) { return Status(Status::IO_ERROR, kIoErrorMsg); - if (!buffer->Decode(&(out_header->encoder_type))) + } + if (!buffer->Decode(&(out_header->encoder_type))) { return Status(Status::IO_ERROR, kIoErrorMsg); - if (!buffer->Decode(&(out_header->encoder_method))) + } + if (!buffer->Decode(&(out_header->encoder_method))) { return Status(Status::IO_ERROR, kIoErrorMsg); - if (!buffer->Decode(&(out_header->flags))) + } + if (!buffer->Decode(&(out_header->flags))) { return Status(Status::IO_ERROR, kIoErrorMsg); + } return OkStatus(); } @@ -49,8 +56,9 @@ Status PointCloudDecoder::DecodeMetadata() { std::unique_ptr<GeometryMetadata> metadata = std::unique_ptr<GeometryMetadata>(new GeometryMetadata()); MetadataDecoder metadata_decoder; - if (!metadata_decoder.DecodeGeometryMetadata(buffer_, metadata.get())) + if (!metadata_decoder.DecodeGeometryMetadata(buffer_, metadata.get())) { return Status(Status::DRACO_ERROR, "Failed to decode metadata."); + } point_cloud_->AddMetadata(std::move(metadata)); return OkStatus(); } @@ -65,9 +73,10 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options, DRACO_RETURN_IF_ERROR(DecodeHeader(buffer_, &header)) // Sanity check that we are really using the right decoder (mostly for cases // where the Decode method was called manually outside of our main API. - if (header.encoder_type != GetGeometryType()) + if (header.encoder_type != GetGeometryType()) { return Status(Status::DRACO_ERROR, "Using incompatible decoder for the input geometry."); + } // TODO(ostava): We should check the method as well, but currently decoders // don't expose the decoding method id. version_major_ = header.version_major; @@ -80,11 +89,13 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options, header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor : kDracoMeshBitstreamVersionMinor; // Check for version compatibility. - if (version_major_ < 1 || version_major_ > max_supported_major_version) + if (version_major_ < 1 || version_major_ > max_supported_major_version) { return Status(Status::UNKNOWN_VERSION, "Unknown major version."); + } if (version_major_ == max_supported_major_version && - version_minor_ > max_supported_minor_version) + version_minor_ > max_supported_minor_version) { return Status(Status::UNKNOWN_VERSION, "Unknown minor version."); + } buffer_->set_bitstream_version( DRACO_BITSTREAM_VERSION(version_major_, version_minor_)); @@ -92,37 +103,44 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options, (header.flags & METADATA_FLAG_MASK)) { DRACO_RETURN_IF_ERROR(DecodeMetadata()) } - if (!InitializeDecoder()) + if (!InitializeDecoder()) { return Status(Status::DRACO_ERROR, "Failed to initialize the decoder."); - if (!DecodeGeometryData()) + } + if (!DecodeGeometryData()) { return Status(Status::DRACO_ERROR, "Failed to decode geometry data."); - if (!DecodePointAttributes()) + } + if (!DecodePointAttributes()) { return Status(Status::DRACO_ERROR, "Failed to decode point attributes."); + } return OkStatus(); } bool PointCloudDecoder::DecodePointAttributes() { uint8_t num_attributes_decoders; - if (!buffer_->Decode(&num_attributes_decoders)) + if (!buffer_->Decode(&num_attributes_decoders)) { return false; + } // Create all attribute decoders. This is implementation specific and the // derived classes can use any data encoded in the // PointCloudEncoder::EncodeAttributesEncoderIdentifier() call. for (int i = 0; i < num_attributes_decoders; ++i) { - if (!CreateAttributesDecoder(i)) + if (!CreateAttributesDecoder(i)) { return false; + } } // Initialize all attributes decoders. No data is decoded here. for (auto &att_dec : attributes_decoders_) { - if (!att_dec->Init(this, point_cloud_)) + if (!att_dec->Init(this, point_cloud_)) { return false; + } } // Decode any data needed by the attribute decoders. for (int i = 0; i < num_attributes_decoders; ++i) { - if (!attributes_decoders_[i]->DecodeAttributesDecoderData(buffer_)) + if (!attributes_decoders_[i]->DecodeAttributesDecoderData(buffer_)) { return false; + } } // Create map between attribute and decoder ids. @@ -138,26 +156,30 @@ bool PointCloudDecoder::DecodePointAttributes() { } // Decode the actual attributes using the created attribute decoders. - if (!DecodeAllAttributes()) + if (!DecodeAllAttributes()) { return false; + } - if (!OnAttributesDecoded()) + if (!OnAttributesDecoded()) { return false; + } return true; } bool PointCloudDecoder::DecodeAllAttributes() { for (auto &att_dec : attributes_decoders_) { - if (!att_dec->DecodeAttributes(buffer_)) + if (!att_dec->DecodeAttributes(buffer_)) { return false; + } } return true; } const PointAttribute *PointCloudDecoder::GetPortableAttribute( int32_t parent_att_id) { - if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) + if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) { return nullptr; + } const int32_t parent_att_decoder_id = attribute_to_decoder_map_[parent_att_id]; return attributes_decoders_[parent_att_decoder_id]->GetPortableAttribute( diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.h index abcb5e068f7..4af7f5cd32c 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.h @@ -42,10 +42,12 @@ class PointCloudDecoder { bool SetAttributesDecoder( int att_decoder_id, std::unique_ptr<AttributesDecoderInterface> decoder) { - if (att_decoder_id < 0) + if (att_decoder_id < 0) { return false; - if (att_decoder_id >= static_cast<int>(attributes_decoders_.size())) + } + if (att_decoder_id >= static_cast<int>(attributes_decoders_.size())) { attributes_decoders_.resize(att_decoder_id + 1); + } attributes_decoders_[att_decoder_id] = std::move(decoder); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc index 986706582f0..b4b0ee94093 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc @@ -35,19 +35,24 @@ Status PointCloudEncoder::Encode(const EncoderOptions &options, attribute_to_encoder_map_.clear(); attributes_encoder_ids_order_.clear(); - if (!point_cloud_) + if (!point_cloud_) { return Status(Status::DRACO_ERROR, "Invalid input geometry."); + } DRACO_RETURN_IF_ERROR(EncodeHeader()) DRACO_RETURN_IF_ERROR(EncodeMetadata()) - if (!InitializeEncoder()) + if (!InitializeEncoder()) { return Status(Status::DRACO_ERROR, "Failed to initialize encoder."); - if (!EncodeEncoderData()) + } + if (!EncodeEncoderData()) { return Status(Status::DRACO_ERROR, "Failed to encode internal data."); + } DRACO_RETURN_IF_ERROR(EncodeGeometryData()); - if (!EncodePointAttributes()) + if (!EncodePointAttributes()) { return Status(Status::DRACO_ERROR, "Failed to encode point attributes."); - if (options.GetGlobalBool("store_number_of_encoded_points", false)) + } + if (options.GetGlobalBool("store_number_of_encoded_points", false)) { ComputeNumberOfEncodedPoints(); + } return OkStatus(); } @@ -92,8 +97,9 @@ Status PointCloudEncoder::EncodeMetadata() { } bool PointCloudEncoder::EncodePointAttributes() { - if (!GenerateAttributesEncoders()) + if (!GenerateAttributesEncoders()) { return false; + } // Encode the number of attribute encoders. buffer_->Encode(static_cast<uint8_t>(attributes_encoders_.size())); @@ -101,39 +107,45 @@ bool PointCloudEncoder::EncodePointAttributes() { // Initialize all the encoders (this is used for example to init attribute // dependencies, no data is encoded in this step). for (auto &att_enc : attributes_encoders_) { - if (!att_enc->Init(this, point_cloud_)) + if (!att_enc->Init(this, point_cloud_)) { return false; + } } // Rearrange attributes to respect dependencies between individual attributes. - if (!RearrangeAttributesEncoders()) + if (!RearrangeAttributesEncoders()) { return false; + } // Encode any data that is necessary to create the corresponding attribute // decoder. for (int att_encoder_id : attributes_encoder_ids_order_) { - if (!EncodeAttributesEncoderIdentifier(att_encoder_id)) + if (!EncodeAttributesEncoderIdentifier(att_encoder_id)) { return false; + } } // Also encode any attribute encoder data (such as the info about encoded // attributes). for (int att_encoder_id : attributes_encoder_ids_order_) { if (!attributes_encoders_[att_encoder_id]->EncodeAttributesEncoderData( - buffer_)) + buffer_)) { return false; + } } // Lastly encode all the attributes using the provided attribute encoders. - if (!EncodeAllAttributes()) + if (!EncodeAllAttributes()) { return false; + } return true; } bool PointCloudEncoder::GenerateAttributesEncoders() { for (int i = 0; i < point_cloud_->num_attributes(); ++i) { - if (!GenerateAttributesEncoder(i)) + if (!GenerateAttributesEncoder(i)) { return false; + } } attribute_to_encoder_map_.resize(point_cloud_->num_attributes()); for (uint32_t i = 0; i < attributes_encoders_.size(); ++i) { @@ -146,27 +158,31 @@ bool PointCloudEncoder::GenerateAttributesEncoders() { bool PointCloudEncoder::EncodeAllAttributes() { for (int att_encoder_id : attributes_encoder_ids_order_) { - if (!attributes_encoders_[att_encoder_id]->EncodeAttributes(buffer_)) + if (!attributes_encoders_[att_encoder_id]->EncodeAttributes(buffer_)) { return false; + } } return true; } bool PointCloudEncoder::MarkParentAttribute(int32_t parent_att_id) { - if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) + if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) { return false; + } const int32_t parent_att_encoder_id = attribute_to_encoder_map_[parent_att_id]; if (!attributes_encoders_[parent_att_encoder_id]->MarkParentAttribute( - parent_att_id)) + parent_att_id)) { return false; + } return true; } const PointAttribute *PointCloudEncoder::GetPortableAttribute( int32_t parent_att_id) { - if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) + if (parent_att_id < 0 || parent_att_id >= point_cloud_->num_attributes()) { return nullptr; + } const int32_t parent_att_encoder_id = attribute_to_encoder_map_[parent_att_id]; return attributes_encoders_[parent_att_encoder_id]->GetPortableAttribute( @@ -193,8 +209,9 @@ bool PointCloudEncoder::RearrangeAttributesEncoders() { // Flagged when any of the encoder get processed. bool encoder_processed = false; for (uint32_t i = 0; i < attributes_encoders_.size(); ++i) { - if (is_encoder_processed[i]) + if (is_encoder_processed[i]) { continue; // Encoder already processed. + } // Check if all parent encoders are already processed. bool can_be_processed = true; for (uint32_t p = 0; p < attributes_encoders_[i]->num_attributes(); ++p) { @@ -211,8 +228,9 @@ bool PointCloudEncoder::RearrangeAttributesEncoders() { } } } - if (!can_be_processed) + if (!can_be_processed) { continue; // Try to process the encoder in the next iteration. + } // Encoder can be processed. Update the encoding order. attributes_encoder_ids_order_[num_processed_encoders++] = i; is_encoder_processed[i] = true; @@ -238,8 +256,9 @@ bool PointCloudEncoder::RearrangeAttributesEncoders() { const int ae = attributes_encoder_ids_order_[ae_order]; const int32_t num_encoder_attributes = attributes_encoders_[ae]->num_attributes(); - if (num_encoder_attributes < 2) + if (num_encoder_attributes < 2) { continue; // No need to resolve dependencies for a single attribute. + } num_processed_attributes = 0; attribute_encoding_order.resize(num_encoder_attributes); while (num_processed_attributes < num_encoder_attributes) { @@ -247,8 +266,9 @@ bool PointCloudEncoder::RearrangeAttributesEncoders() { bool attribute_processed = false; for (int i = 0; i < num_encoder_attributes; ++i) { const int32_t att_id = attributes_encoders_[ae]->GetAttributeId(i); - if (is_attribute_processed[i]) + if (is_attribute_processed[i]) { continue; // Attribute already processed. + } // Check if all parent attributes are already processed. bool can_be_processed = true; for (int p = 0; @@ -260,8 +280,9 @@ bool PointCloudEncoder::RearrangeAttributesEncoders() { break; } } - if (!can_be_processed) + if (!can_be_processed) { continue; // Try to process the attribute in the next iteration. + } // Attribute can be processed. Update the encoding order. attribute_encoding_order[num_processed_attributes++] = i; is_attribute_processed[i] = true; diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.h index 8883f17a789..8883f17a789 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.cc index c35fd79df60..2deebbc4853 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.cc @@ -20,10 +20,12 @@ namespace draco { bool PointCloudKdTreeDecoder::DecodeGeometryData() { int32_t num_points; - if (!buffer()->Decode(&num_points)) + if (!buffer()->Decode(&num_points)) { return false; - if (num_points < 0) + } + if (num_points < 0) { return false; + } point_cloud()->set_num_points(num_points); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.h index 6e192f2a5a0..6e192f2a5a0 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc index 6d0446baad1..92b6c84cd63 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/compression/point_cloud/point_cloud_kd_tree_encoder.h" + #include "draco/compression/attributes/kd_tree_attributes_encoder.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h index 6acbb949d40..6acbb949d40 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc index 614cf37b266..b9382d31070 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_decoder.cc @@ -21,8 +21,9 @@ namespace draco { bool PointCloudSequentialDecoder::DecodeGeometryData() { int32_t num_points; - if (!buffer()->Decode(&num_points)) + if (!buffer()->Decode(&num_points)) { return false; + } point_cloud()->set_num_points(num_points); return true; } diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_decoder.h index 9968dc27517..9968dc27517 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_decoder.h diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc index fa7b6fd905c..fa7b6fd905c 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h index 40d8edcdbb0..40d8edcdbb0 100644 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h diff --git a/extern/draco/dracoenc/src/draco/core/bit_utils.cc b/extern/draco/draco/src/draco/core/bit_utils.cc index 37119a7171b..37119a7171b 100644 --- a/extern/draco/dracoenc/src/draco/core/bit_utils.cc +++ b/extern/draco/draco/src/draco/core/bit_utils.cc diff --git a/extern/draco/dracoenc/src/draco/core/bit_utils.h b/extern/draco/draco/src/draco/core/bit_utils.h index f63cd0750c9..a102095c719 100644 --- a/extern/draco/dracoenc/src/draco/core/bit_utils.h +++ b/extern/draco/draco/src/draco/core/bit_utils.h @@ -20,6 +20,7 @@ #include <inttypes.h> #include <stdint.h> + #include <type_traits> #if defined(_MSC_VER) diff --git a/extern/draco/dracoenc/src/draco/core/bounding_box.cc b/extern/draco/draco/src/draco/core/bounding_box.cc index d95b1e90759..d95b1e90759 100644 --- a/extern/draco/dracoenc/src/draco/core/bounding_box.cc +++ b/extern/draco/draco/src/draco/core/bounding_box.cc diff --git a/extern/draco/dracoenc/src/draco/core/bounding_box.h b/extern/draco/draco/src/draco/core/bounding_box.h index 0259267c99c..1c20fad8bf2 100644 --- a/extern/draco/dracoenc/src/draco/core/bounding_box.h +++ b/extern/draco/draco/src/draco/core/bounding_box.h @@ -36,10 +36,12 @@ class BoundingBox { // argument to an iterator. inline void update_bounding_box(const Vector3f &new_point) { for (int i = 0; i < 3; i++) { - if (new_point[i] < min_point_[i]) + if (new_point[i] < min_point_[i]) { min_point_[i] = new_point[i]; - if (new_point[i] > max_point_[i]) + } + if (new_point[i] > max_point_[i]) { max_point_[i] = new_point[i]; + } } } diff --git a/extern/draco/dracoenc/src/draco/core/cycle_timer.cc b/extern/draco/draco/src/draco/core/cycle_timer.cc index 1eea9f59702..94b4b28b2f9 100644 --- a/extern/draco/dracoenc/src/draco/core/cycle_timer.cc +++ b/extern/draco/draco/src/draco/core/cycle_timer.cc @@ -19,7 +19,7 @@ void DracoTimer::Start() { #ifdef _WIN32 QueryPerformanceCounter(&tv_start); #else - gettimeofday(&tv_start, NULL); + gettimeofday(&tv_start, nullptr); #endif } @@ -27,7 +27,7 @@ void DracoTimer::Stop() { #ifdef _WIN32 QueryPerformanceCounter(&tv_end); #else - gettimeofday(&tv_end, NULL); + gettimeofday(&tv_end, nullptr); #endif } diff --git a/extern/draco/dracoenc/src/draco/core/cycle_timer.h b/extern/draco/draco/src/draco/core/cycle_timer.h index 172f1c2e9b5..172f1c2e9b5 100644 --- a/extern/draco/dracoenc/src/draco/core/cycle_timer.h +++ b/extern/draco/draco/src/draco/core/cycle_timer.h diff --git a/extern/draco/dracoenc/src/draco/core/data_buffer.cc b/extern/draco/draco/src/draco/core/data_buffer.cc index 867760a6fcc..f0b43d67dbd 100644 --- a/extern/draco/dracoenc/src/draco/core/data_buffer.cc +++ b/extern/draco/draco/src/draco/core/data_buffer.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/core/data_buffer.h" + #include <algorithm> namespace draco { @@ -26,15 +27,18 @@ bool DataBuffer::Update(const void *data, int64_t size) { bool DataBuffer::Update(const void *data, int64_t size, int64_t offset) { if (data == nullptr) { - if (size + offset < 0) + if (size + offset < 0) { return false; + } // If no data is provided, just resize the buffer. data_.resize(size + offset); } else { - if (size < 0) + if (size < 0) { return false; - if (size + offset > static_cast<int64_t>(data_.size())) + } + if (size + offset > static_cast<int64_t>(data_.size())) { data_.resize(size + offset); + } const uint8_t *const byte_data = static_cast<const uint8_t *>(data); std::copy(byte_data, byte_data + size, data_.data() + offset); } @@ -48,8 +52,9 @@ void DataBuffer::Resize(int64_t size) { } void DataBuffer::WriteDataToStream(std::ostream &stream) { - if (data_.size() == 0) + if (data_.size() == 0) { return; + } stream.write(reinterpret_cast<char *>(data_.data()), data_.size()); } diff --git a/extern/draco/dracoenc/src/draco/core/data_buffer.h b/extern/draco/draco/src/draco/core/data_buffer.h index 8ee690540bc..8ee690540bc 100644 --- a/extern/draco/dracoenc/src/draco/core/data_buffer.h +++ b/extern/draco/draco/src/draco/core/data_buffer.h diff --git a/extern/draco/dracoenc/src/draco/core/decoder_buffer.cc b/extern/draco/draco/src/draco/core/decoder_buffer.cc index 5ce1f064ac2..4e8ed618d92 100644 --- a/extern/draco/dracoenc/src/draco/core/decoder_buffer.cc +++ b/extern/draco/draco/src/draco/core/decoder_buffer.cc @@ -41,13 +41,15 @@ bool DecoderBuffer::StartBitDecoding(bool decode_size, uint64_t *out_size) { if (decode_size) { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (bitstream_version_ < DRACO_BITSTREAM_VERSION(2, 2)) { - if (!Decode(out_size)) + if (!Decode(out_size)) { return false; + } } else #endif { - if (!DecodeVarint(out_size, this)) + if (!DecodeVarint(out_size, this)) { return false; + } } } bit_mode_ = true; diff --git a/extern/draco/dracoenc/src/draco/core/decoder_buffer.h b/extern/draco/draco/src/draco/core/decoder_buffer.h index 5e3d1ac738d..0559abbe415 100644 --- a/extern/draco/dracoenc/src/draco/core/decoder_buffer.h +++ b/extern/draco/draco/src/draco/core/decoder_buffer.h @@ -16,12 +16,12 @@ #define DRACO_CORE_DECODER_BUFFER_H_ #include <stdint.h> + #include <cstring> #include <memory> -#include "draco/draco_features.h" - #include "draco/core/macros.h" +#include "draco/draco_features.h" namespace draco { @@ -55,8 +55,9 @@ class DecoderBuffer { // Decodes up to 32 bits into out_val. Can be called only in between // StartBitDecoding and EndBitDecoding. Otherwise returns false. bool DecodeLeastSignificantBits32(int nbits, uint32_t *out_value) { - if (!bit_decoder_active()) + if (!bit_decoder_active()) { return false; + } bit_decoder_.GetBits(nbits, out_value); return true; } @@ -66,15 +67,17 @@ class DecoderBuffer { // Returns false on error. template <typename T> bool Decode(T *out_val) { - if (!Peek(out_val)) + if (!Peek(out_val)) { return false; + } pos_ += sizeof(T); return true; } bool Decode(void *out_data, size_t size_to_decode) { - if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) + if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { return false; // Buffer overflow. + } memcpy(out_data, (data_ + pos_), size_to_decode); pos_ += size_to_decode; return true; @@ -84,15 +87,17 @@ class DecoderBuffer { template <typename T> bool Peek(T *out_val) { const size_t size_to_decode = sizeof(T); - if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) + if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { return false; // Buffer overflow. + } memcpy(out_val, (data_ + pos_), size_to_decode); return true; } bool Peek(void *out_data, size_t size_to_peek) { - if (data_size_ < static_cast<int64_t>(pos_ + size_to_peek)) + if (data_size_ < static_cast<int64_t>(pos_ + size_to_peek)) { return false; // Buffer overflow. + } memcpy(out_data, (data_ + pos_), size_to_peek); return true; } @@ -157,8 +162,9 @@ class DecoderBuffer { DRACO_DCHECK_GE(nbits, 0); DRACO_DCHECK_LE(nbits, 32); uint32_t value = 0; - for (int32_t bit = 0; bit < nbits; ++bit) + for (int32_t bit = 0; bit < nbits; ++bit) { value |= GetBit() << bit; + } *x = value; return true; } diff --git a/extern/draco/dracoenc/src/draco/core/divide.cc b/extern/draco/draco/src/draco/core/divide.cc index 6d2e57120c8..6d2e57120c8 100644 --- a/extern/draco/dracoenc/src/draco/core/divide.cc +++ b/extern/draco/draco/src/draco/core/divide.cc diff --git a/extern/draco/dracoenc/src/draco/core/divide.h b/extern/draco/draco/src/draco/core/divide.h index 2217c861e0b..7e3838a008c 100644 --- a/extern/draco/dracoenc/src/draco/core/divide.h +++ b/extern/draco/draco/src/draco/core/divide.h @@ -19,6 +19,7 @@ // This file is based off libvpx's divide.h. #include <stdint.h> + #include <climits> namespace draco { diff --git a/extern/draco/dracoenc/src/draco/core/draco_index_type.h b/extern/draco/draco/src/draco/core/draco_index_type.h index d9dd3f64fa8..d9dd3f64fa8 100644 --- a/extern/draco/dracoenc/src/draco/core/draco_index_type.h +++ b/extern/draco/draco/src/draco/core/draco_index_type.h diff --git a/extern/draco/dracoenc/src/draco/core/draco_index_type_vector.h b/extern/draco/draco/src/draco/core/draco_index_type_vector.h index e2062ef3f35..d47ab3b04eb 100644 --- a/extern/draco/dracoenc/src/draco/core/draco_index_type_vector.h +++ b/extern/draco/draco/src/draco/core/draco_index_type_vector.h @@ -28,7 +28,7 @@ namespace draco { // draco_index_type.h . // TODO(ostava): Make the interface more complete. It's currently missing // features such as iterators. -// TODO(draco-eng): Make unit tests for this class. +// TODO(vytyaz): Add more unit tests for this class. template <class IndexTypeT, class ValueTypeT> class IndexTypeVector { public: @@ -50,10 +50,16 @@ class IndexTypeVector { } size_t size() const { return vector_.size(); } + bool empty() const { return vector_.empty(); } void push_back(const ValueTypeT &val) { vector_.push_back(val); } void push_back(ValueTypeT &&val) { vector_.push_back(std::move(val)); } + template <typename... Args> + void emplace_back(Args &&... args) { + vector_.emplace_back(std::forward<Args>(args)...); + } + inline reference operator[](const IndexTypeT &index) { return vector_[index.value()]; } diff --git a/extern/draco/dracoenc/src/draco/core/draco_types.cc b/extern/draco/draco/src/draco/core/draco_types.cc index 9bde05fda80..9bde05fda80 100644 --- a/extern/draco/dracoenc/src/draco/core/draco_types.cc +++ b/extern/draco/draco/src/draco/core/draco_types.cc diff --git a/extern/draco/dracoenc/src/draco/core/draco_types.h b/extern/draco/draco/src/draco/core/draco_types.h index f5a21e4f1d0..d14437a0214 100644 --- a/extern/draco/dracoenc/src/draco/core/draco_types.h +++ b/extern/draco/draco/src/draco/core/draco_types.h @@ -16,6 +16,7 @@ #define DRACO_CORE_DRACO_TYPES_H_ #include <stdint.h> + #include <string> #include "draco/draco_features.h" diff --git a/extern/draco/dracoenc/src/draco/core/draco_version.h b/extern/draco/draco/src/draco/core/draco_version.h index 9d3a67e4f8e..ffd7948c64d 100644 --- a/extern/draco/dracoenc/src/draco/core/draco_version.h +++ b/extern/draco/draco/src/draco/core/draco_version.h @@ -18,7 +18,7 @@ namespace draco { // Draco version is comprised of <major>.<minor>.<revision>. -static const char kDracoVersion[] = "1.3.5"; +static const char kDracoVersion[] = "1.3.6"; const char *Version() { return kDracoVersion; } diff --git a/extern/draco/dracoenc/src/draco/core/encoder_buffer.cc b/extern/draco/draco/src/draco/core/encoder_buffer.cc index a5e936fd89b..df98677a85b 100644 --- a/extern/draco/dracoenc/src/draco/core/encoder_buffer.cc +++ b/extern/draco/draco/src/draco/core/encoder_buffer.cc @@ -31,10 +31,12 @@ void EncoderBuffer::Clear() { void EncoderBuffer::Resize(int64_t nbytes) { buffer_.resize(nbytes); } bool EncoderBuffer::StartBitEncoding(int64_t required_bits, bool encode_size) { - if (bit_encoder_active()) + if (bit_encoder_active()) { return false; // Bit encoding mode already active. - if (required_bits <= 0) + } + if (required_bits <= 0) { return false; // Invalid size. + } encode_bit_sequence_size_ = encode_size; const int64_t required_bytes = (required_bits + 7) / 8; bit_encoder_reserved_bytes_ = required_bytes; @@ -54,8 +56,9 @@ bool EncoderBuffer::StartBitEncoding(int64_t required_bits, bool encode_size) { } void EncoderBuffer::EndBitEncoding() { - if (!bit_encoder_active()) + if (!bit_encoder_active()) { return; + } // Get the number of encoded bits and bytes (rounded up). const uint64_t encoded_bits = bit_encoder_->Bits(); const uint64_t encoded_bytes = (encoded_bits + 7) / 8; diff --git a/extern/draco/dracoenc/src/draco/core/encoder_buffer.h b/extern/draco/draco/src/draco/core/encoder_buffer.h index ff3e89ba270..b153a629792 100644 --- a/extern/draco/dracoenc/src/draco/core/encoder_buffer.h +++ b/extern/draco/draco/src/draco/core/encoder_buffer.h @@ -47,8 +47,9 @@ class EncoderBuffer { // Encode up to 32 bits into the buffer. Can be called only in between // StartBitEncoding and EndBitEncoding. Otherwise returns false. bool EncodeLeastSignificantBits32(int nbits, uint32_t value) { - if (!bit_encoder_active()) + if (!bit_encoder_active()) { return false; + } bit_encoder_->PutBits(value, nbits); return true; } @@ -57,15 +58,17 @@ class EncoderBuffer { // Returns false when the value couldn't be encoded. template <typename T> bool Encode(const T &data) { - if (bit_encoder_active()) + if (bit_encoder_active()) { return false; + } const uint8_t *src_data = reinterpret_cast<const uint8_t *>(&data); buffer_.insert(buffer_.end(), src_data, src_data + sizeof(T)); return true; } bool Encode(const void *data, size_t data_size) { - if (bit_encoder_active()) + if (bit_encoder_active()) { return false; + } const uint8_t *src_data = reinterpret_cast<const uint8_t *>(data); buffer_.insert(buffer_.end(), src_data, src_data + data_size); return true; @@ -87,8 +90,9 @@ class EncoderBuffer { void PutBits(uint32_t data, int32_t nbits) { DRACO_DCHECK_GE(nbits, 0); DRACO_DCHECK_LE(nbits, 32); - for (int32_t bit = 0; bit < nbits; ++bit) + for (int32_t bit = 0; bit < nbits; ++bit) { PutBit((data >> bit) & 1); + } } // Return number of bits encoded so far. diff --git a/extern/draco/dracoenc/src/draco/core/hash_utils.cc b/extern/draco/draco/src/draco/core/hash_utils.cc index 9a78c2cfafd..fbbd653f369 100644 --- a/extern/draco/dracoenc/src/draco/core/hash_utils.cc +++ b/extern/draco/draco/src/draco/core/hash_utils.cc @@ -50,8 +50,9 @@ uint64_t FingerprintString(const char *s, size_t len) { hash = HashCombine(new_hash, hash); } - if (hash < std::numeric_limits<uint64_t>::max() - 1) + if (hash < std::numeric_limits<uint64_t>::max() - 1) { hash += 2; + } return hash; } } // namespace draco diff --git a/extern/draco/dracoenc/src/draco/core/hash_utils.h b/extern/draco/draco/src/draco/core/hash_utils.h index 0e8da60aa54..aa61523e7fe 100644 --- a/extern/draco/dracoenc/src/draco/core/hash_utils.h +++ b/extern/draco/draco/src/draco/core/hash_utils.h @@ -16,9 +16,9 @@ #define DRACO_CORE_HASH_UTILS_H_ #include <stdint.h> -#include <functional> -// TODO(fgalligan): Move this to core. +#include <cstddef> +#include <functional> namespace draco { diff --git a/extern/draco/dracoenc/src/draco/core/macros.h b/extern/draco/draco/src/draco/core/macros.h index 09819e63969..89b706e53a5 100644 --- a/extern/draco/dracoenc/src/draco/core/macros.h +++ b/extern/draco/draco/src/draco/core/macros.h @@ -16,7 +16,6 @@ #define DRACO_CORE_MACROS_H_ #include "assert.h" - #include "draco/draco_features.h" #ifdef ANDROID_LOGGING diff --git a/extern/draco/dracoenc/src/draco/core/math_utils.h b/extern/draco/draco/src/draco/core/math_utils.h index 50cf5d57199..7f382fa34d4 100644 --- a/extern/draco/dracoenc/src/draco/core/math_utils.h +++ b/extern/draco/draco/src/draco/core/math_utils.h @@ -27,8 +27,9 @@ // replacement for std::sqrt() for general cases. IntSqrt is in fact about 3X // slower compared to most implementation of std::sqrt(). inline uint64_t IntSqrt(uint64_t number) { - if (number == 0) + if (number == 0) { return 0; + } // First estimate good initial value of the square root as log2(number). uint64_t act_number = number; uint64_t square_root = 1; diff --git a/extern/draco/dracoenc/src/draco/core/options.cc b/extern/draco/draco/src/draco/core/options.cc index a9ce14b9837..9b81db48987 100644 --- a/extern/draco/dracoenc/src/draco/core/options.cc +++ b/extern/draco/draco/src/draco/core/options.cc @@ -23,8 +23,9 @@ namespace draco { Options::Options() {} void Options::MergeAndReplace(const Options &other_options) { - for (const auto &item : other_options.options_) + for (const auto &item : other_options.options_) { options_[item.first] = item.second; + } } void Options::SetInt(const std::string &name, int val) { @@ -47,8 +48,9 @@ int Options::GetInt(const std::string &name) const { return GetInt(name, -1); } int Options::GetInt(const std::string &name, int default_val) const { const auto it = options_.find(name); - if (it == options_.end()) + if (it == options_.end()) { return default_val; + } return std::atoi(it->second.c_str()); } @@ -58,8 +60,9 @@ float Options::GetFloat(const std::string &name) const { float Options::GetFloat(const std::string &name, float default_val) const { const auto it = options_.find(name); - if (it == options_.end()) + if (it == options_.end()) { return default_val; + } return static_cast<float>(std::atof(it->second.c_str())); } @@ -69,8 +72,9 @@ bool Options::GetBool(const std::string &name) const { bool Options::GetBool(const std::string &name, bool default_val) const { const int ret = GetInt(name, -1); - if (ret == -1) + if (ret == -1) { return default_val; + } return static_cast<bool>(ret); } @@ -81,8 +85,9 @@ std::string Options::GetString(const std::string &name) const { std::string Options::GetString(const std::string &name, const std::string &default_val) const { const auto it = options_.find(name); - if (it == options_.end()) + if (it == options_.end()) { return default_val; + } return it->second; } diff --git a/extern/draco/dracoenc/src/draco/core/options.h b/extern/draco/draco/src/draco/core/options.h index 4995299633c..1bc4dc0fb7b 100644 --- a/extern/draco/dracoenc/src/draco/core/options.h +++ b/extern/draco/draco/src/draco/core/options.h @@ -81,8 +81,9 @@ void Options::SetVector(const std::string &name, const DataTypeT *vec, int num_dims) { std::string out; for (int i = 0; i < num_dims; ++i) { - if (i > 0) + if (i > 0) { out += " "; + } // GNU STL on android doesn't include a proper std::to_string, but the libc++ // version does @@ -107,11 +108,13 @@ template <typename DataTypeT> bool Options::GetVector(const std::string &name, int num_dims, DataTypeT *out_val) const { const auto it = options_.find(name); - if (it == options_.end()) + if (it == options_.end()) { return false; + } const std::string value = it->second; - if (value.length() == 0) + if (value.length() == 0) { return true; // Option set but no data is present + } const char *act_str = value.c_str(); char *next_str; for (int i = 0; i < num_dims; ++i) { @@ -119,10 +122,11 @@ bool Options::GetVector(const std::string &name, int num_dims, #ifdef ANDROID const int val = strtol(act_str, &next_str, 10); #else - const int val = std::strtol(act_str, &next_str, 10); + const int val = static_cast<int>(std::strtol(act_str, &next_str, 10)); #endif - if (act_str == next_str) + if (act_str == next_str) { return true; // End reached. + } act_str = next_str; out_val[i] = static_cast<DataTypeT>(val); } else { @@ -131,8 +135,9 @@ bool Options::GetVector(const std::string &name, int num_dims, #else const float val = std::strtof(act_str, &next_str); #endif - if (act_str == next_str) + if (act_str == next_str) { return true; // End reached. + } act_str = next_str; out_val[i] = static_cast<DataTypeT>(val); } diff --git a/extern/draco/dracoenc/src/draco/core/quantization_utils.cc b/extern/draco/draco/src/draco/core/quantization_utils.cc index 26417b01998..58dcf5c8c20 100644 --- a/extern/draco/dracoenc/src/draco/core/quantization_utils.cc +++ b/extern/draco/draco/src/draco/core/quantization_utils.cc @@ -27,8 +27,9 @@ void Quantizer::Init(float delta) { inverse_delta_ = 1.f / delta; } Dequantizer::Dequantizer() : delta_(1.f) {} bool Dequantizer::Init(float range, int32_t max_quantized_value) { - if (max_quantized_value <= 0) + if (max_quantized_value <= 0) { return false; + } delta_ = range / static_cast<float>(max_quantized_value); return true; } diff --git a/extern/draco/dracoenc/src/draco/core/quantization_utils.h b/extern/draco/draco/src/draco/core/quantization_utils.h index 54910467407..0f60f1e1b17 100644 --- a/extern/draco/dracoenc/src/draco/core/quantization_utils.h +++ b/extern/draco/draco/src/draco/core/quantization_utils.h @@ -22,6 +22,7 @@ #define DRACO_CORE_QUANTIZATION_UTILS_H_ #include <stdint.h> + #include <cmath> #include "draco/core/macros.h" diff --git a/extern/draco/dracoenc/src/draco/core/status.h b/extern/draco/draco/src/draco/core/status.h index 9ac3def7cd1..449ad8566de 100644 --- a/extern/draco/dracoenc/src/draco/core/status.h +++ b/extern/draco/draco/src/draco/core/status.h @@ -31,6 +31,7 @@ class Status { UNSUPPORTED_VERSION = -4, // Input not compatible with the current version. UNKNOWN_VERSION = -5, // Input was created with an unknown version of // the library. + UNSUPPORTED_FEATURE = -6, // Input contains feature that is not supported. }; Status() : code_(OK) {} @@ -66,8 +67,9 @@ inline Status OkStatus() { return Status(Status::OK); } #define DRACO_RETURN_IF_ERROR(expression) \ { \ const draco::Status _local_status = (expression); \ - if (!_local_status.ok()) \ + if (!_local_status.ok()) { \ return _local_status; \ + } \ } } // namespace draco diff --git a/extern/draco/dracoenc/src/draco/core/status_or.h b/extern/draco/draco/src/draco/core/status_or.h index 156b9bc02a7..156b9bc02a7 100644 --- a/extern/draco/dracoenc/src/draco/core/status_or.h +++ b/extern/draco/draco/src/draco/core/status_or.h diff --git a/extern/draco/dracoenc/src/draco/core/varint_decoding.h b/extern/draco/draco/src/draco/core/varint_decoding.h index 6cd41b29220..4e86df732e0 100644 --- a/extern/draco/dracoenc/src/draco/core/varint_decoding.h +++ b/extern/draco/draco/src/draco/core/varint_decoding.h @@ -22,33 +22,54 @@ namespace draco { +namespace { + +// Decodes a specified unsigned integer as varint. |depth| is the current +// recursion call depth. The first call to the function must be 1. +template <typename IntTypeT> +bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) { + constexpr IntTypeT max_depth = sizeof(IntTypeT) + 1 + (sizeof(IntTypeT) >> 3); + if (depth > max_depth) { + return false; + } + // Coding of unsigned values. + // 0-6 bit - data + // 7 bit - next byte? + uint8_t in; + if (!buffer->Decode(&in)) { + return false; + } + if (in & (1 << 7)) { + // Next byte is available, decode it first. + if (!DecodeVarintUnsigned<IntTypeT>(depth + 1, out_val, buffer)) { + return false; + } + // Append decoded info from this byte. + *out_val <<= 7; + *out_val |= in & ((1 << 7) - 1); + } else { + // Last byte reached + *out_val = in; + } + return true; +} + +} // namespace + // Decodes a specified integer as varint. Note that the IntTypeT must be the // same as the one used in the corresponding EncodeVarint() call. template <typename IntTypeT> bool DecodeVarint(IntTypeT *out_val, DecoderBuffer *buffer) { if (std::is_unsigned<IntTypeT>::value) { - // Coding of unsigned values. - // 0-6 bit - data - // 7 bit - next byte? - uint8_t in; - if (!buffer->Decode(&in)) + if (!DecodeVarintUnsigned<IntTypeT>(1, out_val, buffer)) { return false; - if (in & (1 << 7)) { - // Next byte is available, decode it first. - if (!DecodeVarint<IntTypeT>(out_val, buffer)) - return false; - // Append decoded info from this byte. - *out_val <<= 7; - *out_val |= in & ((1 << 7) - 1); - } else { - // Last byte reached - *out_val = in; } } else { // IntTypeT is a signed value. Decode the symbol and convert to signed. typename std::make_unsigned<IntTypeT>::type symbol; - if (!DecodeVarint(&symbol, buffer)) + if (!DecodeVarintUnsigned(1, &symbol, buffer)) { return false; + } *out_val = ConvertSymbolToSignedInt(symbol); } return true; diff --git a/extern/draco/dracoenc/src/draco/core/varint_encoding.h b/extern/draco/draco/src/draco/core/varint_encoding.h index b9b6dcab78d..9a8a5393698 100644 --- a/extern/draco/dracoenc/src/draco/core/varint_encoding.h +++ b/extern/draco/draco/src/draco/core/varint_encoding.h @@ -34,20 +34,24 @@ bool EncodeVarint(IntTypeT val, EncoderBuffer *out_buffer) { out |= val & ((1 << 7) - 1); if (val >= (1 << 7)) { out |= (1 << 7); - if (!out_buffer->Encode(out)) + if (!out_buffer->Encode(out)) { return false; - if (!EncodeVarint<IntTypeT>(val >> 7, out_buffer)) + } + if (!EncodeVarint<IntTypeT>(val >> 7, out_buffer)) { return false; + } return true; } - if (!out_buffer->Encode(out)) + if (!out_buffer->Encode(out)) { return false; + } } else { // IntTypeT is a signed value. Convert to unsigned symbol and encode. const typename std::make_unsigned<IntTypeT>::type symbol = ConvertSignedIntToSymbol(val); - if (!EncodeVarint(symbol, out_buffer)) + if (!EncodeVarint(symbol, out_buffer)) { return false; + } } return true; } diff --git a/extern/draco/dracoenc/src/draco/core/vector_d.h b/extern/draco/draco/src/draco/core/vector_d.h index 189517f3928..bed97304feb 100644 --- a/extern/draco/dracoenc/src/draco/core/vector_d.h +++ b/extern/draco/draco/src/draco/core/vector_d.h @@ -16,6 +16,7 @@ #define DRACO_CORE_VECTOR_D_H_ #include <inttypes.h> + #include <algorithm> #include <array> #include <cmath> @@ -36,8 +37,9 @@ class VectorD { typedef ScalarT CoefficientType; VectorD() { - for (int i = 0; i < dimension; ++i) + for (int i = 0; i < dimension; ++i) { (*this)[i] = Scalar(0); + } } // The following constructor does not compile in opt mode, which for now led @@ -83,8 +85,9 @@ class VectorD { } VectorD(const Self &o) { - for (int i = 0; i < dimension; ++i) + for (int i = 0; i < dimension; ++i) { (*this)[i] = o[i]; + } } // Constructs the vector from another vector with a different data type or a @@ -97,10 +100,11 @@ class VectorD { template <class OtherScalarT, int other_dimension_t> explicit VectorD(const VectorD<OtherScalarT, other_dimension_t> &src_vector) { for (int i = 0; i < dimension; ++i) { - if (i < other_dimension_t) + if (i < other_dimension_t) { v_[i] = Scalar(src_vector[i]); - else + } else { v_[i] = Scalar(0); + } } } @@ -137,6 +141,35 @@ class VectorD { return ret; } + Self operator*(const Self &o) const { + Self ret; + for (int i = 0; i < dimension; ++i) { + ret[i] = (*this)[i] * o[i]; + } + return ret; + } + + Self &operator+=(const Self &o) { + for (int i = 0; i < dimension; ++i) { + (*this)[i] += o[i]; + } + return *this; + } + + Self &operator-=(const Self &o) { + for (int i = 0; i < dimension; ++i) { + (*this)[i] -= o[i]; + } + return *this; + } + + Self &operator*=(const Self &o) { + for (int i = 0; i < dimension; ++i) { + (*this)[i] *= o[i]; + } + return *this; + } + Self operator*(const Scalar &o) const { Self ret; for (int i = 0; i < dimension; ++i) { @@ -171,8 +204,9 @@ class VectorD { bool operator==(const Self &o) const { for (int i = 0; i < dimension; ++i) { - if ((*this)[i] != o[i]) + if ((*this)[i] != o[i]) { return false; + } } return true; } @@ -181,14 +215,17 @@ class VectorD { bool operator<(const Self &x) const { for (int i = 0; i < dimension - 1; ++i) { - if (v_[i] < x.v_[i]) + if (v_[i] < x.v_[i]) { return true; - if (v_[i] > x.v_[i]) + } + if (v_[i] > x.v_[i]) { return false; + } } // Only one check needed for the last dimension. - if (v_[dimension - 1] < x.v_[dimension - 1]) + if (v_[dimension - 1] < x.v_[dimension - 1]) { return true; + } return false; } @@ -222,6 +259,12 @@ class VectorD { } } + Self GetNormalized() const { + Self ret(*this); + ret.Normalize(); + return ret; + } + const Scalar &MaxCoeff() const { return *std::max_element(v_.begin(), v_.end()); } @@ -231,6 +274,7 @@ class VectorD { } Scalar *data() { return &(v_[0]); } + const Scalar *data() const { return &(v_[0]); } private: std::array<Scalar, dimension> v_; diff --git a/extern/draco/draco/src/draco/draco_features.h b/extern/draco/draco/src/draco/draco_features.h new file mode 100644 index 00000000000..27e3d7f136a --- /dev/null +++ b/extern/draco/draco/src/draco/draco_features.h @@ -0,0 +1,10 @@ +#ifndef DRACO_FEATURES_H_ +#define DRACO_FEATURES_H_ + +#define DRACO_MESH_COMPRESSION_SUPPORTED +#define DRACO_NORMAL_ENCODING_SUPPORTED +#define DRACO_STANDARD_EDGEBREAKER_SUPPORTED +#define DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED +#define DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED + +#endif // DRACO_FEATURES_H_ diff --git a/extern/draco/dracoenc/src/draco/mesh/corner_table.cc b/extern/draco/draco/src/draco/mesh/corner_table.cc index dcfd7967c0b..6066e58bd8b 100644 --- a/extern/draco/dracoenc/src/draco/mesh/corner_table.cc +++ b/extern/draco/draco/src/draco/mesh/corner_table.cc @@ -30,8 +30,9 @@ CornerTable::CornerTable() std::unique_ptr<CornerTable> CornerTable::Create( const IndexTypeVector<FaceIndex, FaceType> &faces) { std::unique_ptr<CornerTable> ct(new CornerTable()); - if (!ct->Init(faces)) + if (!ct->Init(faces)) { return nullptr; + } return ct; } @@ -45,12 +46,15 @@ bool CornerTable::Init(const IndexTypeVector<FaceIndex, FaceType> &faces) { } } int num_vertices = -1; - if (!ComputeOppositeCorners(&num_vertices)) + if (!ComputeOppositeCorners(&num_vertices)) { return false; - if (!BreakNonManifoldEdges()) + } + if (!BreakNonManifoldEdges()) { return false; - if (!ComputeVertexCorners(num_vertices)) + } + if (!ComputeVertexCorners(num_vertices)) { return false; + } return true; } @@ -59,11 +63,13 @@ bool CornerTable::Reset(int num_faces) { } bool CornerTable::Reset(int num_faces, int num_vertices) { - if (num_faces < 0 || num_vertices < 0) + if (num_faces < 0 || num_vertices < 0) { return false; + } if (static_cast<unsigned int>(num_faces) > - std::numeric_limits<CornerIndex::ValueType>::max() / 3) + std::numeric_limits<CornerIndex::ValueType>::max() / 3) { return false; + } corner_to_vertex_map_.assign(num_faces * 3, kInvalidVertexIndex); opposite_corners_.assign(num_faces * 3, kInvalidCornerIndex); vertex_corners_.reserve(num_vertices); @@ -74,8 +80,9 @@ bool CornerTable::Reset(int num_faces, int num_vertices) { bool CornerTable::ComputeOppositeCorners(int *num_vertices) { DRACO_DCHECK(GetValenceCache().IsCacheEmpty()); - if (num_vertices == nullptr) + if (num_vertices == nullptr) { return false; + } opposite_corners_.resize(num_corners(), kInvalidCornerIndex); // Out implementation for finding opposite corners is based on keeping track @@ -92,8 +99,9 @@ bool CornerTable::ComputeOppositeCorners(int *num_vertices) { num_corners_on_vertices.reserve(num_corners()); for (CornerIndex c(0); c < num_corners(); ++c) { const VertexIndex v1 = Vertex(c); - if (v1.value() >= static_cast<int>(num_corners_on_vertices.size())) + if (v1.value() >= static_cast<int>(num_corners_on_vertices.size())) { num_corners_on_vertices.resize(v1.value() + 1, 0); + } // For each corner there is always exactly one outgoing half-edge attached // to its vertex. num_corners_on_vertices[v1.value()]++; @@ -150,11 +158,13 @@ bool CornerTable::ComputeOppositeCorners(int *num_vertices) { offset = vertex_offset[sink_v.value()]; for (int i = 0; i < num_corners_on_vert; ++i, ++offset) { const VertexIndex other_v = vertex_edges[offset].sink_vert; - if (other_v == kInvalidVertexIndex) + if (other_v == kInvalidVertexIndex) { break; // No matching half-edge found on the sink vertex. + } if (other_v == source_v) { - if (tip_v == Vertex(vertex_edges[offset].edge_corner)) + if (tip_v == Vertex(vertex_edges[offset].edge_corner)) { continue; // Don't connect mirrored faces. + } // A matching half-edge was found on the sink vertex. Mark the // half-edge's opposite corner. opposite_c = vertex_edges[offset].edge_corner; @@ -165,8 +175,9 @@ bool CornerTable::ComputeOppositeCorners(int *num_vertices) { // slot. for (int j = i + 1; j < num_corners_on_vert; ++j, ++offset) { vertex_edges[offset] = vertex_edges[offset + 1]; - if (vertex_edges[offset].sink_vert == kInvalidVertexIndex) + if (vertex_edges[offset].sink_vert == kInvalidVertexIndex) { break; // Unused half-edge reached. + } } // Mark the last entry as unused. vertex_edges[offset].sink_vert = kInvalidVertexIndex; @@ -217,8 +228,9 @@ bool CornerTable::BreakNonManifoldEdges() { do { mesh_connectivity_updated = false; for (CornerIndex c(0); c < num_corners(); ++c) { - if (visited_corners[c.value()]) + if (visited_corners[c.value()]) { continue; + } sink_vertices.clear(); // First swing all the way to find the left-most corner connected to the @@ -267,10 +279,12 @@ bool CornerTable::BreakNonManifoldEdges() { // that the final surface would be manifold. const CornerIndex opp_other_edge_corner = Opposite(other_edge_corner); - if (opp_edge_corner != kInvalidCornerIndex) + if (opp_edge_corner != kInvalidCornerIndex) { SetOppositeCorner(opp_edge_corner, kInvalidCornerIndex); - if (opp_other_edge_corner != kInvalidCornerIndex) + } + if (opp_other_edge_corner != kInvalidCornerIndex) { SetOppositeCorner(opp_other_edge_corner, kInvalidCornerIndex); + } SetOppositeCorner(edge_corner, kInvalidCornerIndex); SetOppositeCorner(other_edge_corner, kInvalidCornerIndex); @@ -312,13 +326,15 @@ bool CornerTable::ComputeVertexCorners(int num_vertices) { for (FaceIndex f(0); f < num_faces(); ++f) { const CornerIndex first_face_corner = FirstCorner(f); // Check whether the face is degenerated. If so ignore it. - if (IsDegenerated(f)) + if (IsDegenerated(f)) { continue; + } for (int k = 0; k < 3; ++k) { const CornerIndex c = first_face_corner + k; - if (visited_corners[c.value()]) + if (visited_corners[c.value()]) { continue; + } VertexIndex v = corner_to_vertex_map_[c]; // Note that one vertex maps to many corners, but we just keep track // of the vertex which has a boundary on the left if the vertex lies on @@ -350,8 +366,9 @@ bool CornerTable::ComputeVertexCorners(int num_vertices) { corner_to_vertex_map_[act_c] = v; } act_c = SwingLeft(act_c); - if (act_c == c) + if (act_c == c) { break; // Full circle reached. + } } if (act_c == kInvalidCornerIndex) { // If we have reached an open boundary we need to swing right from the @@ -372,27 +389,31 @@ bool CornerTable::ComputeVertexCorners(int num_vertices) { // Count the number of isolated (unprocessed) vertices. num_isolated_vertices_ = 0; for (bool visited : visited_vertices) { - if (!visited) + if (!visited) { ++num_isolated_vertices_; + } } return true; } bool CornerTable::IsDegenerated(FaceIndex face) const { - if (face == kInvalidFaceIndex) + if (face == kInvalidFaceIndex) { return true; + } const CornerIndex first_face_corner = FirstCorner(face); const VertexIndex v0 = Vertex(first_face_corner); const VertexIndex v1 = Vertex(Next(first_face_corner)); const VertexIndex v2 = Vertex(Previous(first_face_corner)); - if (v0 == v1 || v0 == v2 || v1 == v2) + if (v0 == v1 || v0 == v2 || v1 == v2) { return true; + } return false; } int CornerTable::Valence(VertexIndex v) const { - if (v == kInvalidVertexIndex) + if (v == kInvalidVertexIndex) { return -1; + } return ConfidentValence(v); } diff --git a/extern/draco/dracoenc/src/draco/mesh/corner_table.h b/extern/draco/draco/src/draco/mesh/corner_table.h index 704a7b1b5c4..3aa720fdeb9 100644 --- a/extern/draco/dracoenc/src/draco/mesh/corner_table.h +++ b/extern/draco/draco/src/draco/mesh/corner_table.h @@ -80,23 +80,27 @@ class CornerTable { } inline CornerIndex Opposite(CornerIndex corner) const { - if (corner == kInvalidCornerIndex) + if (corner == kInvalidCornerIndex) { return corner; + } return opposite_corners_[corner]; } inline CornerIndex Next(CornerIndex corner) const { - if (corner == kInvalidCornerIndex) + if (corner == kInvalidCornerIndex) { return corner; + } return LocalIndex(++corner) ? corner : corner - 3; } inline CornerIndex Previous(CornerIndex corner) const { - if (corner == kInvalidCornerIndex) + if (corner == kInvalidCornerIndex) { return corner; + } return LocalIndex(corner) ? corner - 1 : corner + 2; } inline VertexIndex Vertex(CornerIndex corner) const { - if (corner == kInvalidCornerIndex) + if (corner == kInvalidCornerIndex) { return kInvalidVertexIndex; + } return ConfidentVertex(corner); } inline VertexIndex ConfidentVertex(CornerIndex corner) const { @@ -105,13 +109,15 @@ class CornerTable { return corner_to_vertex_map_[corner]; } inline FaceIndex Face(CornerIndex corner) const { - if (corner == kInvalidCornerIndex) + if (corner == kInvalidCornerIndex) { return kInvalidFaceIndex; + } return FaceIndex(corner.value() / 3); } inline CornerIndex FirstCorner(FaceIndex face) const { - if (face == kInvalidFaceIndex) + if (face == kInvalidFaceIndex) { return kInvalidCornerIndex; + } return CornerIndex(face.value() * 3); } inline std::array<CornerIndex, 3> AllCorners(FaceIndex face) const { @@ -146,8 +152,9 @@ class CornerTable { // Returns the parent vertex index of a given corner table vertex. VertexIndex VertexParent(VertexIndex vertex) const { - if (vertex.value() < static_cast<uint32_t>(num_original_vertices_)) + if (vertex.value() < static_cast<uint32_t>(num_original_vertices_)) { return vertex; + } return non_manifold_vertex_parents_[vertex - num_original_vertices_]; } @@ -163,8 +170,9 @@ class CornerTable { int ConfidentValence(VertexIndex v) const; // Returns the valence of the vertex at the given corner. inline int Valence(CornerIndex c) const { - if (c == kInvalidCornerIndex) + if (c == kInvalidCornerIndex) { return -1; + } return ConfidentValence(c); } inline int ConfidentValence(CornerIndex c) const { @@ -175,8 +183,9 @@ class CornerTable { // Returns true if the specified vertex is on a boundary. inline bool IsOnBoundary(VertexIndex vert) const { const CornerIndex corner = LeftMostCorner(vert); - if (SwingLeft(corner) == kInvalidCornerIndex) + if (SwingLeft(corner) == kInvalidCornerIndex) { return true; + } return false; } @@ -205,13 +214,15 @@ class CornerTable { // \ / \ / // *-------* inline CornerIndex GetLeftCorner(CornerIndex corner_id) const { - if (corner_id == kInvalidCornerIndex) + if (corner_id == kInvalidCornerIndex) { return kInvalidCornerIndex; + } return Opposite(Previous(corner_id)); } inline CornerIndex GetRightCorner(CornerIndex corner_id) const { - if (corner_id == kInvalidCornerIndex) + if (corner_id == kInvalidCornerIndex) { return kInvalidCornerIndex; + } return Opposite(Next(corner_id)); } @@ -241,10 +252,12 @@ class CornerTable { // Sets opposite corners for both input corners. inline void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) { DRACO_DCHECK(GetValenceCache().IsCacheEmpty()); - if (corner_0 != kInvalidCornerIndex) + if (corner_0 != kInvalidCornerIndex) { SetOppositeCorner(corner_0, corner_1); - if (corner_1 != kInvalidCornerIndex) + } + if (corner_1 != kInvalidCornerIndex) { SetOppositeCorner(corner_1, corner_0); + } } // Updates mapping between a corner and a vertex. @@ -260,11 +273,26 @@ class CornerTable { return VertexIndex(static_cast<uint32_t>(vertex_corners_.size() - 1)); } + // Adds a new face connected to three vertices. Note that connectivity is not + // automatically updated and all opposite corners need to be set explicitly. + FaceIndex AddNewFace(const std::array<VertexIndex, 3> &vertices) { + // Add a new invalid face. + const FaceIndex new_face_index(num_faces()); + for (int i = 0; i < 3; ++i) { + corner_to_vertex_map_.push_back(vertices[i]); + SetLeftMostCorner(vertices[i], + CornerIndex(corner_to_vertex_map_.size() - 1)); + } + opposite_corners_.resize(corner_to_vertex_map_.size(), kInvalidCornerIndex); + return new_face_index; + } + // Sets a new left most corner for a given vertex. void SetLeftMostCorner(VertexIndex vert, CornerIndex corner) { DRACO_DCHECK(GetValenceCache().IsCacheEmpty()); - if (vert != kInvalidVertexIndex) + if (vert != kInvalidVertexIndex) { vertex_corners_[vert] = corner; + } } // Updates the vertex to corner map on a specified vertex. This should be @@ -273,8 +301,9 @@ class CornerTable { void UpdateVertexToCornerMap(VertexIndex vert) { DRACO_DCHECK(GetValenceCache().IsCacheEmpty()); const CornerIndex first_c = vertex_corners_[vert]; - if (first_c == kInvalidCornerIndex) + if (first_c == kInvalidCornerIndex) { return; // Isolated vertex. + } CornerIndex act_c = SwingLeft(first_c); CornerIndex c = first_c; while (act_c != kInvalidCornerIndex && act_c != first_c) { diff --git a/extern/draco/dracoenc/src/draco/mesh/corner_table_iterators.h b/extern/draco/draco/src/draco/mesh/corner_table_iterators.h index 65869dbe109..7122aa1be0f 100644 --- a/extern/draco/dracoenc/src/draco/mesh/corner_table_iterators.h +++ b/extern/draco/draco/src/draco/mesh/corner_table_iterators.h @@ -45,6 +45,13 @@ class VertexRingIterator return corner_table_->Vertex(ring_corner); } + // Returns one of the corners opposite to the edge connecting the currently + // iterated ring vertex with the central vertex. + CornerIndex EdgeCorner() const { + return left_traversal_ ? corner_table_->Next(corner_) + : corner_table_->Previous(corner_); + } + // Returns true when all ring vertices have been visited. bool End() const { return corner_ == kInvalidCornerIndex; } @@ -120,8 +127,9 @@ class FaceAdjacencyIterator corner_(start_corner_) { // We need to start with a corner that has a valid opposite face (if // there is any such corner). - if (corner_table_->Opposite(corner_) == kInvalidCornerIndex) + if (corner_table_->Opposite(corner_) == kInvalidCornerIndex) { FindNextFaceNeighbor(); + } } // Gets the last visited adjacent face. diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh.cc b/extern/draco/draco/src/draco/mesh/mesh.cc index a78a6ec96a8..3be4b1494ec 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh.cc +++ b/extern/draco/draco/src/draco/mesh/mesh.cc @@ -15,12 +15,9 @@ #include "draco/mesh/mesh.h" #include <array> -#include <unordered_map> namespace draco { -using std::unordered_map; - // Shortcut for typed conditionals. template <bool B, class T, class F> using conditional_t = typename std::conditional<B, T, F>::type; diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh.h b/extern/draco/draco/src/draco/mesh/mesh.h index b8ca5353a81..f4506da81c9 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh.h +++ b/extern/draco/draco/src/draco/mesh/mesh.h @@ -93,8 +93,9 @@ class Mesh : public PointCloud { // Returns the point id of for a corner |ci|. inline PointIndex CornerToPointId(int ci) const { - if (ci == kInvalidCornerIndex.value()) + if (ci < 0 || static_cast<uint32_t>(ci) == kInvalidCornerIndex.value()) { return kInvalidPointIndex; + } return this->face(FaceIndex(ci / 3))[ci % 3]; } diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_are_equivalent.cc b/extern/draco/draco/src/draco/mesh/mesh_are_equivalent.cc index deb68940a54..b832379afe4 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_are_equivalent.cc +++ b/extern/draco/draco/src/draco/mesh/mesh_are_equivalent.cc @@ -101,10 +101,12 @@ void MeshAreEquivalent::Init(const Mesh &mesh0, const Mesh &mesh1) { } bool MeshAreEquivalent::operator()(const Mesh &mesh0, const Mesh &mesh1) { - if (mesh0.num_faces() != mesh1.num_faces()) + if (mesh0.num_faces() != mesh1.num_faces()) { return false; - if (mesh0.num_attributes() != mesh1.num_attributes()) + } + if (mesh0.num_attributes() != mesh1.num_attributes()) { return false; + } // The following function inits mesh info, i.e., computes the order of // faces with respect to the lex order. This way one can then compare the @@ -121,20 +123,27 @@ bool MeshAreEquivalent::operator()(const Mesh &mesh0, const Mesh &mesh1) { mesh0.GetNamedAttribute(AttributeType(att_id)); const PointAttribute *const att1 = mesh1.GetNamedAttribute(AttributeType(att_id)); - if (att0 == nullptr && att1 == nullptr) + if (att0 == nullptr && att1 == nullptr) { continue; - if (att0 == nullptr) + } + if (att0 == nullptr) { return false; - if (att1 == nullptr) + } + if (att1 == nullptr) { return false; - if (att0->data_type() != att1->data_type()) + } + if (att0->data_type() != att1->data_type()) { return false; - if (att0->num_components() != att1->num_components()) + } + if (att0->num_components() != att1->num_components()) { return false; - if (att0->normalized() != att1->normalized()) + } + if (att0->normalized() != att1->normalized()) { return false; - if (att0->byte_stride() != att1->byte_stride()) + } + if (att0->byte_stride() != att1->byte_stride()) { return false; + } DRACO_DCHECK(att0->IsValid()); DRACO_DCHECK(att1->IsValid()); @@ -162,8 +171,9 @@ bool MeshAreEquivalent::operator()(const Mesh &mesh0, const Mesh &mesh1) { att0->GetValue(index0, data0.get()); att1->GetValue(index1, data1.get()); // Compare the data as is in memory. - if (memcmp(data0.get(), data1.get(), att0->byte_stride()) != 0) + if (memcmp(data0.get(), data1.get(), att0->byte_stride()) != 0) { return false; + } } } } @@ -172,18 +182,21 @@ bool MeshAreEquivalent::operator()(const Mesh &mesh0, const Mesh &mesh1) { bool MeshAreEquivalent::FaceIndexLess::operator()(FaceIndex f0, FaceIndex f1) const { - if (f0 == f1) + if (f0 == f1) { return false; + } const int c0 = mesh_info.corner_index_of_smallest_vertex[f0]; const int c1 = mesh_info.corner_index_of_smallest_vertex[f1]; for (int i = 0; i < 3; ++i) { const Vector3f vf0 = GetPosition(mesh_info.mesh, f0, (c0 + i) % 3); const Vector3f vf1 = GetPosition(mesh_info.mesh, f1, (c1 + i) % 3); - if (vf0 < vf1) + if (vf0 < vf1) { return true; - if (vf1 < vf0) + } + if (vf1 < vf0) { return false; + } } // In case the two faces are equivalent. return false; diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_are_equivalent.h b/extern/draco/draco/src/draco/mesh/mesh_are_equivalent.h index 71ef4a93c12..71ef4a93c12 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_are_equivalent.h +++ b/extern/draco/draco/src/draco/mesh/mesh_are_equivalent.h diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_attribute_corner_table.cc b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.cc index 768d5f5e28e..28b68d5fd40 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_attribute_corner_table.cc +++ b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/mesh/mesh_attribute_corner_table.h" + #include "draco/mesh/corner_table_iterators.h" #include "draco/mesh/mesh_misc_functions.h" @@ -22,8 +23,9 @@ MeshAttributeCornerTable::MeshAttributeCornerTable() : no_interior_seams_(true), corner_table_(nullptr), valence_cache_(*this) {} bool MeshAttributeCornerTable::InitEmpty(const CornerTable *table) { - if (table == nullptr) + if (table == nullptr) { return false; + } valence_cache_.ClearValenceCache(); valence_cache_.ClearValenceCacheInaccurate(); is_edge_on_seam_.assign(table->num_corners(), false); @@ -39,8 +41,9 @@ bool MeshAttributeCornerTable::InitEmpty(const CornerTable *table) { bool MeshAttributeCornerTable::InitFromAttribute(const Mesh *mesh, const CornerTable *table, const PointAttribute *att) { - if (!InitEmpty(table)) + if (!InitEmpty(table)) { return false; + } valence_cache_.ClearValenceCache(); valence_cache_.ClearValenceCacheInaccurate(); @@ -49,8 +52,9 @@ bool MeshAttributeCornerTable::InitFromAttribute(const Mesh *mesh, // special handling. for (CornerIndex c(0); c < corner_table_->num_corners(); ++c) { const FaceIndex f = corner_table_->Face(c); - if (corner_table_->IsDegenerated(f)) + if (corner_table_->IsDegenerated(f)) { continue; // Ignore corners on degenerated faces. + } const CornerIndex opp_corner = corner_table_->Opposite(c); if (opp_corner == kInvalidCornerIndex) { // Boundary. Mark it as seam edge. @@ -63,8 +67,9 @@ bool MeshAttributeCornerTable::InitFromAttribute(const Mesh *mesh, is_vertex_on_seam_[v.value()] = true; continue; } - if (opp_corner < c) + if (opp_corner < c) { continue; // Opposite corner was already processed. + } CornerIndex act_c(c), act_sibling_c(opp_corner); for (int i = 0; i < 2; ++i) { @@ -135,11 +140,14 @@ template <bool init_vertex_to_attribute_entry_map> void MeshAttributeCornerTable::RecomputeVerticesInternal( const Mesh *mesh, const PointAttribute *att) { DRACO_DCHECK(GetValenceCache().IsCacheEmpty()); + vertex_to_attribute_entry_id_map_.clear(); + vertex_to_left_most_corner_map_.clear(); int num_new_vertices = 0; for (VertexIndex v(0); v < corner_table_->num_vertices(); ++v) { const CornerIndex c = corner_table_->LeftMostCorner(v); - if (c == kInvalidCornerIndex) + if (c == kInvalidCornerIndex) { continue; // Isolated vertex? + } AttributeValueIndex first_vert_id(num_new_vertices++); if (init_vertex_to_attribute_entry_map) { const PointIndex point_id = mesh->CornerToPointId(c.value()); @@ -184,8 +192,9 @@ void MeshAttributeCornerTable::RecomputeVerticesInternal( } int MeshAttributeCornerTable::Valence(VertexIndex v) const { - if (v == kInvalidVertexIndex) + if (v == kInvalidVertexIndex) { return -1; + } return ConfidentValence(v); } diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_attribute_corner_table.h b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h index b9e938f5b7d..7dad25cf1d2 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_attribute_corner_table.h +++ b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h @@ -47,8 +47,9 @@ class MeshAttributeCornerTable { } inline CornerIndex Opposite(CornerIndex corner) const { - if (corner == kInvalidCornerIndex || IsCornerOppositeToSeamEdge(corner)) + if (corner == kInvalidCornerIndex || IsCornerOppositeToSeamEdge(corner)) { return kInvalidCornerIndex; + } return corner_table_->Opposite(corner); } @@ -88,6 +89,7 @@ class MeshAttributeCornerTable { return static_cast<int>(vertex_to_attribute_entry_id_map_.size()); } int num_faces() const { return static_cast<int>(corner_table_->num_faces()); } + int num_corners() const { return corner_table_->num_corners(); } VertexIndex Vertex(CornerIndex corner) const { DRACO_DCHECK_LT(corner.value(), corner_to_vertex_map_.size()); @@ -105,11 +107,27 @@ class MeshAttributeCornerTable { return vertex_to_left_most_corner_map_[v.value()]; } + inline FaceIndex Face(CornerIndex corner) const { + return corner_table_->Face(corner); + } + + inline CornerIndex FirstCorner(FaceIndex face) const { + return corner_table_->FirstCorner(face); + } + + inline std::array<CornerIndex, 3> AllCorners(FaceIndex face) const { + return corner_table_->AllCorners(face); + } + inline bool IsOnBoundary(VertexIndex vert) const { const CornerIndex corner = LeftMostCorner(vert); - if (corner == kInvalidCornerIndex) + if (corner == kInvalidCornerIndex) { + return true; + } + if (SwingLeft(corner) == kInvalidCornerIndex) { return true; - return IsCornerOnSeam(corner); + } + return false; } bool no_interior_seams() const { return no_interior_seams_; } @@ -126,8 +144,9 @@ class MeshAttributeCornerTable { // Returns the valence of the vertex at the given corner. inline int Valence(CornerIndex c) const { DRACO_DCHECK_LT(c.value(), corner_table_->num_corners()); - if (c == kInvalidCornerIndex) + if (c == kInvalidCornerIndex) { return -1; + } return ConfidentValence(c); } inline int ConfidentValence(CornerIndex c) const { diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.cc b/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc index 8e2d393b8f3..773c1e18fe6 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.cc +++ b/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc @@ -17,12 +17,14 @@ namespace draco { bool MeshCleanup::operator()(Mesh *mesh, const MeshCleanupOptions &options) { - if (!options.remove_degenerated_faces && !options.remove_unused_attributes) + if (!options.remove_degenerated_faces && !options.remove_unused_attributes) { return true; // Nothing to cleanup. + } const PointAttribute *const pos_att = mesh->GetNamedAttribute(GeometryAttribute::POSITION); - if (pos_att == nullptr) + if (pos_att == nullptr) { return false; + } // Array that is going to store whether a corresponding point is used. std::vector<bool> is_point_used; if (options.remove_unused_attributes) { @@ -161,8 +163,9 @@ bool MeshCleanup::operator()(Mesh *mesh, const MeshCleanupOptions &options) { // The new point id that maps to the currently processed attribute // entry. const PointIndex new_point_id = point_map[i]; - if (new_point_id == kInvalidPointIndex) + if (new_point_id == kInvalidPointIndex) { continue; + } // Index of the currently processed attribute entry in the original // mesh. const AttributeValueIndex original_entry_index = diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.h b/extern/draco/draco/src/draco/mesh/mesh_cleanup.h index b56129dce58..b56129dce58 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup.h +++ b/extern/draco/draco/src/draco/mesh/mesh_cleanup.h diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.cc b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.cc index b55527aa85e..4485b3369ac 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.cc +++ b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.cc @@ -18,18 +18,23 @@ namespace draco { std::unique_ptr<CornerTable> CreateCornerTableFromPositionAttribute( const Mesh *mesh) { + return CreateCornerTableFromAttribute(mesh, GeometryAttribute::POSITION); +} + +std::unique_ptr<CornerTable> CreateCornerTableFromAttribute( + const Mesh *mesh, GeometryAttribute::Type type) { typedef CornerTable::FaceType FaceType; - const PointAttribute *const att = - mesh->GetNamedAttribute(GeometryAttribute::POSITION); - if (att == nullptr) + const PointAttribute *const att = mesh->GetNamedAttribute(type); + if (att == nullptr) { return nullptr; + } IndexTypeVector<FaceIndex, FaceType> faces(mesh->num_faces()); FaceType new_face; for (FaceIndex i(0); i < mesh->num_faces(); ++i) { const Mesh::Face &face = mesh->face(i); for (int j = 0; j < 3; ++j) { - // Map general vertex indices to position indices. + // Map general vertex indices to attribute indices. new_face[j] = att->mapped_index(face[j]).value(); } faces[FaceIndex(i)] = new_face; diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.h b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h index b972109e679..b450bc80cd8 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.h +++ b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h @@ -29,6 +29,11 @@ namespace draco { std::unique_ptr<CornerTable> CreateCornerTableFromPositionAttribute( const Mesh *mesh); +// Creates a CornerTable from the first named attribute of |mesh| with a given +// type. Returns nullptr on error. +std::unique_ptr<CornerTable> CreateCornerTableFromAttribute( + const Mesh *mesh, GeometryAttribute::Type type); + // Creates a CornerTable from all attributes of |mesh|. Boundaries are // automatically introduced on all attribute seams. Returns nullptr on error. std::unique_ptr<CornerTable> CreateCornerTableFromAllAttributes( @@ -40,19 +45,22 @@ inline bool IsCornerOppositeToAttributeSeam(CornerIndex ci, const Mesh &mesh, const CornerTable &ct) { const CornerIndex opp_ci = ct.Opposite(ci); - if (opp_ci == kInvalidCornerIndex) + if (opp_ci == kInvalidCornerIndex) { return false; // No opposite corner == no attribute seam. + } // Compare attribute value indices on both ends of the opposite edge. CornerIndex c0 = ct.Next(ci); CornerIndex c1 = ct.Previous(opp_ci); if (att.mapped_index(mesh.CornerToPointId(c0)) != - att.mapped_index(mesh.CornerToPointId(c1))) + att.mapped_index(mesh.CornerToPointId(c1))) { return true; + } c0 = ct.Previous(ci); c1 = ct.Next(opp_ci); if (att.mapped_index(mesh.CornerToPointId(c0)) != - att.mapped_index(mesh.CornerToPointId(c1))) + att.mapped_index(mesh.CornerToPointId(c1))) { return true; + } return false; } @@ -71,8 +79,18 @@ InterpolatedVectorT ComputeInterpolatedAttributeValueOnMeshFace( attribute.GetMappedValue(face[c], &(val[c][0])); } // Return an interpolated value. - return barycentric_coord[0] * val[0] + barycentric_coord[1] * val[1] + - barycentric_coord[2] * val[2]; + InterpolatedVectorT res; + for (int d = 0; d < InterpolatedVectorT::dimension; ++d) { + const float interpolated_component = barycentric_coord[0] * val[0][d] + + barycentric_coord[1] * val[1][d] + + barycentric_coord[2] * val[2][d]; + if (std::is_integral<typename InterpolatedVectorT::Scalar>::value) { + res[d] = std::floor(interpolated_component + 0.5f); + } else { + res[d] = interpolated_component; + } + } + return res; } } // namespace draco diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_stripifier.cc b/extern/draco/draco/src/draco/mesh/mesh_stripifier.cc index 5b63da3023d..f68062eba68 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_stripifier.cc +++ b/extern/draco/draco/src/draco/mesh/mesh_stripifier.cc @@ -41,13 +41,15 @@ void MeshStripifier::GenerateStripsFromCorner(int local_strip_id, // Perform the backward pass only when there is no attribute seam between // the initial face and the first face of the backward traversal. if (GetOppositeCorner(corner_table_->Previous(start_ci)) == - kInvalidCornerIndex) + kInvalidCornerIndex) { break; // Attribute seam or a boundary. + } ci = corner_table_->Next(start_ci); ci = corner_table_->SwingLeft(ci); - if (ci == kInvalidCornerIndex) + if (ci == kInvalidCornerIndex) { break; + } fi = corner_table_->Face(ci); } @@ -74,8 +76,9 @@ void MeshStripifier::GenerateStripsFromCorner(int local_strip_id, } } ci = GetOppositeCorner(ci); - if (ci == kInvalidCornerIndex) + if (ci == kInvalidCornerIndex) { break; + } fi = corner_table_->Face(ci); } // Strip end reached. diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_stripifier.h b/extern/draco/draco/src/draco/mesh/mesh_stripifier.h index f7c1ead4c44..0c298f48e86 100644 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_stripifier.h +++ b/extern/draco/draco/src/draco/mesh/mesh_stripifier.h @@ -74,8 +74,9 @@ class MeshStripifier { // TODO(ostava): We may be able to avoid computing the corner table if we // already have it stored somewhere. corner_table_ = CreateCornerTableFromPositionAttribute(mesh_); - if (corner_table_ == nullptr) + if (corner_table_ == nullptr) { return false; + } // Mark all faces as unvisited. is_face_visited_.assign(mesh.num_faces(), false); @@ -144,16 +145,19 @@ class MeshStripifier { // across an attribute seam. Otherwise return kInvalidCornerIndex. CornerIndex GetOppositeCorner(CornerIndex ci) const { const CornerIndex oci = corner_table_->Opposite(ci); - if (oci < 0) + if (oci < 0) { return kInvalidCornerIndex; + } // Ensure the point ids are same on both sides of the shared edge between // the triangles. if (CornerToPointIndex(corner_table_->Next(ci)) != - CornerToPointIndex(corner_table_->Previous(oci))) + CornerToPointIndex(corner_table_->Previous(oci))) { return kInvalidCornerIndex; + } if (CornerToPointIndex(corner_table_->Previous(ci)) != - CornerToPointIndex(corner_table_->Next(oci))) + CornerToPointIndex(corner_table_->Next(oci))) { return kInvalidCornerIndex; + } return oci; } @@ -179,13 +183,15 @@ template <typename OutputIteratorT, typename IndexTypeT> bool MeshStripifier::GenerateTriangleStripsWithPrimitiveRestart( const Mesh &mesh, IndexTypeT primitive_restart_index, OutputIteratorT out_it) { - if (!Prepare(mesh)) + if (!Prepare(mesh)) { return false; + } // Go over all faces and generate strips from the first unvisited one. for (FaceIndex fi(0); fi < mesh.num_faces(); ++fi) { - if (is_face_visited_[fi]) + if (is_face_visited_[fi]) { continue; + } const int longest_strip_id = FindLongestStripFromFace(fi); @@ -203,13 +209,15 @@ bool MeshStripifier::GenerateTriangleStripsWithPrimitiveRestart( template <typename OutputIteratorT> bool MeshStripifier::GenerateTriangleStripsWithDegenerateTriangles( const Mesh &mesh, OutputIteratorT out_it) { - if (!Prepare(mesh)) + if (!Prepare(mesh)) { return false; + } // Go over all faces and generate strips from the first unvisited one. for (FaceIndex fi(0); fi < mesh.num_faces(); ++fi) { - if (is_face_visited_[fi]) + if (is_face_visited_[fi]) { continue; + } const int longest_strip_id = FindLongestStripFromFace(fi); diff --git a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.cc b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc index 7a76745342b..60b0c50b8d5 100644 --- a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.cc +++ b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc @@ -60,15 +60,17 @@ void TriangleSoupMeshBuilder::SetPerFaceAttributeValueForFace( {{PointIndex(start_index), PointIndex(start_index + 1), PointIndex(start_index + 2)}}); int8_t &element_type = attribute_element_types_[att_id]; - if (element_type < 0) + if (element_type < 0) { element_type = MESH_FACE_ATTRIBUTE; + } } std::unique_ptr<Mesh> TriangleSoupMeshBuilder::Finalize() { #ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED // First deduplicate attribute values. - if (!mesh_->DeduplicateAttributeValues()) + if (!mesh_->DeduplicateAttributeValues()) { return nullptr; + } #endif #ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED // Also deduplicate vertex indices. diff --git a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.h b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.h index 3ae652cfeee..89466e1d849 100644 --- a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.h +++ b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.h @@ -16,7 +16,6 @@ #define DRACO_MESH_TRIANGLE_SOUP_MESH_BUILDER_H_ #include "draco/draco_features.h" - #include "draco/mesh/mesh.h" namespace draco { diff --git a/extern/draco/dracoenc/src/draco/mesh/valence_cache.h b/extern/draco/draco/src/draco/mesh/valence_cache.h index f75d66f4b99..3540377db81 100644 --- a/extern/draco/dracoenc/src/draco/mesh/valence_cache.h +++ b/extern/draco/draco/src/draco/mesh/valence_cache.h @@ -36,13 +36,15 @@ class ValenceCache { // Do not call before CacheValences() / CacheValencesInaccurate(). inline int8_t ValenceFromCacheInaccurate(CornerIndex c) const { - if (c == kInvalidCornerIndex) + if (c == kInvalidCornerIndex) { return -1; + } return ValenceFromCacheInaccurate(table_.Vertex(c)); } inline int32_t ValenceFromCache(CornerIndex c) const { - if (c == kInvalidCornerIndex) + if (c == kInvalidCornerIndex) { return -1; + } return ValenceFromCache(table_.Vertex(c)); } @@ -65,18 +67,20 @@ class ValenceCache { if (vertex_valence_cache_8_bit_.size() == 0) { const VertexIndex vertex_count = VertexIndex(table_.num_vertices()); vertex_valence_cache_8_bit_.resize(vertex_count.value()); - for (VertexIndex v = VertexIndex(0); v < vertex_count; v += 1) + for (VertexIndex v = VertexIndex(0); v < vertex_count; v += 1) { vertex_valence_cache_8_bit_[v] = static_cast<int8_t>( (std::min)(static_cast<int32_t>(std::numeric_limits<int8_t>::max()), table_.Valence(v))); + } } } void CacheValences() const { if (vertex_valence_cache_32_bit_.size() == 0) { const VertexIndex vertex_count = VertexIndex(table_.num_vertices()); vertex_valence_cache_32_bit_.resize(vertex_count.value()); - for (VertexIndex v = VertexIndex(0); v < vertex_count; v += 1) + for (VertexIndex v = VertexIndex(0); v < vertex_count; v += 1) { vertex_valence_cache_32_bit_[v] = table_.Valence(v); + } } } @@ -90,8 +94,9 @@ class ValenceCache { } inline int8_t ValenceFromCacheInaccurate(VertexIndex v) const { DRACO_DCHECK_EQ(vertex_valence_cache_8_bit_.size(), table_.num_vertices()); - if (v == kInvalidVertexIndex || v.value() >= table_.num_vertices()) + if (v == kInvalidVertexIndex || v.value() >= table_.num_vertices()) { return -1; + } return ConfidentValenceFromCacheInaccurate(v); } inline int8_t ConfidentValenceFromCacheInaccurate(VertexIndex v) const { @@ -103,8 +108,9 @@ class ValenceCache { // TODO(draco-eng) Add unit tests for ValenceCache functions. inline int32_t ValenceFromCache(VertexIndex v) const { DRACO_DCHECK_EQ(vertex_valence_cache_32_bit_.size(), table_.num_vertices()); - if (v == kInvalidVertexIndex || v.value() >= table_.num_vertices()) + if (v == kInvalidVertexIndex || v.value() >= table_.num_vertices()) { return -1; + } return ConfidentValenceFromCache(v); } diff --git a/extern/draco/dracoenc/src/draco/metadata/geometry_metadata.cc b/extern/draco/draco/src/draco/metadata/geometry_metadata.cc index 896663ae8ab..b83898140ae 100644 --- a/extern/draco/dracoenc/src/draco/metadata/geometry_metadata.cc +++ b/extern/draco/draco/src/draco/metadata/geometry_metadata.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/metadata/geometry_metadata.h" + #include <utility> namespace draco { @@ -21,10 +22,12 @@ const AttributeMetadata *GeometryMetadata::GetAttributeMetadataByStringEntry( const std::string &entry_name, const std::string &entry_value) const { for (auto &&att_metadata : att_metadatas_) { std::string value; - if (!att_metadata->GetEntryString(entry_name, &value)) + if (!att_metadata->GetEntryString(entry_name, &value)) { continue; - if (value == entry_value) + } + if (value == entry_value) { return att_metadata.get(); + } } // No attribute has the requested entry. return nullptr; @@ -32,8 +35,9 @@ const AttributeMetadata *GeometryMetadata::GetAttributeMetadataByStringEntry( bool GeometryMetadata::AddAttributeMetadata( std::unique_ptr<AttributeMetadata> att_metadata) { - if (!att_metadata.get()) + if (!att_metadata.get()) { return false; + } att_metadatas_.push_back(std::move(att_metadata)); return true; } diff --git a/extern/draco/dracoenc/src/draco/metadata/geometry_metadata.h b/extern/draco/draco/src/draco/metadata/geometry_metadata.h index 9f668f7fa15..ec7ecb9ee68 100644 --- a/extern/draco/dracoenc/src/draco/metadata/geometry_metadata.h +++ b/extern/draco/draco/src/draco/metadata/geometry_metadata.h @@ -51,11 +51,12 @@ struct AttributeMetadataHasher { return hash; } }; + // Class for representing the metadata for a point cloud. It could have a list // of attribute metadata. class GeometryMetadata : public Metadata { public: - GeometryMetadata(){}; + GeometryMetadata() {} explicit GeometryMetadata(const Metadata &metadata) : Metadata(metadata) {} const AttributeMetadata *GetAttributeMetadataByStringEntry( @@ -63,9 +64,12 @@ class GeometryMetadata : public Metadata { bool AddAttributeMetadata(std::unique_ptr<AttributeMetadata> att_metadata); void DeleteAttributeMetadataByUniqueId(int32_t att_unique_id) { + if (att_unique_id < 0) { + return; + } for (auto itr = att_metadatas_.begin(); itr != att_metadatas_.end(); ++itr) { - if (itr->get()->att_unique_id() == att_unique_id) { + if (itr->get()->att_unique_id() == static_cast<uint32_t>(att_unique_id)) { att_metadatas_.erase(itr); return; } @@ -74,10 +78,15 @@ class GeometryMetadata : public Metadata { const AttributeMetadata *GetAttributeMetadataByUniqueId( int32_t att_unique_id) const { + if (att_unique_id < 0) { + return nullptr; + } + // TODO(draco-eng): Consider using unordered_map instead of vector to store // attribute metadata. for (auto &&att_metadata : att_metadatas_) { - if (att_metadata->att_unique_id() == att_unique_id) { + if (att_metadata->att_unique_id() == + static_cast<uint32_t>(att_unique_id)) { return att_metadata.get(); } } @@ -85,10 +94,15 @@ class GeometryMetadata : public Metadata { } AttributeMetadata *attribute_metadata(int32_t att_unique_id) { + if (att_unique_id < 0) { + return nullptr; + } + // TODO(draco-eng): Consider use unordered_map instead of vector to store // attribute metadata. for (auto &&att_metadata : att_metadatas_) { - if (att_metadata->att_unique_id() == att_unique_id) { + if (att_metadata->att_unique_id() == + static_cast<uint32_t>(att_unique_id)) { return att_metadata.get(); } } diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata.cc b/extern/draco/draco/src/draco/metadata/metadata.cc index ca82d163bf8..9141907ed71 100644 --- a/extern/draco/dracoenc/src/draco/metadata/metadata.cc +++ b/extern/draco/draco/src/draco/metadata/metadata.cc @@ -13,6 +13,7 @@ // limitations under the License. // #include "draco/metadata/metadata.h" + #include <utility> namespace draco { @@ -29,8 +30,9 @@ EntryValue::EntryValue(const std::string &value) { template <> bool EntryValue::GetValue(std::string *value) const { - if (data_.empty()) + if (data_.empty()) { return false; + } value->resize(data_.size()); memcpy(&value->at(0), &data_[0], data_.size()); return true; diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata.h b/extern/draco/draco/src/draco/metadata/metadata.h index bf0be36f3b1..56d05e46a3e 100644 --- a/extern/draco/dracoenc/src/draco/metadata/metadata.h +++ b/extern/draco/draco/src/draco/metadata/metadata.h @@ -16,9 +16,9 @@ #define DRACO_METADATA_METADATA_H_ #include <cstring> +#include <map> #include <memory> #include <string> -#include <map> #include <vector> #include "draco/core/hash_utils.h" @@ -59,8 +59,9 @@ class EntryValue { template <typename DataTypeT> bool GetValue(std::vector<DataTypeT> *value) const { - if (data_.empty()) + if (data_.empty()) { return false; + } const size_t data_type_size = sizeof(DataTypeT); if (data_.size() % data_type_size != 0) { return false; @@ -82,7 +83,7 @@ class EntryValue { struct EntryValueHasher { size_t operator()(const EntryValue &ev) const { size_t hash = ev.data_.size(); - for (int i = 0; i < ev.data_.size(); ++i) { + for (size_t i = 0; i < ev.data_.size(); ++i) { hash = HashCombine(ev.data_[i], hash); } return hash; @@ -150,11 +151,9 @@ class Metadata { void RemoveEntry(const std::string &name); int num_entries() const { return static_cast<int>(entries_.size()); } - const std::map<std::string, EntryValue> &entries() const { - return entries_; - } - const std::map<std::string, std::unique_ptr<Metadata>> - &sub_metadatas() const { + const std::map<std::string, EntryValue> &entries() const { return entries_; } + const std::map<std::string, std::unique_ptr<Metadata>> &sub_metadatas() + const { return sub_metadatas_; } @@ -163,8 +162,9 @@ class Metadata { template <typename DataTypeT> void AddEntry(const std::string &entry_name, const DataTypeT &entry_value) { const auto itr = entries_.find(entry_name); - if (itr != entries_.end()) + if (itr != entries_.end()) { entries_.erase(itr); + } entries_.insert(std::make_pair(entry_name, EntryValue(entry_value))); } diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_decoder.cc b/extern/draco/draco/src/draco/metadata/metadata_decoder.cc index 62acc26772a..e664e4fa524 100644 --- a/extern/draco/dracoenc/src/draco/metadata/metadata_decoder.cc +++ b/extern/draco/draco/src/draco/metadata/metadata_decoder.cc @@ -24,80 +24,119 @@ MetadataDecoder::MetadataDecoder() : buffer_(nullptr) {} bool MetadataDecoder::DecodeMetadata(DecoderBuffer *in_buffer, Metadata *metadata) { - if (!metadata) + if (!metadata) { return false; + } buffer_ = in_buffer; return DecodeMetadata(metadata); } bool MetadataDecoder::DecodeGeometryMetadata(DecoderBuffer *in_buffer, GeometryMetadata *metadata) { - if (!metadata) + if (!metadata) { return false; + } buffer_ = in_buffer; uint32_t num_att_metadata = 0; - DecodeVarint(&num_att_metadata, buffer_); + if (!DecodeVarint(&num_att_metadata, buffer_)) { + return false; + } // Decode attribute metadata. for (uint32_t i = 0; i < num_att_metadata; ++i) { uint32_t att_unique_id; - DecodeVarint(&att_unique_id, buffer_); + if (!DecodeVarint(&att_unique_id, buffer_)) { + return false; + } std::unique_ptr<AttributeMetadata> att_metadata = std::unique_ptr<AttributeMetadata>(new AttributeMetadata()); att_metadata->set_att_unique_id(att_unique_id); - if (!DecodeMetadata(static_cast<Metadata *>(att_metadata.get()))) + if (!DecodeMetadata(static_cast<Metadata *>(att_metadata.get()))) { return false; + } metadata->AddAttributeMetadata(std::move(att_metadata)); } return DecodeMetadata(static_cast<Metadata *>(metadata)); } bool MetadataDecoder::DecodeMetadata(Metadata *metadata) { - uint32_t num_entries = 0; - DecodeVarint(&num_entries, buffer_); - for (uint32_t i = 0; i < num_entries; ++i) { - if (!DecodeEntry(metadata)) + struct MetadataPair { + Metadata *parent_metadata; + Metadata *decoded_metadata; + }; + std::vector<MetadataPair> metadata_stack; + metadata_stack.push_back({nullptr, metadata}); + while (!metadata_stack.empty()) { + const MetadataPair mp = metadata_stack.back(); + metadata_stack.pop_back(); + metadata = mp.decoded_metadata; + + if (mp.parent_metadata != nullptr) { + std::string sub_metadata_name; + if (!DecodeName(&sub_metadata_name)) { + return false; + } + std::unique_ptr<Metadata> sub_metadata = + std::unique_ptr<Metadata>(new Metadata()); + metadata = sub_metadata.get(); + mp.parent_metadata->AddSubMetadata(sub_metadata_name, + std::move(sub_metadata)); + } + if (metadata == nullptr) { return false; - } - uint32_t num_sub_metadata = 0; - DecodeVarint(&num_sub_metadata, buffer_); - for (uint32_t i = 0; i < num_sub_metadata; ++i) { - std::string sub_metadata_name; - if (!DecodeName(&sub_metadata_name)) + } + + uint32_t num_entries = 0; + if (!DecodeVarint(&num_entries, buffer_)) { return false; - std::unique_ptr<Metadata> sub_metadata = - std::unique_ptr<Metadata>(new Metadata()); - if (!DecodeMetadata(sub_metadata.get())) + } + for (uint32_t i = 0; i < num_entries; ++i) { + if (!DecodeEntry(metadata)) { + return false; + } + } + uint32_t num_sub_metadata = 0; + if (!DecodeVarint(&num_sub_metadata, buffer_)) { return false; - metadata->AddSubMetadata(sub_metadata_name, std::move(sub_metadata)); + } + for (uint32_t i = 0; i < num_sub_metadata; ++i) { + metadata_stack.push_back({metadata, nullptr}); + } } return true; } bool MetadataDecoder::DecodeEntry(Metadata *metadata) { std::string entry_name; - if (!DecodeName(&entry_name)) + if (!DecodeName(&entry_name)) { return false; + } uint32_t data_size = 0; - if (!DecodeVarint(&data_size, buffer_)) + if (!DecodeVarint(&data_size, buffer_)) { return false; - if (data_size == 0) + } + if (data_size == 0) { return false; + } std::vector<uint8_t> entry_value(data_size); - if (!buffer_->Decode(&entry_value[0], data_size)) + if (!buffer_->Decode(&entry_value[0], data_size)) { return false; + } metadata->AddEntryBinary(entry_name, entry_value); return true; } bool MetadataDecoder::DecodeName(std::string *name) { uint8_t name_len = 0; - if (!buffer_->Decode(&name_len)) + if (!buffer_->Decode(&name_len)) { return false; + } name->resize(name_len); - if (name_len == 0) + if (name_len == 0) { return true; - if (!buffer_->Decode(&name->at(0), name_len)) + } + if (!buffer_->Decode(&name->at(0), name_len)) { return false; + } return true; } } // namespace draco diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_decoder.h b/extern/draco/draco/src/draco/metadata/metadata_decoder.h index b4c4943fbaa..b4c4943fbaa 100644 --- a/extern/draco/dracoenc/src/draco/metadata/metadata_decoder.h +++ b/extern/draco/draco/src/draco/metadata/metadata_decoder.h diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.cc b/extern/draco/draco/src/draco/metadata/metadata_encoder.cc index 6e85ce6f9d9..168be83c6b2 100644 --- a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.cc +++ b/extern/draco/draco/src/draco/metadata/metadata_encoder.cc @@ -25,8 +25,9 @@ bool MetadataEncoder::EncodeMetadata(EncoderBuffer *out_buffer, EncodeVarint(static_cast<uint32_t>(metadata->num_entries()), out_buffer); // Encode all entries. for (const auto &entry : entries) { - if (!EncodeString(out_buffer, entry.first)) + if (!EncodeString(out_buffer, entry.first)) { return false; + } const std::vector<uint8_t> &entry_value = entry.second.data(); const uint32_t data_size = static_cast<uint32_t>(entry_value.size()); EncodeVarint(data_size, out_buffer); @@ -38,8 +39,9 @@ bool MetadataEncoder::EncodeMetadata(EncoderBuffer *out_buffer, EncodeVarint(static_cast<uint32_t>(sub_metadatas.size()), out_buffer); // Encode each sub-metadata for (auto &&sub_metadata_entry : sub_metadatas) { - if (!EncodeString(out_buffer, sub_metadata_entry.first)) + if (!EncodeString(out_buffer, sub_metadata_entry.first)) { return false; + } EncodeMetadata(out_buffer, sub_metadata_entry.second.get()); } @@ -48,8 +50,9 @@ bool MetadataEncoder::EncodeMetadata(EncoderBuffer *out_buffer, bool MetadataEncoder::EncodeAttributeMetadata( EncoderBuffer *out_buffer, const AttributeMetadata *metadata) { - if (!metadata) + if (!metadata) { return false; + } // Encode attribute id. EncodeVarint(metadata->att_unique_id(), out_buffer); EncodeMetadata(out_buffer, static_cast<const Metadata *>(metadata)); @@ -58,8 +61,9 @@ bool MetadataEncoder::EncodeAttributeMetadata( bool MetadataEncoder::EncodeGeometryMetadata(EncoderBuffer *out_buffer, const GeometryMetadata *metadata) { - if (!metadata) + if (!metadata) { return false; + } // Encode number of attribute metadata. const std::vector<std::unique_ptr<AttributeMetadata>> &att_metadatas = metadata->attribute_metadatas(); @@ -79,8 +83,9 @@ bool MetadataEncoder::EncodeString(EncoderBuffer *out_buffer, const std::string &str) { // We only support string of maximum length 255 which is using one byte to // encode the length. - if (str.size() > 255) + if (str.size() > 255) { return false; + } if (str.empty()) { out_buffer->Encode(static_cast<uint8_t>(0)); } else { diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.h b/extern/draco/draco/src/draco/metadata/metadata_encoder.h index 5bce5d5b50e..5bce5d5b50e 100644 --- a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.h +++ b/extern/draco/draco/src/draco/metadata/metadata_encoder.h diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.cc b/extern/draco/draco/src/draco/point_cloud/point_cloud.cc index 9552654be16..8eb638f80d4 100644 --- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.cc +++ b/extern/draco/draco/src/draco/point_cloud/point_cloud.cc @@ -23,8 +23,9 @@ PointCloud::PointCloud() : num_points_(0) {} int32_t PointCloud::NumNamedAttributes(GeometryAttribute::Type type) const { if (type == GeometryAttribute::INVALID || - type >= GeometryAttribute::NAMED_ATTRIBUTES_COUNT) + type >= GeometryAttribute::NAMED_ATTRIBUTES_COUNT) { return 0; + } return static_cast<int32_t>(named_attribute_index_[type].size()); } @@ -34,8 +35,9 @@ int32_t PointCloud::GetNamedAttributeId(GeometryAttribute::Type type) const { int32_t PointCloud::GetNamedAttributeId(GeometryAttribute::Type type, int i) const { - if (NumNamedAttributes(type) <= i) + if (NumNamedAttributes(type) <= i) { return -1; + } return named_attribute_index_[type][i]; } @@ -47,8 +49,9 @@ const PointAttribute *PointCloud::GetNamedAttribute( const PointAttribute *PointCloud::GetNamedAttribute( GeometryAttribute::Type type, int i) const { const int32_t att_id = GetNamedAttributeId(type, i); - if (att_id == -1) + if (att_id == -1) { return nullptr; + } return attributes_[att_id].get(); } @@ -57,8 +60,9 @@ const PointAttribute *PointCloud::GetNamedAttributeByUniqueId( for (size_t att_id = 0; att_id < named_attribute_index_[type].size(); ++att_id) { if (attributes_[named_attribute_index_[type][att_id]]->unique_id() == - unique_id) + unique_id) { return attributes_[named_attribute_index_[type][att_id]].get(); + } } return nullptr; } @@ -66,15 +70,17 @@ const PointAttribute *PointCloud::GetNamedAttributeByUniqueId( const PointAttribute *PointCloud::GetAttributeByUniqueId( uint32_t unique_id) const { const int32_t att_id = GetAttributeIdByUniqueId(unique_id); - if (att_id == -1) + if (att_id == -1) { return nullptr; + } return attributes_[att_id].get(); } int32_t PointCloud::GetAttributeIdByUniqueId(uint32_t unique_id) const { for (size_t att_id = 0; att_id < attributes_.size(); ++att_id) { - if (attributes_[att_id]->unique_id() == unique_id) + if (attributes_[att_id]->unique_id() == unique_id) { return static_cast<int32_t>(att_id); + } } return -1; } @@ -88,8 +94,9 @@ int PointCloud::AddAttribute( const GeometryAttribute &att, bool identity_mapping, AttributeValueIndex::ValueType num_attribute_values) { auto pa = CreateAttribute(att, identity_mapping, num_attribute_values); - if (!pa) + if (!pa) { return -1; + } const int32_t att_id = AddAttribute(std::move(pa)); return att_id; } @@ -97,8 +104,9 @@ int PointCloud::AddAttribute( std::unique_ptr<PointAttribute> PointCloud::CreateAttribute( const GeometryAttribute &att, bool identity_mapping, AttributeValueIndex::ValueType num_attribute_values) const { - if (att.attribute_type() == GeometryAttribute::INVALID) + if (att.attribute_type() == GeometryAttribute::INVALID) { return nullptr; + } std::unique_ptr<PointAttribute> pa = std::unique_ptr<PointAttribute>(new PointAttribute(att)); // Initialize point cloud specific attribute data. @@ -107,7 +115,7 @@ std::unique_ptr<PointAttribute> PointCloud::CreateAttribute( pa->SetExplicitMapping(num_points_); } else { pa->SetIdentityMapping(); - pa->Resize(num_points_); + num_attribute_values = std::max(num_points_, num_attribute_values); } if (num_attribute_values > 0) { pa->Reset(num_attribute_values); @@ -128,8 +136,9 @@ void PointCloud::SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa) { } void PointCloud::DeleteAttribute(int att_id) { - if (att_id < 0 || att_id >= attributes_.size()) + if (att_id < 0 || att_id >= attributes_.size()) { return; // Attribute does not exist. + } const GeometryAttribute::Type att_type = attributes_[att_id]->attribute_type(); const uint32_t unique_id = attribute(att_id)->unique_id(); @@ -143,8 +152,9 @@ void PointCloud::DeleteAttribute(int att_id) { if (att_type < GeometryAttribute::NAMED_ATTRIBUTES_COUNT) { const auto it = std::find(named_attribute_index_[att_type].begin(), named_attribute_index_[att_type].end(), att_id); - if (it != named_attribute_index_[att_type].end()) + if (it != named_attribute_index_[att_type].end()) { named_attribute_index_[att_type].erase(it); + } } // Update ids of all subsequent named attributes (decrease them by one). @@ -173,8 +183,9 @@ void PointCloud::DeduplicatePointIds() { for (int32_t i = 0; i < this->num_attributes(); ++i) { const AttributeValueIndex att_id0 = attribute(i)->mapped_index(p0); const AttributeValueIndex att_id1 = attribute(i)->mapped_index(p1); - if (att_id0 != att_id1) + if (att_id0 != att_id1) { return false; + } } return true; }; @@ -196,8 +207,9 @@ void PointCloud::DeduplicatePointIds() { unique_points.push_back(i); } } - if (num_unique_points == num_points_) + if (num_unique_points == num_points_) { return; // All vertices are already unique. + } ApplyPointIdDeduplication(index_map, unique_points); set_num_points(num_unique_points); @@ -228,12 +240,14 @@ void PointCloud::ApplyPointIdDeduplication( #ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED bool PointCloud::DeduplicateAttributeValues() { // Go over all attributes and create mapping between duplicate entries. - if (num_points() == 0) + if (num_points() == 0) { return false; // Unexpected attribute size. + } // Deduplicate all attributes. for (int32_t att_id = 0; att_id < num_attributes(); ++att_id) { - if (!attribute(att_id)->DeduplicateValues(*attribute(att_id))) + if (!attribute(att_id)->DeduplicateValues(*attribute(att_id))) { return false; + } } return true; } @@ -257,7 +271,8 @@ BoundingBox PointCloud::ComputeBoundingBox() const { // Consider using pc_att->ConvertValue<float, 3>(i, &p[0]) (Enforced // transformation from Vector with any dimension to Vector3f) Vector3f p; - for (AttributeValueIndex i(0); i < pc_att->size(); ++i) { + for (AttributeValueIndex i(0); i < static_cast<uint32_t>(pc_att->size()); + ++i) { pc_att->GetValue(i, &p[0]); bounding_box.update_bounding_box(p); } diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.h b/extern/draco/draco/src/draco/point_cloud/point_cloud.h index e15206f17c4..d11bd47a366 100644 --- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.h +++ b/extern/draco/draco/src/draco/point_cloud/point_cloud.h @@ -15,11 +15,10 @@ #ifndef DRACO_POINT_CLOUD_POINT_CLOUD_H_ #define DRACO_POINT_CLOUD_POINT_CLOUD_H_ -#include "draco/draco_features.h" - #include "draco/attributes/point_attribute.h" #include "draco/core/bounding_box.h" #include "draco/core/vector_d.h" +#include "draco/draco_features.h" #include "draco/metadata/geometry_metadata.h" namespace draco { @@ -131,7 +130,7 @@ class PointCloud { // Add metadata for an attribute. void AddAttributeMetadata(int32_t att_id, std::unique_ptr<AttributeMetadata> metadata) { - if (!metadata_.get()) { + if (!metadata_) { metadata_ = std::unique_ptr<GeometryMetadata>(new GeometryMetadata()); } const int32_t att_unique_id = attribute(att_id)->unique_id(); @@ -141,8 +140,9 @@ class PointCloud { const AttributeMetadata *GetAttributeMetadataByAttributeId( int32_t att_id) const { - if (metadata_ == nullptr) + if (metadata_ == nullptr) { return nullptr; + } const uint32_t unique_id = attribute(att_id)->unique_id(); return metadata_->GetAttributeMetadataByUniqueId(unique_id); } @@ -150,20 +150,23 @@ class PointCloud { // Returns the attribute metadata that has the requested metadata entry. const AttributeMetadata *GetAttributeMetadataByStringEntry( const std::string &name, const std::string &value) const { - if (metadata_ == nullptr) + if (metadata_ == nullptr) { return nullptr; + } return metadata_->GetAttributeMetadataByStringEntry(name, value); } // Returns the first attribute that has the requested metadata entry. int GetAttributeIdByMetadataEntry(const std::string &name, const std::string &value) const { - if (metadata_ == nullptr) + if (metadata_ == nullptr) { return -1; + } const AttributeMetadata *att_metadata = metadata_->GetAttributeMetadataByStringEntry(name, value); - if (!att_metadata) + if (!att_metadata) { return -1; + } return GetAttributeIdByUniqueId(att_metadata->att_unique_id()); } @@ -229,8 +232,8 @@ struct PointCloudHasher { } // Hash metadata. GeometryMetadataHasher metadata_hasher; - if (pc.metadata_.get()) { - hash = HashCombine(metadata_hasher(*pc.metadata_.get()), hash); + if (pc.metadata_) { + hash = HashCombine(metadata_hasher(*pc.metadata_), hash); } return hash; } diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.cc b/extern/draco/draco/src/draco/point_cloud/point_cloud_builder.cc index a0381631cfd..431ae505f5f 100644 --- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.cc +++ b/extern/draco/draco/src/draco/point_cloud/point_cloud_builder.cc @@ -43,8 +43,9 @@ void PointCloudBuilder::SetAttributeValuesForAllPoints( PointAttribute *const att = point_cloud_->attribute(att_id); const int data_stride = DataTypeLength(att->data_type()) * att->num_components(); - if (stride == 0) + if (stride == 0) { stride = data_stride; + } if (stride == data_stride) { // Fast copy path. att->buffer()->Write(0, attribute_values, diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.h b/extern/draco/draco/src/draco/point_cloud/point_cloud_builder.h index cf55a728b15..cf55a728b15 100644 --- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.h +++ b/extern/draco/draco/src/draco/point_cloud/point_cloud_builder.h diff --git a/extern/draco/dracoenc/cmake/DracoConfig.cmake b/extern/draco/dracoenc/cmake/DracoConfig.cmake deleted file mode 100644 index be5e1faefe2..00000000000 --- a/extern/draco/dracoenc/cmake/DracoConfig.cmake +++ /dev/null @@ -1,3 +0,0 @@ -@PACKAGE_INIT@ -set_and_check(draco_INCLUDE_DIR "@PACKAGE_draco_include_install_dir@") -set_and_check(draco_LIBRARY_DIR "@PACKAGE_draco_lib_install_dir@") diff --git a/extern/draco/dracoenc/cmake/FindDraco.cmake b/extern/draco/dracoenc/cmake/FindDraco.cmake deleted file mode 100644 index 5f27bf29390..00000000000 --- a/extern/draco/dracoenc/cmake/FindDraco.cmake +++ /dev/null @@ -1,58 +0,0 @@ -# Finddraco -# -# Locates draco and sets the following variables: -# -# draco_FOUND -# draco_INCLUDE_DIRS -# draco_LIBARY_DIRS -# draco_LIBRARIES -# draco_VERSION_STRING -# -# draco_FOUND is set to YES only when all other variables are successfully -# configured. - -unset(draco_FOUND) -unset(draco_INCLUDE_DIRS) -unset(draco_LIBRARY_DIRS) -unset(draco_LIBRARIES) -unset(draco_VERSION_STRING) - -mark_as_advanced(draco_FOUND) -mark_as_advanced(draco_INCLUDE_DIRS) -mark_as_advanced(draco_LIBRARY_DIRS) -mark_as_advanced(draco_LIBRARIES) -mark_as_advanced(draco_VERSION_STRING) - -set(draco_version_file_no_prefix "draco/src/draco/core/draco_version.h") - -# Set draco_INCLUDE_DIRS -find_path(draco_INCLUDE_DIRS NAMES "${draco_version_file_no_prefix}") - -# Extract the version string from draco_version.h. -if (draco_INCLUDE_DIRS) - set(draco_version_file - "${draco_INCLUDE_DIRS}/draco/src/draco/core/draco_version.h") - file(STRINGS "${draco_version_file}" draco_version - REGEX "kdracoVersion") - list(GET draco_version 0 draco_version) - string(REPLACE "static const char kdracoVersion[] = " "" draco_version - "${draco_version}") - string(REPLACE ";" "" draco_version "${draco_version}") - string(REPLACE "\"" "" draco_version "${draco_version}") - set(draco_VERSION_STRING ${draco_version}) -endif () - -# Find the library. -if (BUILD_SHARED_LIBS) - find_library(draco_LIBRARIES NAMES draco.dll libdraco.dylib libdraco.so) -else () - find_library(draco_LIBRARIES NAMES draco.lib libdraco.a) -endif () - -# Store path to library. -get_filename_component(draco_LIBRARY_DIRS ${draco_LIBRARIES} DIRECTORY) - -if (draco_INCLUDE_DIRS AND draco_LIBRARY_DIRS AND draco_LIBRARIES AND - draco_VERSION_STRING) - set(draco_FOUND YES) -endif () diff --git a/extern/draco/dracoenc/cmake/compiler_flags.cmake b/extern/draco/dracoenc/cmake/compiler_flags.cmake deleted file mode 100644 index bbfb069d2d3..00000000000 --- a/extern/draco/dracoenc/cmake/compiler_flags.cmake +++ /dev/null @@ -1,216 +0,0 @@ -if (NOT DRACO_CMAKE_COMPILER_FLAGS_CMAKE_) -set(DRACO_CMAKE_COMPILER_FLAGS_CMAKE_ 1) - -include(CheckCCompilerFlag) -include(CheckCXXCompilerFlag) -include("${draco_root}/cmake/compiler_tests.cmake") - -# Strings used to cache failed C/CXX flags. -set(DRACO_FAILED_C_FLAGS) -set(DRACO_FAILED_CXX_FLAGS) - -# Checks C compiler for support of $c_flag. Adds $c_flag to $CMAKE_C_FLAGS when -# the compile test passes. Caches $c_flag in $DRACO_FAILED_C_FLAGS when the test -# fails. -macro (add_c_flag_if_supported c_flag) - unset(C_FLAG_FOUND CACHE) - string(FIND "${CMAKE_C_FLAGS}" "${c_flag}" C_FLAG_FOUND) - unset(C_FLAG_FAILED CACHE) - string(FIND "${DRACO_FAILED_C_FLAGS}" "${c_flag}" C_FLAG_FAILED) - - if (${C_FLAG_FOUND} EQUAL -1 AND ${C_FLAG_FAILED} EQUAL -1) - unset(C_FLAG_SUPPORTED CACHE) - message("Checking C compiler flag support for: " ${c_flag}) - check_c_compiler_flag("${c_flag}" C_FLAG_SUPPORTED) - if (${C_FLAG_SUPPORTED}) - string(APPEND CMAKE_C_FLAGS " ${c_flag}" CACHE STRING "") - else () - string(APPEND DRACO_FAILED_C_FLAGS " ${c_flag}" CACHE STRING - "" FORCE) - endif () - endif () -endmacro () - -# Checks C++ compiler for support of $cxx_flag. Adds $cxx_flag to -# $CMAKE_CXX_FLAGS when the compile test passes. Caches $c_flag in -# $DRACO_FAILED_CXX_FLAGS when the test fails. -macro (add_cxx_flag_if_supported cxx_flag) - unset(CXX_FLAG_FOUND CACHE) - string(FIND "${CMAKE_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FOUND) - unset(CXX_FLAG_FAILED CACHE) - string(FIND "${DRACO_FAILED_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FAILED) - - if (${CXX_FLAG_FOUND} EQUAL -1 AND ${CXX_FLAG_FAILED} EQUAL -1) - unset(CXX_FLAG_SUPPORTED CACHE) - message("Checking CXX compiler flag support for: " ${cxx_flag}) - check_cxx_compiler_flag("${cxx_flag}" CXX_FLAG_SUPPORTED) - if (${CXX_FLAG_SUPPORTED}) - string(APPEND CMAKE_CXX_FLAGS " ${cxx_flag}" CACHE STRING "") - else() - string(APPEND DRACO_FAILED_CXX_FLAGS " ${cxx_flag}" CACHE - STRING "" FORCE) - endif () - endif () -endmacro () - -# Convenience method for adding a flag to both the C and C++ compiler command -# lines. -macro (add_compiler_flag_if_supported flag) - add_c_flag_if_supported(${flag}) - add_cxx_flag_if_supported(${flag}) -endmacro () - -# Checks C compiler for support of $c_flag and terminates generation when -# support is not present. -macro (require_c_flag c_flag update_c_flags) - unset(C_FLAG_FOUND CACHE) - string(FIND "${CMAKE_C_FLAGS}" "${c_flag}" C_FLAG_FOUND) - - if (${C_FLAG_FOUND} EQUAL -1) - unset(HAVE_C_FLAG CACHE) - message("Checking C compiler flag support for: " ${c_flag}) - check_c_compiler_flag("${c_flag}" HAVE_C_FLAG) - if (NOT ${HAVE_C_FLAG}) - message(FATAL_ERROR - "${PROJECT_NAME} requires support for C flag: ${c_flag}.") - endif () - if (${update_c_flags}) - set(CMAKE_C_FLAGS "${c_flag} ${CMAKE_C_FLAGS}" CACHE STRING "" FORCE) - endif () - endif () -endmacro () - -# Checks CXX compiler for support of $cxx_flag and terminates generation when -# support is not present. -macro (require_cxx_flag cxx_flag update_cxx_flags) - unset(CXX_FLAG_FOUND CACHE) - string(FIND "${CMAKE_CXX_FLAGS}" "${cxx_flag}" CXX_FLAG_FOUND) - - if (${CXX_FLAG_FOUND} EQUAL -1) - unset(HAVE_CXX_FLAG CACHE) - message("Checking CXX compiler flag support for: " ${cxx_flag}) - check_cxx_compiler_flag("${cxx_flag}" HAVE_CXX_FLAG) - if (NOT ${HAVE_CXX_FLAG}) - message(FATAL_ERROR - "${PROJECT_NAME} requires support for CXX flag: ${cxx_flag}.") - endif () - if (${update_cxx_flags}) - set(CMAKE_CXX_FLAGS "${cxx_flag} ${CMAKE_CXX_FLAGS}" CACHE STRING "" - FORCE) - endif () - endif () -endmacro () - -# Checks for support of $flag by both the C and CXX compilers. Terminates -# generation when support is not present in both compilers. -macro (require_compiler_flag flag update_cmake_flags) - require_c_flag(${flag} ${update_cmake_flags}) - require_cxx_flag(${flag} ${update_cmake_flags}) -endmacro () - -# Checks only non-MSVC targets for support of $c_flag and terminates generation -# when support is not present. -macro (require_c_flag_nomsvc c_flag update_c_flags) - if (NOT MSVC) - require_c_flag(${c_flag} ${update_c_flags}) - endif () -endmacro () - -# Checks only non-MSVC targets for support of $cxx_flag and terminates -# generation when support is not present. -macro (require_cxx_flag_nomsvc cxx_flag update_cxx_flags) - if (NOT MSVC) - require_cxx_flag(${cxx_flag} ${update_cxx_flags}) - endif () -endmacro () - -# Checks only non-MSVC targets for support of $flag by both the C and CXX -# compilers. Terminates generation when support is not present in both -# compilers. -macro (require_compiler_flag_nomsvc flag update_cmake_flags) - require_c_flag_nomsvc(${flag} ${update_cmake_flags}) - require_cxx_flag_nomsvc(${flag} ${update_cmake_flags}) -endmacro () - -# Adds $flag to assembler command line. -macro (append_as_flag flag) - unset(AS_FLAG_FOUND CACHE) - string(FIND "${DRACO_AS_FLAGS}" "${flag}" AS_FLAG_FOUND) - - if (${AS_FLAG_FOUND} EQUAL -1) - string(APPEND DRACO_AS_FLAGS " ${flag}") - endif () -endmacro () - -# Adds $flag to the C compiler command line. -macro (append_c_flag flag) - unset(C_FLAG_FOUND CACHE) - string(FIND "${CMAKE_C_FLAGS}" "${flag}" C_FLAG_FOUND) - - if (${C_FLAG_FOUND} EQUAL -1) - string(APPEND CMAKE_C_FLAGS " ${flag}") - endif () -endmacro () - -# Adds $flag to the CXX compiler command line. -macro (append_cxx_flag flag) - unset(CXX_FLAG_FOUND CACHE) - string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" CXX_FLAG_FOUND) - - if (${CXX_FLAG_FOUND} EQUAL -1) - string(APPEND CMAKE_CXX_FLAGS " ${flag}") - endif () -endmacro () - -# Adds $flag to the C and CXX compiler command lines. -macro (append_compiler_flag flag) - append_c_flag(${flag}) - append_cxx_flag(${flag}) -endmacro () - -# Adds $flag to the executable linker command line. -macro (append_exe_linker_flag flag) - unset(LINKER_FLAG_FOUND CACHE) - string(FIND "${CMAKE_EXE_LINKER_FLAGS}" "${flag}" LINKER_FLAG_FOUND) - - if (${LINKER_FLAG_FOUND} EQUAL -1) - string(APPEND CMAKE_EXE_LINKER_FLAGS " ${flag}") - endif () -endmacro () - -# Adds $flag to the link flags for $target. -function (append_link_flag_to_target target flags) - unset(target_link_flags) - get_target_property(target_link_flags ${target} LINK_FLAGS) - - if (target_link_flags) - unset(link_flag_found) - string(FIND "${target_link_flags}" "${flags}" link_flag_found) - - if (NOT ${link_flag_found} EQUAL -1) - return() - endif () - - string(APPEND target_link_flags " ${flags}") - else () - set(target_link_flags "${flags}") - endif () - - set_target_properties(${target} PROPERTIES LINK_FLAGS ${target_link_flags}) -endfunction () - -# Adds $flag to executable linker flags, and makes sure C/CXX builds still work. -macro (require_linker_flag flag) - append_exe_linker_flag(${flag}) - - unset(c_passed) - draco_check_c_compiles("LINKER_FLAG_C_TEST(${flag})" "" c_passed) - unset(cxx_passed) - draco_check_cxx_compiles("LINKER_FLAG_CXX_TEST(${flag})" "" cxx_passed) - - if (NOT c_passed OR NOT cxx_passed) - message(FATAL_ERROR "Linker flag test for ${flag} failed.") - endif () -endmacro () - -endif () # DRACO_CMAKE_COMPILER_FLAGS_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/compiler_tests.cmake b/extern/draco/dracoenc/cmake/compiler_tests.cmake deleted file mode 100644 index 7cc3fbfc67d..00000000000 --- a/extern/draco/dracoenc/cmake/compiler_tests.cmake +++ /dev/null @@ -1,124 +0,0 @@ -if (NOT DRACO_CMAKE_COMPILER_TESTS_CMAKE_) -set(DRACO_CMAKE_COMPILER_TESTS_CMAKE_ 1) - -include(CheckCSourceCompiles) -include(CheckCXXSourceCompiles) - -# The basic main() macro used in all compile tests. -set(DRACO_C_MAIN "\nint main(void) { return 0; }") -set(DRACO_CXX_MAIN "\nint main() { return 0; }") - -# Strings containing the names of passed and failed tests. -set(DRACO_C_PASSED_TESTS) -set(DRACO_C_FAILED_TESTS) -set(DRACO_CXX_PASSED_TESTS) -set(DRACO_CXX_FAILED_TESTS) - -macro(draco_push_var var new_value) - set(SAVED_${var} ${var}) - set(${var} ${new_value}) -endmacro () - -macro(draco_pop_var var) - set(var ${SAVED_${var}}) - unset(SAVED_${var}) -endmacro () - -# Confirms $test_source compiles and stores $test_name in one of -# $DRACO_C_PASSED_TESTS or $DRACO_C_FAILED_TESTS depending on out come. When the -# test passes $result_var is set to 1. When it fails $result_var is unset. -# The test is not run if the test name is found in either of the passed or -# failed test variables. -macro(draco_check_c_compiles test_name test_source result_var) - unset(C_TEST_PASSED CACHE) - unset(C_TEST_FAILED CACHE) - string(FIND "${DRACO_C_PASSED_TESTS}" "${test_name}" C_TEST_PASSED) - string(FIND "${DRACO_C_FAILED_TESTS}" "${test_name}" C_TEST_FAILED) - if (${C_TEST_PASSED} EQUAL -1 AND ${C_TEST_FAILED} EQUAL -1) - unset(C_TEST_COMPILED CACHE) - message("Running C compiler test: ${test_name}") - check_c_source_compiles("${test_source} ${DRACO_C_MAIN}" C_TEST_COMPILED) - set(${result_var} ${C_TEST_COMPILED}) - - if (${C_TEST_COMPILED}) - string(APPEND DRACO_C_PASSED_TESTS " ${test_name}") - else () - string(APPEND DRACO_C_FAILED_TESTS " ${test_name}") - message("C Compiler test ${test_name} failed.") - endif () - elseif (NOT ${C_TEST_PASSED} EQUAL -1) - set(${result_var} 1) - else () # ${C_TEST_FAILED} NOT EQUAL -1 - unset(${result_var}) - endif () -endmacro () - -# Confirms $test_source compiles and stores $test_name in one of -# $DRACO_CXX_PASSED_TESTS or $DRACO_CXX_FAILED_TESTS depending on out come. When -# the test passes $result_var is set to 1. When it fails $result_var is unset. -# The test is not run if the test name is found in either of the passed or -# failed test variables. -macro(draco_check_cxx_compiles test_name test_source result_var) - unset(CXX_TEST_PASSED CACHE) - unset(CXX_TEST_FAILED CACHE) - string(FIND "${DRACO_CXX_PASSED_TESTS}" "${test_name}" CXX_TEST_PASSED) - string(FIND "${DRACO_CXX_FAILED_TESTS}" "${test_name}" CXX_TEST_FAILED) - if (${CXX_TEST_PASSED} EQUAL -1 AND ${CXX_TEST_FAILED} EQUAL -1) - unset(CXX_TEST_COMPILED CACHE) - message("Running CXX compiler test: ${test_name}") - check_cxx_source_compiles("${test_source} ${DRACO_CXX_MAIN}" - CXX_TEST_COMPILED) - set(${result_var} ${CXX_TEST_COMPILED}) - - if (${CXX_TEST_COMPILED}) - string(APPEND DRACO_CXX_PASSED_TESTS " ${test_name}") - else () - string(APPEND DRACO_CXX_FAILED_TESTS " ${test_name}") - message("CXX Compiler test ${test_name} failed.") - endif () - elseif (NOT ${CXX_TEST_PASSED} EQUAL -1) - set(${result_var} 1) - else () # ${CXX_TEST_FAILED} NOT EQUAL -1 - unset(${result_var}) - endif () -endmacro () - -# Convenience macro that confirms $test_source compiles as C and C++. -# $result_var is set to 1 when both tests are successful, and 0 when one or both -# tests fail. -# Note: This macro is intended to be used to write to result variables that -# are expanded via configure_file(). $result_var is set to 1 or 0 to allow -# direct usage of the value in generated source files. -macro(draco_check_source_compiles test_name test_source result_var) - unset(C_PASSED) - unset(CXX_PASSED) - draco_check_c_compiles(${test_name} ${test_source} C_PASSED) - draco_check_cxx_compiles(${test_name} ${test_source} CXX_PASSED) - if (${C_PASSED} AND ${CXX_PASSED}) - set(${result_var} 1) - else () - set(${result_var} 0) - endif () -endmacro () - -# When inline support is detected for the current compiler the supported -# inlining keyword is written to $result in caller scope. -macro (draco_get_inline result) - draco_check_source_compiles("inline_check_1" - "static inline void macro(void) {}" - HAVE_INLINE_1) - if (HAVE_INLINE_1 EQUAL 1) - set(${result} "inline") - return() - endif () - - # Check __inline. - draco_check_source_compiles("inline_check_2" - "static __inline void macro(void) {}" - HAVE_INLINE_2) - if (HAVE_INLINE_2 EQUAL 1) - set(${result} "__inline") - endif () -endmacro () - -endif () # DRACO_CMAKE_COMPILER_TESTS_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/draco_features.cmake b/extern/draco/dracoenc/cmake/draco_features.cmake deleted file mode 100644 index 057b0b07ecd..00000000000 --- a/extern/draco/dracoenc/cmake/draco_features.cmake +++ /dev/null @@ -1,57 +0,0 @@ -if (NOT DRACO_CMAKE_DRACO_FEATURES_CMAKE_) -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 <feature_name> [TARGETS <target_name>]) -# 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}" - "// 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}" "#define ${feature}\n") - endforeach () - - file(APPEND "${draco_features_file_name}" "\n#endif // DRACO_FEATURES_H_") -endfunction () - -endif () # DRACO_CMAKE_DRACO_FEATURES_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/draco_test_config.h.cmake b/extern/draco/dracoenc/cmake/draco_test_config.h.cmake deleted file mode 100644 index 77a574123fd..00000000000 --- a/extern/draco/dracoenc/cmake/draco_test_config.h.cmake +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef DRACO_TESTING_DRACO_TEST_CONFIG_H_ -#define DRACO_TESTING_DRACO_TEST_CONFIG_H_ - -// If this file is named draco_test_config.h.cmake: -// This file is used as input at cmake generation time. - -// If this file is named draco_test_config.h: -// GENERATED FILE, DO NOT EDIT. SEE ABOVE. - -#define DRACO_TEST_DATA_DIR "${DRACO_TEST_DATA_DIR}" -#define DRACO_TEST_TEMP_DIR "${DRACO_TEST_TEMP_DIR}" - -#endif // DRACO_TESTING_DRACO_TEST_CONFIG_H_ diff --git a/extern/draco/dracoenc/cmake/draco_version.cc.cmake b/extern/draco/dracoenc/cmake/draco_version.cc.cmake deleted file mode 100644 index 921df7de77d..00000000000 --- a/extern/draco/dracoenc/cmake/draco_version.cc.cmake +++ /dev/null @@ -1,21 +0,0 @@ -// If this file is named draco_version.cc.cmake: -// This file is used as input at cmake generation time. - -// If this file is named draco_version.cc: -// GENERATED FILE, DO NOT EDIT. SEE ABOVE. -#include "draco_version.h" - -static const char kDracoGitHash[] = "${draco_git_hash}"; -static const char kDracoGitDesc[] = "${draco_git_desc}"; - -const char *draco_git_hash() { - return kDracoGitHash; -} - -const char *draco_git_version() { - return kDracoGitDesc; -} - -const char* draco_version() { - return draco::Version(); -} diff --git a/extern/draco/dracoenc/cmake/draco_version.h.cmake b/extern/draco/dracoenc/cmake/draco_version.h.cmake deleted file mode 100644 index 506423ed34c..00000000000 --- a/extern/draco/dracoenc/cmake/draco_version.h.cmake +++ /dev/null @@ -1,21 +0,0 @@ -// If this file is named draco_version.h.cmake: -// This file is used as input at cmake generation time. - -// If this file is named draco_version.h: -// GENERATED FILE, DO NOT EDIT. SEE ABOVE. -#ifndef DRACO_DRACO_VERSION_H_ -#define DRACO_DRACO_VERSION_H_ - -#include "draco/core/draco_version.h" - -// Returns git hash of Draco git repository. -const char *draco_git_hash(); - -// Returns the output of the git describe command when run from the Draco git -// repository. -const char *draco_git_version(); - -// Returns the version string from core/draco_version.h. -const char* draco_version(); - -#endif // DRACO_DRACO_VERSION_H_ diff --git a/extern/draco/dracoenc/cmake/msvc_runtime.cmake b/extern/draco/dracoenc/cmake/msvc_runtime.cmake deleted file mode 100644 index ca8de08f9a2..00000000000 --- a/extern/draco/dracoenc/cmake/msvc_runtime.cmake +++ /dev/null @@ -1,14 +0,0 @@ -cmake_minimum_required(VERSION 3.2) - -if (MSVC) - # Use statically linked versions of the MS standard libraries. - if (NOT "${MSVC_RUNTIME}" STREQUAL "dll") - foreach (flag_var - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if (${flag_var} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endif () - endforeach () - endif () -endif () diff --git a/extern/draco/dracoenc/cmake/sanitizers.cmake b/extern/draco/dracoenc/cmake/sanitizers.cmake deleted file mode 100644 index e966cd85d52..00000000000 --- a/extern/draco/dracoenc/cmake/sanitizers.cmake +++ /dev/null @@ -1,19 +0,0 @@ -if (NOT DRACO_CMAKE_SANITIZERS_CMAKE_) -set(DRACO_CMAKE_SANITIZERS_CMAKE_ 1) - -if (MSVC OR NOT SANITIZE) - return () -endif () - -include("${draco_root}/cmake/compiler_flags.cmake") - -string(TOLOWER ${SANITIZE} SANITIZE) - -# Require the sanitizer requested. -require_linker_flag("-fsanitize=${SANITIZE}") -require_compiler_flag("-fsanitize=${SANITIZE}" YES) - -# Make callstacks accurate. -require_compiler_flag("-fno-omit-frame-pointer -fno-optimize-sibling-calls" YES) - -endif() # DRACO_CMAKE_SANITIZERS_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/arm-ios-common.cmake b/extern/draco/dracoenc/cmake/toolchains/arm-ios-common.cmake deleted file mode 100644 index 48f5ce5e68c..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/arm-ios-common.cmake +++ /dev/null @@ -1,13 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARM_IOS_COMMON_CMAKE_) -set(DRACO_CMAKE_ARM_IOS_COMMON_CMAKE_ 1) - -set(CMAKE_SYSTEM_NAME "Darwin") -set(CMAKE_OSX_SYSROOT iphoneos) -set(CMAKE_C_COMPILER clang) -set(CMAKE_C_COMPILER_ARG1 "-arch ${CMAKE_SYSTEM_PROCESSOR}") -set(CMAKE_CXX_COMPILER clang++) -set(CMAKE_CXX_COMPILER_ARG1 "-arch ${CMAKE_SYSTEM_PROCESSOR}") - -# TODO(tomfinegan): Handle bit code embedding. - -endif () # DRACO_CMAKE_TOOLCHAINS_ARM_IOS_COMMON_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/arm64-android-ndk-libcpp.cmake b/extern/draco/dracoenc/cmake/toolchains/arm64-android-ndk-libcpp.cmake deleted file mode 100644 index bd044199063..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/arm64-android-ndk-libcpp.cmake +++ /dev/null @@ -1,12 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARM64_ANDROID_NDK_LIBCPP_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_ARM64_ANDROID_NDK_LIBCPP_CMAKE_ 1) - -include("${CMAKE_CURRENT_LIST_DIR}/../util.cmake") - -set(CMAKE_SYSTEM_NAME Android) -set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) -require_variable(CMAKE_ANDROID_NDK) -set_variable_if_unset(CMAKE_SYSTEM_VERSION 21) -set_variable_if_unset(CMAKE_ANDROID_STL_TYPE c++_static) - -endif () # DRACO_CMAKE_TOOLCHAINS_ARM64_ANDROID_NDK_LIBCPP_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/arm64-ios.cmake b/extern/draco/dracoenc/cmake/toolchains/arm64-ios.cmake deleted file mode 100644 index 0d4909e1be3..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/arm64-ios.cmake +++ /dev/null @@ -1,14 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARM64_IOS_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_ARM64_IOS_CMAKE_ 1) - -if (XCODE) - # TODO(tomfinegan): Handle arm builds in Xcode. - message(FATAL_ERROR "This toolchain does not support Xcode.") -endif () - -set(CMAKE_SYSTEM_PROCESSOR "arm64") -set(CMAKE_OSX_ARCHITECTURES "arm64") - -include("${CMAKE_CURRENT_LIST_DIR}/arm-ios-common.cmake") - -endif () # DRACO_CMAKE_TOOLCHAINS_ARM64_IOS_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/arm64-linux-gcc.cmake b/extern/draco/dracoenc/cmake/toolchains/arm64-linux-gcc.cmake deleted file mode 100644 index 3bab482855c..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/arm64-linux-gcc.cmake +++ /dev/null @@ -1,18 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARM64_LINUX_GCC_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_ARM64_LINUX_GCC_CMAKE_ 1) - -set(CMAKE_SYSTEM_NAME "Linux") - -if ("${CROSS}" STREQUAL "") - # Default the cross compiler prefix to something known to work. - set(CROSS aarch64-linux-gnu-) -endif () - -set(CMAKE_C_COMPILER ${CROSS}gcc) -set(CMAKE_CXX_COMPILER ${CROSS}g++) -set(AS_EXECUTABLE ${CROSS}as) -set(CMAKE_C_COMPILER_ARG1 "-march=armv8-a") -set(CMAKE_CXX_COMPILER_ARG1 "-march=armv8-a") -set(CMAKE_SYSTEM_PROCESSOR "arm64") - -endif () # DRACO_CMAKE_TOOLCHAINS_ARM64_LINUX_GCC_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/armv7-android-ndk-libcpp.cmake b/extern/draco/dracoenc/cmake/toolchains/armv7-android-ndk-libcpp.cmake deleted file mode 100644 index fd50defd82e..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/armv7-android-ndk-libcpp.cmake +++ /dev/null @@ -1,12 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARMV7_ANDROID_NDK_LIBCPP_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_ARMV7_ANDROID_NDK_LIBCPP_CMAKE_ 1) - -include("${CMAKE_CURRENT_LIST_DIR}/../util.cmake") - -set(CMAKE_SYSTEM_NAME Android) -set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a) -require_variable(CMAKE_ANDROID_NDK) -set_variable_if_unset(CMAKE_SYSTEM_VERSION 18) -set_variable_if_unset(CMAKE_ANDROID_STL_TYPE c++_static) - -endif () # DRACO_CMAKE_TOOLCHAINS_ARMV7_ANDROID_NDK_LIBCPP_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/armv7-ios.cmake b/extern/draco/dracoenc/cmake/toolchains/armv7-ios.cmake deleted file mode 100644 index 61d67872917..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/armv7-ios.cmake +++ /dev/null @@ -1,14 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARMV7_IOS_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_ARMV7_IOS_CMAKE_ 1) - -if (XCODE) - # TODO(tomfinegan): Handle arm builds in Xcode. - message(FATAL_ERROR "This toolchain does not support Xcode.") -endif () - -set(CMAKE_SYSTEM_PROCESSOR "armv7") -set(CMAKE_OSX_ARCHITECTURES "armv7") - -include("${CMAKE_CURRENT_LIST_DIR}/arm-ios-common.cmake") - -endif () # DRACO_CMAKE_TOOLCHAINS_ARMV7_IOS_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/armv7-linux-gcc.cmake b/extern/draco/dracoenc/cmake/toolchains/armv7-linux-gcc.cmake deleted file mode 100644 index e0f850f4270..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/armv7-linux-gcc.cmake +++ /dev/null @@ -1,24 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARMV7_LINUX_GCC_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_ARMV7_LINUX_GCC_CMAKE_ 1) - -set(CMAKE_SYSTEM_NAME "Linux") - -if ("${CROSS}" STREQUAL "") - # Default the cross compiler prefix to something known to work. - set(CROSS arm-linux-gnueabihf-) -endif () - -if (NOT ${CROSS} MATCHES hf-$) - set(DRACO_EXTRA_TOOLCHAIN_FLAGS "-mfloat-abi=softfp") -endif () - -set(CMAKE_C_COMPILER ${CROSS}gcc) -set(CMAKE_CXX_COMPILER ${CROSS}g++) -set(AS_EXECUTABLE ${CROSS}as) -set(CMAKE_C_COMPILER_ARG1 - "-march=armv7-a -mfpu=neon ${DRACO_EXTRA_TOOLCHAIN_FLAGS}") -set(CMAKE_CXX_COMPILER_ARG1 - "-march=armv7-a -mfpu=neon ${DRACO_EXTRA_TOOLCHAIN_FLAGS}") -set(CMAKE_SYSTEM_PROCESSOR "armv7") - -endif () # DRACO_CMAKE_TOOLCHAINS_ARMV7_LINUX_GCC_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/armv7s-ios.cmake b/extern/draco/dracoenc/cmake/toolchains/armv7s-ios.cmake deleted file mode 100644 index 45097936bcb..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/armv7s-ios.cmake +++ /dev/null @@ -1,14 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_ARMV7S_IOS_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_ARMV7S_IOS_CMAKE_ 1) - -if (XCODE) - # TODO(tomfinegan): Handle arm builds in Xcode. - message(FATAL_ERROR "This toolchain does not support Xcode.") -endif () - -set(CMAKE_SYSTEM_PROCESSOR "armv7s") -set(CMAKE_OSX_ARCHITECTURES "armv7s") - -include("${CMAKE_CURRENT_LIST_DIR}/arm-ios-common.cmake") - -endif () # DRACO_CMAKE_TOOLCHAINS_ARMV7S_IOS_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/x86-android-ndk-libcpp.cmake b/extern/draco/dracoenc/cmake/toolchains/x86-android-ndk-libcpp.cmake deleted file mode 100644 index 7bb3717971f..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/x86-android-ndk-libcpp.cmake +++ /dev/null @@ -1,12 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_X86_ANDROID_NDK_LIBCPP_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_X86_ANDROID_NDK_LIBCPP_CMAKE_ 1) - -include("${CMAKE_CURRENT_LIST_DIR}/../util.cmake") - -set(CMAKE_SYSTEM_NAME Android) -set(CMAKE_ANDROID_ARCH_ABI x86) -require_variable(CMAKE_ANDROID_NDK) -set_variable_if_unset(CMAKE_SYSTEM_VERSION 18) -set_variable_if_unset(CMAKE_ANDROID_STL_TYPE c++_static) - -endif () # DRACO_CMAKE_TOOLCHAINS_X86_ANDROID_NDK_LIBCPP_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/toolchains/x86_64-android-ndk-libcpp.cmake b/extern/draco/dracoenc/cmake/toolchains/x86_64-android-ndk-libcpp.cmake deleted file mode 100644 index 3b86b9d6682..00000000000 --- a/extern/draco/dracoenc/cmake/toolchains/x86_64-android-ndk-libcpp.cmake +++ /dev/null @@ -1,12 +0,0 @@ -if (NOT DRACO_CMAKE_TOOLCHAINS_X86_64_ANDROID_NDK_LIBCPP_CMAKE_) -set(DRACO_CMAKE_TOOLCHAINS_X86_64_ANDROID_NDK_LIBCPP_CMAKE_ 1) - -include("${CMAKE_CURRENT_LIST_DIR}/../util.cmake") - -set(CMAKE_SYSTEM_NAME Android) -set(CMAKE_ANDROID_ARCH_ABI x86_64) -require_variable(CMAKE_ANDROID_NDK) -set_variable_if_unset(CMAKE_SYSTEM_VERSION 21) -set_variable_if_unset(CMAKE_ANDROID_STL_TYPE c++_static) - -endif () # DRACO_CMAKE_TOOLCHAINS_X86_64_ANDROID_NDK_LIBCPP_CMAKE_ diff --git a/extern/draco/dracoenc/cmake/util.cmake b/extern/draco/dracoenc/cmake/util.cmake deleted file mode 100644 index d9254c03c03..00000000000 --- a/extern/draco/dracoenc/cmake/util.cmake +++ /dev/null @@ -1,73 +0,0 @@ -if (NOT DRACO_CMAKE_UTIL_CMAKE_) -set(DRACO_CMAKE_UTIL_CMAKE_ 1) - -# Creates dummy source file in $draco_build_dir named $basename.$extension and -# returns the full path to the dummy source file via the $out_file_path -# parameter. -function (create_dummy_source_file basename extension out_file_path) - set(dummy_source_file "${draco_build_dir}/${basename}.${extension}") - file(WRITE "${dummy_source_file}" - "// Generated file. DO NOT EDIT!\n" - "// ${target_name} needs a ${extension} file to force link language, \n" - "// or to silence a harmless CMake warning: Ignore me.\n" - "void ${target_name}_dummy_function(void) {}\n") - set(${out_file_path} ${dummy_source_file} PARENT_SCOPE) -endfunction () - -# Convenience function for adding a dummy source file to $target_name using -# $extension as the file extension. Wraps create_dummy_source_file(). -function (add_dummy_source_file_to_target target_name extension) - create_dummy_source_file("${target_name}" "${extension}" "dummy_source_file") - target_sources(${target_name} PRIVATE ${dummy_source_file}) -endfunction () - -# Extracts the version number from $version_file and returns it to the user via -# $version_string_out_var. This is achieved by finding the first instance of -# the kDracoVersion variable and then removing everything but the string literal -# assigned to the variable. Quotes and semicolon are stripped from the returned -# string. -function (extract_version_string version_file version_string_out_var) - file(STRINGS "${version_file}" draco_version REGEX "kDracoVersion") - list(GET draco_version 0 draco_version) - string(REPLACE "static const char kDracoVersion[] = " "" draco_version - "${draco_version}") - string(REPLACE ";" "" draco_version "${draco_version}") - string(REPLACE "\"" "" draco_version "${draco_version}") - set("${version_string_out_var}" "${draco_version}" PARENT_SCOPE) -endfunction () - -# Sets CMake compiler launcher to $launcher_name when $launcher_name is found in -# $PATH. Warns user about ignoring build flag $launcher_flag when $launcher_name -# is not found in $PATH. -function (set_compiler_launcher launcher_flag launcher_name) - find_program(launcher_path "${launcher_name}") - if (launcher_path) - set(CMAKE_C_COMPILER_LAUNCHER "${launcher_path}" PARENT_SCOPE) - set(CMAKE_CXX_COMPILER_LAUNCHER "${launcher_path}" PARENT_SCOPE) - message("--- Using ${launcher_name} as compiler launcher.") - else () - message(WARNING - "--- Cannot find ${launcher_name}, ${launcher_flag} ignored.") - endif () -endfunction () - -# Terminates CMake execution when $var_name is unset in the environment. Sets -# CMake variable to the value of the environment variable when the variable is -# present in the environment. -macro(require_variable var_name) - if ("$ENV{${var_name}}" STREQUAL "") - message(FATAL_ERROR "${var_name} must be set in environment.") - endif () - set_variable_if_unset(${var_name} "") -endmacro () - -# Sets $var_name to $default_value if not already set in the environment. -macro (set_variable_if_unset var_name default_value) - if (NOT "$ENV{${var_name}}" STREQUAL "") - set(${var_name} $ENV{${var_name}}) - else () - set(${var_name} ${default_value}) - endif () -endmacro () - -endif() # DRACO_CMAKE_UTIL_CMAKE_ diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_encoding_test.cc b/extern/draco/dracoenc/src/draco/animation/keyframe_animation_encoding_test.cc deleted file mode 100644 index 4a6491f9d0d..00000000000 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_encoding_test.cc +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/animation/keyframe_animation.h" -#include "draco/animation/keyframe_animation_decoder.h" -#include "draco/animation/keyframe_animation_encoder.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" - -namespace draco { - -class KeyframeAnimationEncodingTest : public ::testing::Test { - protected: - KeyframeAnimationEncodingTest() {} - - bool CreateAndAddTimestamps(int32_t num_frames) { - timestamps_.resize(num_frames); - for (int i = 0; i < timestamps_.size(); ++i) - timestamps_[i] = static_cast<draco::KeyframeAnimation::TimestampType>(i); - return keyframe_animation_.SetTimestamps(timestamps_); - } - - int32_t CreateAndAddAnimationData(int32_t num_frames, - uint32_t num_components) { - // Create and add animation data with. - animation_data_.resize(num_frames * num_components); - for (int i = 0; i < animation_data_.size(); ++i) - animation_data_[i] = static_cast<float>(i); - return keyframe_animation_.AddKeyframes(draco::DT_FLOAT32, num_components, - animation_data_); - } - - template <int num_components_t> - void CompareAnimationData(const KeyframeAnimation &animation0, - const KeyframeAnimation &animation1, - bool quantized) { - ASSERT_EQ(animation0.num_frames(), animation1.num_frames()); - ASSERT_EQ(animation0.num_animations(), animation1.num_animations()); - - if (quantized) { - // TODO(hemmer) : Add test for stable quantization. - // Quantization will result in slightly different values. - // Skip comparing values. - return; - } - - // Compare time stamp. - const auto timestamp_att0 = animation0.timestamps(); - const auto timestamp_att1 = animation0.timestamps(); - for (int i = 0; i < animation0.num_frames(); ++i) { - std::array<float, 1> att_value0; - std::array<float, 1> att_value1; - ASSERT_TRUE((timestamp_att0->GetValue<float, 1>( - draco::AttributeValueIndex(i), &att_value0))); - ASSERT_TRUE((timestamp_att1->GetValue<float, 1>( - draco::AttributeValueIndex(i), &att_value1))); - ASSERT_FLOAT_EQ(att_value0[0], att_value1[0]); - } - - for (int animation_id = 1; animation_id < animation0.num_animations(); - ++animation_id) { - // Compare keyframe data. - const auto keyframe_att0 = animation0.keyframes(animation_id); - const auto keyframe_att1 = animation1.keyframes(animation_id); - ASSERT_EQ(keyframe_att0->num_components(), - keyframe_att1->num_components()); - for (int i = 0; i < animation0.num_frames(); ++i) { - std::array<float, num_components_t> att_value0; - std::array<float, num_components_t> att_value1; - ASSERT_TRUE((keyframe_att0->GetValue<float, num_components_t>( - draco::AttributeValueIndex(i), &att_value0))); - ASSERT_TRUE((keyframe_att1->GetValue<float, num_components_t>( - draco::AttributeValueIndex(i), &att_value1))); - for (int j = 0; j < att_value0.size(); ++j) { - ASSERT_FLOAT_EQ(att_value0[j], att_value1[j]); - } - } - } - } - - template <int num_components_t> - void TestKeyframeAnimationEncoding() { - TestKeyframeAnimationEncoding<num_components_t>(false); - } - - template <int num_components_t> - void TestKeyframeAnimationEncoding(bool quantized) { - // Encode animation class. - draco::EncoderBuffer buffer; - draco::KeyframeAnimationEncoder encoder; - EncoderOptions options = EncoderOptions::CreateDefaultOptions(); - if (quantized) { - // Set quantization for timestamps. - options.SetAttributeInt(0, "quantization_bits", 20); - // Set quantization for keyframes. - for (int i = 1; i <= keyframe_animation_.num_animations(); ++i) { - options.SetAttributeInt(i, "quantization_bits", 20); - } - } - - ASSERT_TRUE( - encoder.EncodeKeyframeAnimation(keyframe_animation_, options, &buffer) - .ok()); - - draco::DecoderBuffer dec_decoder; - draco::KeyframeAnimationDecoder decoder; - DecoderBuffer dec_buffer; - dec_buffer.Init(buffer.data(), buffer.size()); - - // Decode animation class. - std::unique_ptr<KeyframeAnimation> decoded_animation( - new KeyframeAnimation()); - DecoderOptions dec_options; - ASSERT_TRUE( - decoder.Decode(dec_options, &dec_buffer, decoded_animation.get()).ok()); - - // Verify if animation before and after compression is identical. - CompareAnimationData<num_components_t>(keyframe_animation_, - *decoded_animation, quantized); - } - - draco::KeyframeAnimation keyframe_animation_; - std::vector<draco::KeyframeAnimation::TimestampType> timestamps_; - std::vector<float> animation_data_; -}; - -TEST_F(KeyframeAnimationEncodingTest, OneComponent) { - const int num_frames = 1; - ASSERT_TRUE(CreateAndAddTimestamps(num_frames)); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, 1), 1); - TestKeyframeAnimationEncoding<1>(); -} - -TEST_F(KeyframeAnimationEncodingTest, ManyComponents) { - const int num_frames = 100; - ASSERT_TRUE(CreateAndAddTimestamps(num_frames)); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, 100), 1); - TestKeyframeAnimationEncoding<100>(); -} - -TEST_F(KeyframeAnimationEncodingTest, ManyComponentsWithQuantization) { - const int num_frames = 100; - ASSERT_TRUE(CreateAndAddTimestamps(num_frames)); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, 4), 1); - // Test compression with quantization. - TestKeyframeAnimationEncoding<4>(true); -} - -TEST_F(KeyframeAnimationEncodingTest, MultipleAnimations) { - const int num_frames = 5; - ASSERT_TRUE(CreateAndAddTimestamps(num_frames)); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, 3), 1); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, 3), 2); - TestKeyframeAnimationEncoding<3>(); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_test.cc b/extern/draco/dracoenc/src/draco/animation/keyframe_animation_test.cc deleted file mode 100644 index bc92b25ffc4..00000000000 --- a/extern/draco/dracoenc/src/draco/animation/keyframe_animation_test.cc +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/animation/keyframe_animation.h" - -#include "draco/core/draco_test_base.h" - -namespace { - -class KeyframeAnimationTest : public ::testing::Test { - protected: - KeyframeAnimationTest() {} - - bool CreateAndAddTimestamps(int32_t num_frames) { - timestamps_.resize(num_frames); - for (int i = 0; i < timestamps_.size(); ++i) - timestamps_[i] = static_cast<draco::KeyframeAnimation::TimestampType>(i); - return keyframe_animation_.SetTimestamps(timestamps_); - } - - int32_t CreateAndAddAnimationData(int32_t num_frames, - uint32_t num_components) { - // Create and add animation data with. - animation_data_.resize(num_frames * num_components); - for (int i = 0; i < animation_data_.size(); ++i) - animation_data_[i] = static_cast<float>(i); - return keyframe_animation_.AddKeyframes(draco::DT_FLOAT32, num_components, - animation_data_); - } - - template <int num_components_t> - void CompareAnimationData() { - // Compare time stamp. - const auto timestamp_att = keyframe_animation_.timestamps(); - for (int i = 0; i < timestamps_.size(); ++i) { - std::array<float, 1> att_value; - ASSERT_TRUE((timestamp_att->GetValue<float, 1>( - draco::AttributeValueIndex(i), &att_value))); - ASSERT_FLOAT_EQ(att_value[0], i); - } - - // Compare keyframe data. - const auto keyframe_att = keyframe_animation_.keyframes(1); - for (int i = 0; i < animation_data_.size() / num_components_t; ++i) { - std::array<float, num_components_t> att_value; - ASSERT_TRUE((keyframe_att->GetValue<float, num_components_t>( - draco::AttributeValueIndex(i), &att_value))); - for (int j = 0; j < num_components_t; ++j) { - ASSERT_FLOAT_EQ(att_value[j], i * num_components_t + j); - } - } - } - - template <int num_components_t> - void TestKeyframeAnimation(int32_t num_frames) { - ASSERT_TRUE(CreateAndAddTimestamps(num_frames)); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, num_components_t), 1); - CompareAnimationData<num_components_t>(); - } - - draco::KeyframeAnimation keyframe_animation_; - std::vector<draco::KeyframeAnimation::TimestampType> timestamps_; - std::vector<float> animation_data_; -}; - -// Test animation with 1 component and 10 frames. -TEST_F(KeyframeAnimationTest, OneComponent) { TestKeyframeAnimation<1>(10); } - -// Test animation with 4 component and 10 frames. -TEST_F(KeyframeAnimationTest, FourComponent) { TestKeyframeAnimation<4>(10); } - -// Test adding animation data before timestamp. -TEST_F(KeyframeAnimationTest, AddingAnimationFirst) { - ASSERT_EQ(CreateAndAddAnimationData(5, 1), 1); - ASSERT_TRUE(CreateAndAddTimestamps(5)); -} - -// Test adding timestamp more than once. -TEST_F(KeyframeAnimationTest, ErrorAddingTimestampsTwice) { - ASSERT_TRUE(CreateAndAddTimestamps(5)); - ASSERT_FALSE(CreateAndAddTimestamps(5)); -} -// Test animation with multiple animation data. -TEST_F(KeyframeAnimationTest, MultipleAnimationData) { - const int num_frames = 5; - ASSERT_TRUE(CreateAndAddTimestamps(num_frames)); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, 1), 1); - ASSERT_EQ(CreateAndAddAnimationData(num_frames, 2), 2); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/attributes/point_attribute_test.cc b/extern/draco/dracoenc/src/draco/attributes/point_attribute_test.cc deleted file mode 100644 index 183003abea4..00000000000 --- a/extern/draco/dracoenc/src/draco/attributes/point_attribute_test.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/attributes/point_attribute.h" - -#include "draco/core/draco_test_base.h" - -namespace { - -class PointAttributeTest : public ::testing::Test { - protected: - PointAttributeTest() {} -}; - -TEST_F(PointAttributeTest, TestCopy) { - // This test verifies that PointAttribute can copy data from another point - // attribute. - draco::GeometryAttribute pos_att; - pos_att.Init(draco::GeometryAttribute::POSITION, nullptr, 1, draco::DT_INT32, - false, 4, 0); - draco::PointAttribute pa(pos_att); - pa.SetIdentityMapping(); - pa.Reset(10); - for (int32_t i = 0; i < 10; ++i) { - pa.SetAttributeValue(draco::AttributeValueIndex(i), &i); - } - - draco::PointAttribute other_pa; - other_pa.CopyFrom(pa); - - draco::PointAttributeHasher hasher; - ASSERT_EQ(hasher(pa), hasher(other_pa)); - - // The hash function does not actually compute the hash from attribute values, - // so ensure the data got copied correctly as well. - for (int32_t i = 0; i < 10; ++i) { - int32_t data; - other_pa.GetValue(draco::AttributeValueIndex(i), &data); - ASSERT_EQ(data, i); - } -} - -TEST_F(PointAttributeTest, TestGetValueFloat) { - draco::GeometryAttribute pos_att; - pos_att.Init(draco::GeometryAttribute::POSITION, nullptr, 3, - draco::DT_FLOAT32, false, 4, 0); - draco::PointAttribute pa(pos_att); - pa.SetIdentityMapping(); - pa.Reset(5); - float points[3]; - for (int32_t i = 0; i < 5; ++i) { - points[0] = i * 3.0; - points[1] = (i * 3.0) + 1.0; - points[2] = (i * 3.0) + 2.0; - pa.SetAttributeValue(draco::AttributeValueIndex(i), &points); - } - - for (int32_t i = 0; i < 5; ++i) { - pa.GetValue(draco::AttributeValueIndex(i), &points); - ASSERT_FLOAT_EQ(points[0], i * 3.0); - ASSERT_FLOAT_EQ(points[1], (i * 3.0) + 1.0); - ASSERT_FLOAT_EQ(points[2], (i * 3.0) + 2.0); - } -} - -TEST_F(PointAttributeTest, TestGetArray) { - draco::GeometryAttribute pos_att; - pos_att.Init(draco::GeometryAttribute::POSITION, nullptr, 3, - draco::DT_FLOAT32, false, 4, 0); - draco::PointAttribute pa(pos_att); - pa.SetIdentityMapping(); - pa.Reset(5); - float points[3]; - for (int32_t i = 0; i < 5; ++i) { - points[0] = i * 3.0; - points[1] = (i * 3.0) + 1.0; - points[2] = (i * 3.0) + 2.0; - pa.SetAttributeValue(draco::AttributeValueIndex(i), &points); - } - - for (int32_t i = 0; i < 5; ++i) { - std::array<float, 3> att_value; - att_value = pa.GetValue<float, 3>(draco::AttributeValueIndex(i)); - ASSERT_FLOAT_EQ(att_value[0], i * 3.0); - ASSERT_FLOAT_EQ(att_value[1], (i * 3.0) + 1.0); - ASSERT_FLOAT_EQ(att_value[2], (i * 3.0) + 2.0); - } - for (int32_t i = 0; i < 5; ++i) { - std::array<float, 3> att_value; - EXPECT_TRUE( - (pa.GetValue<float, 3>(draco::AttributeValueIndex(i), &att_value))); - ASSERT_FLOAT_EQ(att_value[0], i * 3.0); - ASSERT_FLOAT_EQ(att_value[1], (i * 3.0) + 1.0); - ASSERT_FLOAT_EQ(att_value[2], (i * 3.0) + 2.0); - } -} - -TEST_F(PointAttributeTest, TestArrayReadError) { - draco::GeometryAttribute pos_att; - pos_att.Init(draco::GeometryAttribute::POSITION, nullptr, 3, - draco::DT_FLOAT32, false, 4, 0); - draco::PointAttribute pa(pos_att); - pa.SetIdentityMapping(); - pa.Reset(5); - float points[3]; - for (int32_t i = 0; i < 5; ++i) { - points[0] = i * 3.0; - points[1] = (i * 3.0) + 1.0; - points[2] = (i * 3.0) + 2.0; - pa.SetAttributeValue(draco::AttributeValueIndex(i), &points); - } - - std::array<float, 3> att_value; - EXPECT_FALSE( - (pa.GetValue<float, 3>(draco::AttributeValueIndex(5), &att_value))); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector_test.cc b/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector_test.cc deleted file mode 100644 index bff10392c3d..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector_test.cc +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2018 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/attributes/point_d_vector.h" -#include "draco/compression/point_cloud/algorithms/point_cloud_types.h" -#include "draco/core/draco_test_base.h" - -namespace draco { - -class PointDVectorTest : public ::testing::Test { - protected: - template <typename PT> - void TestIntegrity() {} - template <typename PT> - void TestSize() { - for (uint32_t n_items = 0; n_items <= 10; ++n_items) { - for (uint32_t dimensionality = 1; dimensionality <= 10; - ++dimensionality) { - draco::PointDVector<PT> var(n_items, dimensionality); - ASSERT_EQ(n_items, var.size()); - ASSERT_EQ(n_items * dimensionality, var.GetBufferSize()); - } - } - } - template <typename PT> - void TestContentsContiguous() { - for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) { - for (uint32_t dimensionality = 1; dimensionality < 10; - dimensionality += 2) { - for (uint32_t att_dimensionality = 1; - att_dimensionality <= dimensionality; att_dimensionality += 2) { - for (uint32_t offset_dimensionality = 0; - offset_dimensionality < dimensionality - att_dimensionality; - ++offset_dimensionality) { - PointDVector<PT> var(n_items, dimensionality); - - std::vector<PT> att(n_items * att_dimensionality); - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - att[val * att_dimensionality + att_dim] = val; - } - } - const PT *const attribute_data = att.data(); - - var.CopyAttribute(att_dimensionality, offset_dimensionality, - attribute_data); - - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - ASSERT_EQ(var[val][offset_dimensionality + att_dim], val); - } - } - } - } - } - } - } - template <typename PT> - void TestContentsDiscrete() { - for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) { - for (uint32_t dimensionality = 1; dimensionality < 10; - dimensionality += 2) { - for (uint32_t att_dimensionality = 1; - att_dimensionality <= dimensionality; att_dimensionality += 2) { - for (uint32_t offset_dimensionality = 0; - offset_dimensionality < dimensionality - att_dimensionality; - ++offset_dimensionality) { - PointDVector<PT> var(n_items, dimensionality); - - std::vector<PT> att(n_items * att_dimensionality); - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - att[val * att_dimensionality + att_dim] = val; - } - } - const PT *const attribute_data = att.data(); - - for (PT item = 0; item < n_items; item += 1) { - var.CopyAttribute(att_dimensionality, offset_dimensionality, item, - attribute_data + item * att_dimensionality); - } - - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - ASSERT_EQ(var[val][offset_dimensionality + att_dim], val); - } - } - } - } - } - } - } - - template <typename PT> - void TestContentsCopy() { - for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) { - for (uint32_t dimensionality = 1; dimensionality < 10; - dimensionality += 2) { - for (uint32_t att_dimensionality = 1; - att_dimensionality <= dimensionality; att_dimensionality += 2) { - for (uint32_t offset_dimensionality = 0; - offset_dimensionality < dimensionality - att_dimensionality; - ++offset_dimensionality) { - PointDVector<PT> var(n_items, dimensionality); - PointDVector<PT> dest(n_items, dimensionality); - - std::vector<PT> att(n_items * att_dimensionality); - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - att[val * att_dimensionality + att_dim] = val; - } - } - const PT *const attribute_data = att.data(); - - var.CopyAttribute(att_dimensionality, offset_dimensionality, - attribute_data); - - for (PT item = 0; item < n_items; item += 1) { - dest.CopyItem(var, item, item); - } - - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - ASSERT_EQ(var[val][offset_dimensionality + att_dim], val); - ASSERT_EQ(dest[val][offset_dimensionality + att_dim], val); - } - } - } - } - } - } - } - template <typename PT> - void TestIterator() { - for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) { - for (uint32_t dimensionality = 1; dimensionality < 10; - dimensionality += 2) { - for (uint32_t att_dimensionality = 1; - att_dimensionality <= dimensionality; att_dimensionality += 2) { - for (uint32_t offset_dimensionality = 0; - offset_dimensionality < dimensionality - att_dimensionality; - ++offset_dimensionality) { - PointDVector<PT> var(n_items, dimensionality); - PointDVector<PT> dest(n_items, dimensionality); - - std::vector<PT> att(n_items * att_dimensionality); - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - att[val * att_dimensionality + att_dim] = val; - } - } - const PT *const attribute_data = att.data(); - - var.CopyAttribute(att_dimensionality, offset_dimensionality, - attribute_data); - - for (PT item = 0; item < n_items; item += 1) { - dest.CopyItem(var, item, item); - } - - auto V0 = var.begin(); - auto VE = var.end(); - auto D0 = dest.begin(); - auto DE = dest.end(); - - while (V0 != VE && D0 != DE) { - ASSERT_EQ(*D0, *V0); // compare PseudoPointD - // verify elemental values - for (auto index = 0; index < dimensionality; index += 1) { - ASSERT_EQ((*D0)[index], (*V0)[index]); - } - ++V0; - ++D0; - } - - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - ASSERT_EQ(var[val][offset_dimensionality + att_dim], val); - ASSERT_EQ(dest[val][offset_dimensionality + att_dim], val); - } - } - } - } - } - } - } - template <typename PT> - void TestPoint3Iterator() { - for (uint32_t n_items = 1; n_items <= 1000; n_items *= 10) { - const uint32_t dimensionality = 3; - // for (uint32_t dimensionality = 1; dimensionality < 10; - // dimensionality += 2) { - const uint32_t att_dimensionality = 3; - // for (uint32_t att_dimensionality = 1; - // att_dimensionality <= dimensionality; att_dimensionality += 2) { - for (uint32_t offset_dimensionality = 0; - offset_dimensionality < dimensionality - att_dimensionality; - ++offset_dimensionality) { - PointDVector<PT> var(n_items, dimensionality); - PointDVector<PT> dest(n_items, dimensionality); - - std::vector<PT> att(n_items * att_dimensionality); - std::vector<draco::Point3ui> att3(n_items); - for (PT val = 0; val < n_items; val += 1) { - att3[val][0] = val; - att3[val][1] = val; - att3[val][2] = val; - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - att[val * att_dimensionality + att_dim] = val; - } - } - const PT *const attribute_data = att.data(); - - var.CopyAttribute(att_dimensionality, offset_dimensionality, - attribute_data); - - for (PT item = 0; item < n_items; item += 1) { - dest.CopyItem(var, item, item); - } - - auto aV0 = att3.begin(); - auto aVE = att3.end(); - auto V0 = var.begin(); - auto VE = var.end(); - auto D0 = dest.begin(); - auto DE = dest.end(); - - while (aV0 != aVE && V0 != VE && D0 != DE) { - ASSERT_EQ(*D0, *V0); // compare PseudoPointD - // verify elemental values - for (auto index = 0; index < dimensionality; index += 1) { - ASSERT_EQ((*D0)[index], (*V0)[index]); - ASSERT_EQ((*D0)[index], (*aV0)[index]); - ASSERT_EQ((*aV0)[index], (*V0)[index]); - } - ++aV0; - ++V0; - ++D0; - } - - for (PT val = 0; val < n_items; val += 1) { - for (PT att_dim = 0; att_dim < att_dimensionality; att_dim += 1) { - ASSERT_EQ(var[val][offset_dimensionality + att_dim], val); - ASSERT_EQ(dest[val][offset_dimensionality + att_dim], val); - } - } - } - } - } - - void TestPseudoPointDSwap() { - draco::Point3ui val = {0, 1, 2}; - draco::Point3ui dest = {10, 11, 12}; - draco::PseudoPointD<uint32_t> val_src1(&val[0], 3); - draco::PseudoPointD<uint32_t> dest_src1(&dest[0], 3); - - ASSERT_EQ(val_src1[0], 0); - ASSERT_EQ(val_src1[1], 1); - ASSERT_EQ(val_src1[2], 2); - ASSERT_EQ(dest_src1[0], 10); - ASSERT_EQ(dest_src1[1], 11); - ASSERT_EQ(dest_src1[2], 12); - - ASSERT_NE(val_src1, dest_src1); - - swap(val_src1, dest_src1); - - ASSERT_EQ(dest_src1[0], 0); - ASSERT_EQ(dest_src1[1], 1); - ASSERT_EQ(dest_src1[2], 2); - ASSERT_EQ(val_src1[0], 10); - ASSERT_EQ(val_src1[1], 11); - ASSERT_EQ(val_src1[2], 12); - - ASSERT_NE(val_src1, dest_src1); - } - void TestPseudoPointDEquality() { - draco::Point3ui val = {0, 1, 2}; - draco::Point3ui dest = {0, 1, 2}; - draco::PseudoPointD<uint32_t> val_src1(&val[0], 3); - draco::PseudoPointD<uint32_t> val_src2(&val[0], 3); - draco::PseudoPointD<uint32_t> dest_src1(&dest[0], 3); - draco::PseudoPointD<uint32_t> dest_src2(&dest[0], 3); - - ASSERT_EQ(val_src1, val_src1); - ASSERT_EQ(val_src1, val_src2); - ASSERT_EQ(dest_src1, val_src1); - ASSERT_EQ(dest_src1, val_src2); - ASSERT_EQ(val_src2, val_src1); - ASSERT_EQ(val_src2, val_src2); - ASSERT_EQ(dest_src2, val_src1); - ASSERT_EQ(dest_src2, val_src2); - - for (auto i = 0; i < 3; i++) { - ASSERT_EQ(val_src1[i], val_src1[i]); - ASSERT_EQ(val_src1[i], val_src2[i]); - ASSERT_EQ(dest_src1[i], val_src1[i]); - ASSERT_EQ(dest_src1[i], val_src2[i]); - ASSERT_EQ(val_src2[i], val_src1[i]); - ASSERT_EQ(val_src2[i], val_src2[i]); - ASSERT_EQ(dest_src2[i], val_src1[i]); - ASSERT_EQ(dest_src2[i], val_src2[i]); - } - } - void TestPseudoPointDInequality() { - draco::Point3ui val = {0, 1, 2}; - draco::Point3ui dest = {1, 2, 3}; - draco::PseudoPointD<uint32_t> val_src1(&val[0], 3); - draco::PseudoPointD<uint32_t> val_src2(&val[0], 3); - draco::PseudoPointD<uint32_t> dest_src1(&dest[0], 3); - draco::PseudoPointD<uint32_t> dest_src2(&dest[0], 3); - - ASSERT_EQ(val_src1, val_src1); - ASSERT_EQ(val_src1, val_src2); - ASSERT_NE(dest_src1, val_src1); - ASSERT_NE(dest_src1, val_src2); - ASSERT_EQ(val_src2, val_src1); - ASSERT_EQ(val_src2, val_src2); - ASSERT_NE(dest_src2, val_src1); - ASSERT_NE(dest_src2, val_src2); - - for (auto i = 0; i < 3; i++) { - ASSERT_EQ(val_src1[i], val_src1[i]); - ASSERT_EQ(val_src1[i], val_src2[i]); - ASSERT_NE(dest_src1[i], val_src1[i]); - ASSERT_NE(dest_src1[i], val_src2[i]); - ASSERT_EQ(val_src2[i], val_src1[i]); - ASSERT_EQ(val_src2[i], val_src2[i]); - ASSERT_NE(dest_src2[i], val_src1[i]); - ASSERT_NE(dest_src2[i], val_src2[i]); - } - } -}; - -TEST_F(PointDVectorTest, VectorTest) { - TestSize<uint32_t>(); - TestContentsDiscrete<uint32_t>(); - TestContentsContiguous<uint32_t>(); - TestContentsCopy<uint32_t>(); - TestIterator<uint32_t>(); - TestPoint3Iterator<uint32_t>(); -} -TEST_F(PointDVectorTest, PseudoPointDTest) { - TestPseudoPointDSwap(); - TestPseudoPointDEquality(); - TestPseudoPointDInequality(); -} -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_test.cc b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_test.cc deleted file mode 100644 index 8c8932f77c3..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_transform_test.cc +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_encoding_transform.h" -#include "draco/core/draco_test_base.h" - -namespace { - -class PredictionSchemeNormalOctahedronCanonicalizedTransformTest - : public ::testing::Test { - protected: - typedef draco::PredictionSchemeNormalOctahedronCanonicalizedEncodingTransform< - int32_t> - Transform; - typedef Transform::Point2 Point2; - - void TestComputeCorrection(const Transform &transform, const int32_t &ox, - const int32_t &oy, const int32_t &px, - const int32_t &py, const int32_t &cx, - const int32_t &cy) { - const int32_t o[2] = {ox + 7, oy + 7}; - const int32_t p[2] = {px + 7, py + 7}; - int32_t corr[2] = {500, 500}; - transform.ComputeCorrection(o, p, corr); - ASSERT_EQ(corr[0], (cx + 15) % 15); - ASSERT_EQ(corr[1], (cy + 15) % 15); - } - - void TestGetRotationCount(const Transform &transform, const Point2 &pred, - const int32_t &rot_dir) { - const int32_t rotation_count = transform.GetRotationCount(pred); - ASSERT_EQ(rot_dir, rotation_count); - } - - void TestRotateRepresentation(const Transform &transform, const Point2 &org, - const Point2 &pred, const Point2 &rot_org, - const Point2 &rot_pred) { - const int32_t rotation_count = transform.GetRotationCount(pred); - const Point2 res_org = transform.RotatePoint(org, rotation_count); - const Point2 res_pred = transform.RotatePoint(pred, rotation_count); - ASSERT_EQ(rot_org[0], res_org[0]); - ASSERT_EQ(rot_org[1], res_org[1]); - ASSERT_EQ(rot_pred[0], res_pred[0]); - ASSERT_EQ(rot_pred[1], res_pred[1]); - } -}; - -TEST_F(PredictionSchemeNormalOctahedronCanonicalizedTransformTest, Init) { - const Transform transform(15); - ASSERT_TRUE(transform.AreCorrectionsPositive()); -} - -TEST_F(PredictionSchemeNormalOctahedronCanonicalizedTransformTest, - IsInBottomLeft) { - const Transform transform(15); - ASSERT_TRUE(transform.IsInBottomLeft(Point2(0, 0))); - ASSERT_TRUE(transform.IsInBottomLeft(Point2(-1, -1))); - ASSERT_TRUE(transform.IsInBottomLeft(Point2(-7, -7))); - - ASSERT_FALSE(transform.IsInBottomLeft(Point2(1, 1))); - ASSERT_FALSE(transform.IsInBottomLeft(Point2(7, 7))); - ASSERT_FALSE(transform.IsInBottomLeft(Point2(-1, 1))); - ASSERT_FALSE(transform.IsInBottomLeft(Point2(-7, 7))); - ASSERT_FALSE(transform.IsInBottomLeft(Point2(1, -1))); - ASSERT_FALSE(transform.IsInBottomLeft(Point2(7, -7))); -} - -TEST_F(PredictionSchemeNormalOctahedronCanonicalizedTransformTest, - GetRotationCount) { - const Transform transform(15); - TestGetRotationCount(transform, Point2(1, 2), 2); // top right - TestGetRotationCount(transform, Point2(-1, 2), 3); // top left - TestGetRotationCount(transform, Point2(1, -2), 1); // bottom right - TestGetRotationCount(transform, Point2(-1, -2), 0); // bottom left - TestGetRotationCount(transform, Point2(0, 2), 3); // top left - TestGetRotationCount(transform, Point2(0, -2), 1); // bottom right - TestGetRotationCount(transform, Point2(2, 0), 2); // top right - TestGetRotationCount(transform, Point2(-2, 0), 0); // bottom left - TestGetRotationCount(transform, Point2(0, 0), 0); // bottom left -} - -TEST_F(PredictionSchemeNormalOctahedronCanonicalizedTransformTest, - RotateRepresentation) { - const Transform transform(15); - // p top left; shift clockwise by 3 - TestRotateRepresentation(transform, Point2(1, 2), Point2(-3, 1), - Point2(-2, 1), Point2(-1, -3)); // q top right - TestRotateRepresentation(transform, Point2(-1, -2), Point2(-3, 1), - Point2(2, -1), Point2(-1, -3)); // q bottom left - TestRotateRepresentation(transform, Point2(1, -2), Point2(-3, 1), - Point2(2, 1), Point2(-1, -3)); // q bottom right - TestRotateRepresentation(transform, Point2(-1, 2), Point2(-3, 1), - Point2(-2, -1), Point2(-1, -3)); // q top left - // p top right; shift clockwise by 2 (flip) - TestRotateRepresentation(transform, Point2(1, 1), Point2(1, 3), - Point2(-1, -1), Point2(-1, -3)); // q top right - TestRotateRepresentation(transform, Point2(-1, -2), Point2(1, 3), - Point2(1, 2), Point2(-1, -3)); // q bottom left - TestRotateRepresentation(transform, Point2(-1, 2), Point2(1, 3), - Point2(1, -2), Point2(-1, -3)); // q top left - TestRotateRepresentation(transform, Point2(1, -2), Point2(1, 3), - Point2(-1, 2), Point2(-1, -3)); // q bottom right - // p bottom right; shift clockwise by 1 - TestRotateRepresentation(transform, Point2(1, 2), Point2(3, -1), - Point2(2, -1), Point2(-1, -3)); // q top right - TestRotateRepresentation(transform, Point2(1, -2), Point2(3, -1), - Point2(-2, -1), Point2(-1, -3)); // q bottom right - TestRotateRepresentation(transform, Point2(-1, -2), Point2(3, -1), - Point2(-2, 1), Point2(-1, -3)); // q bottom left - TestRotateRepresentation(transform, Point2(-1, 2), Point2(3, -1), - Point2(2, 1), Point2(-1, -3)); // q top left - // p bottom left; no change - TestRotateRepresentation(transform, Point2(1, 2), Point2(-1, -3), - Point2(1, 2), Point2(-1, -3)); // q top right - TestRotateRepresentation(transform, Point2(-1, 2), Point2(-1, -3), - Point2(-1, 2), Point2(-1, -3)); // q top left - TestRotateRepresentation(transform, Point2(1, -2), Point2(-1, -3), - Point2(1, -2), Point2(-1, -3)); // q bottom right - TestRotateRepresentation(transform, Point2(-1, -2), Point2(-1, -3), - Point2(-1, -2), Point2(-1, -3)); // q bottom left -} - -TEST_F(PredictionSchemeNormalOctahedronCanonicalizedTransformTest, - ComputeCorrection) { - const Transform transform(15); - TestComputeCorrection(transform, 0, 0, 0, 0, 0, 0); - TestComputeCorrection(transform, 1, 1, 1, 1, 0, 0); - // inside diamond; p top right - TestComputeCorrection(transform, 3, 4, 1, 2, -2, -2); // q top right - TestComputeCorrection(transform, -3, 4, 1, 2, 4, -2); // q top left - TestComputeCorrection(transform, 3, -4, 1, 2, -2, 6); // q bottom right - TestComputeCorrection(transform, -3, -4, 1, 2, 4, 6); // q bottom left - // inside diamond; p top left - TestComputeCorrection(transform, 3, 4, -1, 2, -2, 4); // q top right - TestComputeCorrection(transform, -3, 4, -1, 2, -2, -2); // q top left - TestComputeCorrection(transform, 3, -4, -1, 2, 6, 4); // q bottom right - TestComputeCorrection(transform, -3, -4, -1, 2, 6, -2); // q bottom left - // inside diamond; p bottom right - TestComputeCorrection(transform, 3, 4, 1, -2, 6, -2); // q top right - TestComputeCorrection(transform, -3, 4, 1, -2, 6, 4); // q top left - TestComputeCorrection(transform, 3, -4, 1, -2, -2, -2); // q bottom right - TestComputeCorrection(transform, -3, -4, 1, -2, -2, 4); // q bottom left - // inside diamond; p bottom left - TestComputeCorrection(transform, 3, 4, -1, -2, 4, 6); // q top right - TestComputeCorrection(transform, -3, 4, -1, -2, -2, 6); // q top left - TestComputeCorrection(transform, 3, -4, -1, -2, 4, -2); // q bottom right - TestComputeCorrection(transform, -3, -4, -1, -2, -2, -2); // q bottom left - // outside diamond; p top right - TestComputeCorrection(transform, 1, 2, 5, 4, -2, -4); // q top right - TestComputeCorrection(transform, -1, 2, 5, 4, -7, -4); // q top left - TestComputeCorrection(transform, 1, -2, 5, 4, -2, -7); // q bottom right - TestComputeCorrection(transform, -1, -2, 5, 4, -7, -7); // q bottom left - // outside diamond; p top left - TestComputeCorrection(transform, 1, 2, -5, 4, -4, -7); // q top right - TestComputeCorrection(transform, -1, 2, -5, 4, -4, -2); // q top left - TestComputeCorrection(transform, 1, -2, -5, 4, -7, -7); // q bottom right - TestComputeCorrection(transform, -1, -2, -5, 4, -7, -2); // q bottom left - // outside diamond; p bottom right - TestComputeCorrection(transform, 1, 2, 5, -4, -7, -2); // q top right - TestComputeCorrection(transform, -1, 2, 5, -4, -7, -7); // q top left - TestComputeCorrection(transform, 1, -2, 5, -4, -4, -2); // q bottom right - TestComputeCorrection(transform, -1, -2, 5, -4, -4, -7); // q bottom left - // outside diamond; p bottom left - TestComputeCorrection(transform, 1, 2, -5, -4, -7, -7); // q top right - TestComputeCorrection(transform, -1, 2, -5, -4, -2, -7); // q top left - TestComputeCorrection(transform, 1, -2, -5, -4, -7, -4); // q bottom right - TestComputeCorrection(transform, -1, -2, -5, -4, -2, -4); // q bottom left - - TestComputeCorrection(transform, -1, -2, 7, 7, -5, -6); - TestComputeCorrection(transform, 0, 0, 7, 7, 7, 7); - TestComputeCorrection(transform, -1, -2, 0, -2, 0, 1); -} - -TEST_F(PredictionSchemeNormalOctahedronCanonicalizedTransformTest, Interface) { - const Transform transform(15); - ASSERT_EQ(transform.max_quantized_value(), 15); - ASSERT_EQ(transform.center_value(), 7); - ASSERT_EQ(transform.quantization_bits(), 4); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_test.cc b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_test.cc deleted file mode 100644 index 1001b19fa50..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_transform_test.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_encoding_transform.h" -#include "draco/core/draco_test_base.h" - -namespace { - -class PredictionSchemeNormalOctahedronTransformTest : public ::testing::Test { - protected: - typedef draco::PredictionSchemeNormalOctahedronEncodingTransform<int32_t> - Transform; - typedef Transform::Point2 Point2; - - void TestComputeCorrection(const Transform &transform, const int32_t &ox, - const int32_t &oy, const int32_t &px, - const int32_t &py, const int32_t &cx, - const int32_t &cy) { - const int32_t o[2] = {ox + 7, oy + 7}; - const int32_t p[2] = {px + 7, py + 7}; - int32_t corr[2] = {500, 500}; - transform.ComputeCorrection(o, p, corr); - ASSERT_EQ(corr[0], (cx + 15) % 15); - ASSERT_EQ(corr[1], (cy + 15) % 15); - } -}; - -TEST_F(PredictionSchemeNormalOctahedronTransformTest, Init) { - const Transform transform(15); - ASSERT_TRUE(transform.AreCorrectionsPositive()); -} - -TEST_F(PredictionSchemeNormalOctahedronTransformTest, ComputeCorrections) { - const Transform transform(15); - // checks inside diamond - TestComputeCorrection(transform, 0, 0, 0, 0, 0, 0); - TestComputeCorrection(transform, 1, 1, 1, 1, 0, 0); - TestComputeCorrection(transform, 3, 4, 1, 1, 2, 3); - TestComputeCorrection(transform, -1, -1, -1, -1, 0, 0); - TestComputeCorrection(transform, -3, -4, -1, -1, -2, -3); - // checks outside diamond - TestComputeCorrection(transform, 4, 4, 4, 4, 0, 0); - TestComputeCorrection(transform, 5, 6, 4, 4, -2, -1); - TestComputeCorrection(transform, 3, 2, 4, 4, 2, 1); - // checks on outer edges - TestComputeCorrection(transform, 7, 7, 4, 4, -3, -3); - TestComputeCorrection(transform, 6, 7, 4, 4, -3, -2); - TestComputeCorrection(transform, -6, 7, 4, 4, -3, -2); - TestComputeCorrection(transform, 7, 6, 4, 4, -2, -3); - TestComputeCorrection(transform, 7, -6, 4, 4, -2, -3); -} - -TEST_F(PredictionSchemeNormalOctahedronTransformTest, Interface) { - const Transform transform(15); - ASSERT_EQ(transform.max_quantized_value(), 15); - ASSERT_EQ(transform.center_value(), 7); - ASSERT_EQ(transform.quantization_bits(), 4); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_encoding_test.cc b/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_encoding_test.cc deleted file mode 100644 index d7b0cd25df6..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_integer_attribute_encoding_test.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include <numeric> - -#include "draco/compression/attributes/sequential_integer_attribute_decoder.h" -#include "draco/compression/attributes/sequential_integer_attribute_encoder.h" -#include "draco/compression/config/compression_shared.h" -#include "draco/core/draco_test_base.h" - -namespace draco { - -class SequentialIntegerAttributeEncodingTest : public ::testing::Test { - protected: -}; - -TEST_F(SequentialIntegerAttributeEncodingTest, DoesCompress) { - // This test verifies that IntegerEncoding encodes and decodes the given data. - const std::vector<int32_t> values{1, 8, 7, 5, 5, 5, 9, - 155, -6, -9, 9, 125, 1, 0}; - GeometryAttribute ga; - PointAttribute pa; - pa.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_INT32, false, 4, 0); - pa.Reset(values.size()); - pa.SetIdentityMapping(); - for (uint32_t i = 0; i < values.size(); ++i) { - pa.SetAttributeValue(AttributeValueIndex(i), &values[i]); - } - // List of point ids from 0 to point_ids.size() - 1. - std::vector<PointIndex> point_ids(values.size()); - std::iota(point_ids.begin(), point_ids.end(), 0); - - EncoderBuffer out_buf; - SequentialIntegerAttributeEncoder ie; - ASSERT_TRUE(ie.InitializeStandalone(&pa)); - ASSERT_TRUE(ie.TransformAttributeToPortableFormat(point_ids)); - ASSERT_TRUE(ie.EncodePortableAttribute(point_ids, &out_buf)); - ASSERT_TRUE(ie.EncodeDataNeededByPortableTransform(&out_buf)); - - DecoderBuffer in_buf; - in_buf.Init(out_buf.data(), out_buf.size()); - in_buf.set_bitstream_version(kDracoMeshBitstreamVersion); - SequentialIntegerAttributeDecoder id; - ASSERT_TRUE(id.InitializeStandalone(&pa)); - ASSERT_TRUE(id.DecodePortableAttribute(point_ids, &in_buf)); - ASSERT_TRUE(id.DecodeDataNeededByPortableTransform(point_ids, &in_buf)); - ASSERT_TRUE(id.TransformAttributeToOriginalFormat(point_ids)); - - for (uint32_t i = 0; i < values.size(); ++i) { - int32_t entry_val; - pa.GetValue(AttributeValueIndex(i), &entry_val); - ASSERT_EQ(entry_val, values[i]); - } -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_coding_test.cc b/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_coding_test.cc deleted file mode 100644 index 9509ad9f354..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/bit_coders/rans_coding_test.cc +++ /dev/null @@ -1,9 +0,0 @@ -#include "draco/compression/bit_coders/adaptive_rans_bit_decoder.h" -#include "draco/compression/bit_coders/adaptive_rans_bit_encoder.h" -#include "draco/compression/bit_coders/rans_bit_decoder.h" -#include "draco/compression/bit_coders/rans_bit_encoder.h" -#include "draco/core/draco_test_base.h" - -// Just including rans_coding.h and adaptive_rans_coding.h gets an asan error -// when compiling (blaze test :rans_coding_test --config=asan) -TEST(RansCodingTest, LinkerTest) {} diff --git a/extern/draco/dracoenc/src/draco/compression/config/decoder_options_test.cc b/extern/draco/dracoenc/src/draco/compression/config/decoder_options_test.cc deleted file mode 100644 index a5cd7f10640..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/config/decoder_options_test.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/config/decoder_options.h" - -#include "draco/core/draco_test_base.h" - -namespace { - -class DecoderOptionsTest : public ::testing::Test { - protected: - DecoderOptionsTest() {} -}; - -TEST_F(DecoderOptionsTest, TestOptions) { - // This test verifies that we can update global and attribute options of the - // DecoderOptions class instance. - draco::DecoderOptions options; - options.SetGlobalInt("test", 3); - ASSERT_EQ(options.GetGlobalInt("test", -1), 3); - - options.SetAttributeInt(draco::GeometryAttribute::POSITION, "test", 1); - options.SetAttributeInt(draco::GeometryAttribute::GENERIC, "test", 2); - ASSERT_EQ( - options.GetAttributeInt(draco::GeometryAttribute::TEX_COORD, "test", -1), - 3); - ASSERT_EQ( - options.GetAttributeInt(draco::GeometryAttribute::POSITION, "test", -1), - 1); - ASSERT_EQ( - options.GetAttributeInt(draco::GeometryAttribute::GENERIC, "test", -1), - 2); -} - -TEST_F(DecoderOptionsTest, TestAttributeOptionsAccessors) { - // This test verifies that we can query options stored in DecoderOptions - // class instance. - draco::DecoderOptions options; - options.SetGlobalInt("test", 1); - options.SetAttributeInt(draco::GeometryAttribute::POSITION, "test", 2); - options.SetAttributeInt(draco::GeometryAttribute::TEX_COORD, "test", 3); - - ASSERT_EQ( - options.GetAttributeInt(draco::GeometryAttribute::POSITION, "test", -1), - 2); - ASSERT_EQ( - options.GetAttributeInt(draco::GeometryAttribute::POSITION, "test2", -1), - -1); - ASSERT_EQ( - options.GetAttributeInt(draco::GeometryAttribute::TEX_COORD, "test", -1), - 3); - ASSERT_EQ( - options.GetAttributeInt(draco::GeometryAttribute::NORMAL, "test", -1), 1); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/compression/decode_test.cc b/extern/draco/dracoenc/src/draco/compression/decode_test.cc deleted file mode 100644 index c57542069dd..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/decode_test.cc +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/decode.h" - -#include <cinttypes> -#include <fstream> -#include <sstream> - -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" - -namespace { - -class DecodeTest : public ::testing::Test { - protected: - DecodeTest() {} -}; - -#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED -TEST_F(DecodeTest, TestSkipAttributeTransform) { - const std::string file_name = "test_nm_quant.0.9.0.drc"; - // Tests that decoders can successfully skip attribute transform. - std::ifstream input_file(draco::GetTestFileFullPath(file_name), - std::ios::binary); - ASSERT_TRUE(input_file); - - // Read the file stream into a buffer. - std::streampos file_size = 0; - input_file.seekg(0, std::ios::end); - file_size = input_file.tellg() - file_size; - input_file.seekg(0, std::ios::beg); - std::vector<char> data(file_size); - input_file.read(data.data(), file_size); - - ASSERT_FALSE(data.empty()); - - // Create a draco decoding buffer. Note that no data is copied in this step. - draco::DecoderBuffer buffer; - buffer.Init(data.data(), data.size()); - - draco::Decoder decoder; - // Make sure we skip dequantization for the position attribute. - decoder.SetSkipAttributeTransform(draco::GeometryAttribute::POSITION); - - // Decode the input data into a geometry. - std::unique_ptr<draco::PointCloud> pc = - decoder.DecodePointCloudFromBuffer(&buffer).value(); - ASSERT_NE(pc, nullptr); - - const draco::PointAttribute *const pos_att = - pc->GetNamedAttribute(draco::GeometryAttribute::POSITION); - ASSERT_NE(pos_att, nullptr); - - // Ensure the position attribute is of type int32_t and that it has a valid - // attribute transform. - ASSERT_EQ(pos_att->data_type(), draco::DT_INT32); - ASSERT_NE(pos_att->GetAttributeTransformData(), nullptr); - - // Normal attribute should be left transformed. - const draco::PointAttribute *const norm_att = - pc->GetNamedAttribute(draco::GeometryAttribute::NORMAL); - ASSERT_EQ(norm_att->data_type(), draco::DT_FLOAT32); - ASSERT_EQ(norm_att->GetAttributeTransformData(), nullptr); -} -#endif - -void TestSkipAttributeTransformOnPointCloudWithColor(const std::string &file) { - std::ifstream input_file(draco::GetTestFileFullPath(file), std::ios::binary); - ASSERT_TRUE(input_file); - - // Read the file stream into a buffer. - std::streampos file_size = 0; - input_file.seekg(0, std::ios::end); - file_size = input_file.tellg() - file_size; - input_file.seekg(0, std::ios::beg); - std::vector<char> data(file_size); - input_file.read(data.data(), file_size); - - ASSERT_FALSE(data.empty()); - - // Create a draco decoding buffer. Note that no data is copied in this step. - draco::DecoderBuffer buffer; - buffer.Init(data.data(), data.size()); - - draco::Decoder decoder; - // Make sure we skip dequantization for the position attribute. - decoder.SetSkipAttributeTransform(draco::GeometryAttribute::POSITION); - - // Decode the input data into a geometry. - std::unique_ptr<draco::PointCloud> pc = - decoder.DecodePointCloudFromBuffer(&buffer).value(); - ASSERT_NE(pc, nullptr); - - const draco::PointAttribute *const pos_att = - pc->GetNamedAttribute(draco::GeometryAttribute::POSITION); - ASSERT_NE(pos_att, nullptr); - - // Ensure the position attribute is of type int32_t or uint32_t and that it - // has a valid attribute transform. - ASSERT_TRUE(pos_att->data_type() == draco::DT_INT32 || - pos_att->data_type() == draco::DT_UINT32); - ASSERT_NE(pos_att->GetAttributeTransformData(), nullptr); - - const draco::PointAttribute *const clr_att = - pc->GetNamedAttribute(draco::GeometryAttribute::COLOR); - ASSERT_EQ(clr_att->data_type(), draco::DT_UINT8); - - // Ensure the color attribute was decoded correctly. Perform the decoding - // again without skipping the position dequantization and compare the - // attribute values. - - draco::DecoderBuffer buffer_2; - buffer_2.Init(data.data(), data.size()); - - draco::Decoder decoder_2; - - // Decode the input data into a geometry. - std::unique_ptr<draco::PointCloud> pc_2 = - decoder_2.DecodePointCloudFromBuffer(&buffer_2).value(); - ASSERT_NE(pc_2, nullptr); - - const draco::PointAttribute *const clr_att_2 = - pc_2->GetNamedAttribute(draco::GeometryAttribute::COLOR); - ASSERT_NE(clr_att_2, nullptr); - for (draco::PointIndex pi(0); pi < pc_2->num_points(); ++pi) { - // Colors should be exactly the same for both cases. - ASSERT_EQ(std::memcmp(clr_att->GetAddress(clr_att->mapped_index(pi)), - clr_att_2->GetAddress(clr_att_2->mapped_index(pi)), - clr_att->byte_stride()), - 0); - } -} - -TEST_F(DecodeTest, TestSkipAttributeTransformOnPointCloud) { - // Tests that decoders can successfully skip attribute transform on a point - // cloud with multiple attributes encoded with one attributes encoder. - TestSkipAttributeTransformOnPointCloudWithColor("pc_color.drc"); - TestSkipAttributeTransformOnPointCloudWithColor("pc_kd_color.drc"); -} - -TEST_F(DecodeTest, TestSkipAttributeTransformWithNoQuantization) { - // Tests that decoders can successfully skip attribute transform even though - // the input model was not quantized (it has no attribute transform). - const std::string file_name = "point_cloud_no_qp.drc"; - std::ifstream input_file(draco::GetTestFileFullPath(file_name), - std::ios::binary); - ASSERT_TRUE(input_file); - - // Read the file stream into a buffer. - std::streampos file_size = 0; - input_file.seekg(0, std::ios::end); - file_size = input_file.tellg() - file_size; - input_file.seekg(0, std::ios::beg); - std::vector<char> data(file_size); - input_file.read(data.data(), file_size); - - ASSERT_FALSE(data.empty()); - - // Create a draco decoding buffer. Note that no data is copied in this step. - draco::DecoderBuffer buffer; - buffer.Init(data.data(), data.size()); - - draco::Decoder decoder; - // Make sure we skip dequantization for the position attribute. - decoder.SetSkipAttributeTransform(draco::GeometryAttribute::POSITION); - - // Decode the input data into a geometry. - std::unique_ptr<draco::PointCloud> pc = - decoder.DecodePointCloudFromBuffer(&buffer).value(); - ASSERT_NE(pc, nullptr); - - const draco::PointAttribute *const pos_att = - pc->GetNamedAttribute(draco::GeometryAttribute::POSITION); - ASSERT_NE(pos_att, nullptr); - - // Ensure the position attribute is of type float32 since the attribute was - // not quantized. - ASSERT_EQ(pos_att->data_type(), draco::DT_FLOAT32); - - // Make sure there is no attribute transform available for the attribute. - ASSERT_EQ(pos_att->GetAttributeTransformData(), nullptr); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/compression/encode_test.cc b/extern/draco/dracoenc/src/draco/compression/encode_test.cc deleted file mode 100644 index 2eadb73b343..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/encode_test.cc +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#include <cinttypes> -#include <fstream> -#include <sstream> - -#include "draco/attributes/attribute_quantization_transform.h" -#include "draco/compression/decode.h" -#include "draco/compression/encode.h" -#include "draco/compression/expert_encode.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/core/vector_d.h" -#include "draco/io/obj_decoder.h" -#include "draco/mesh/triangle_soup_mesh_builder.h" -#include "draco/point_cloud/point_cloud_builder.h" - -namespace { - -class EncodeTest : public ::testing::Test { - protected: - EncodeTest() {} - std::unique_ptr<draco::Mesh> CreateTestMesh() const { - draco::TriangleSoupMeshBuilder mesh_builder; - - // Create a simple mesh with one face. - mesh_builder.Start(1); - - // Add one position attribute and two texture coordinate attributes. - const int32_t pos_att_id = mesh_builder.AddAttribute( - draco::GeometryAttribute::POSITION, 3, draco::DT_FLOAT32); - const int32_t tex_att_id_0 = mesh_builder.AddAttribute( - draco::GeometryAttribute::TEX_COORD, 2, draco::DT_FLOAT32); - const int32_t tex_att_id_1 = mesh_builder.AddAttribute( - draco::GeometryAttribute::TEX_COORD, 2, draco::DT_FLOAT32); - - // Initialize the attribute values. - mesh_builder.SetAttributeValuesForFace( - pos_att_id, draco::FaceIndex(0), draco::Vector3f(0.f, 0.f, 0.f).data(), - draco::Vector3f(1.f, 0.f, 0.f).data(), - draco::Vector3f(1.f, 1.f, 0.f).data()); - mesh_builder.SetAttributeValuesForFace( - tex_att_id_0, draco::FaceIndex(0), draco::Vector2f(0.f, 0.f).data(), - draco::Vector2f(1.f, 0.f).data(), draco::Vector2f(1.f, 1.f).data()); - mesh_builder.SetAttributeValuesForFace( - tex_att_id_1, draco::FaceIndex(0), draco::Vector2f(0.f, 0.f).data(), - draco::Vector2f(1.f, 0.f).data(), draco::Vector2f(1.f, 1.f).data()); - - return mesh_builder.Finalize(); - } - - std::unique_ptr<draco::PointCloud> CreateTestPointCloud() const { - draco::PointCloudBuilder pc_builder; - - constexpr int kNumPoints = 100; - constexpr int kNumGenAttCoords0 = 4; - constexpr int kNumGenAttCoords1 = 6; - pc_builder.Start(kNumPoints); - - // Add one position attribute and two generic attributes. - const int32_t pos_att_id = pc_builder.AddAttribute( - draco::GeometryAttribute::POSITION, 3, draco::DT_FLOAT32); - const int32_t gen_att_id_0 = pc_builder.AddAttribute( - draco::GeometryAttribute::GENERIC, kNumGenAttCoords0, draco::DT_UINT32); - const int32_t gen_att_id_1 = pc_builder.AddAttribute( - draco::GeometryAttribute::GENERIC, kNumGenAttCoords1, draco::DT_UINT8); - - std::vector<uint32_t> gen_att_data_0(kNumGenAttCoords0); - std::vector<uint32_t> gen_att_data_1(kNumGenAttCoords1); - - // Initialize the attribute values. - for (draco::PointIndex i(0); i < kNumPoints; ++i) { - const float pos_coord = static_cast<float>(i.value()); - pc_builder.SetAttributeValueForPoint( - pos_att_id, i, - draco::Vector3f(pos_coord, -pos_coord, pos_coord).data()); - - for (int j = 0; j < kNumGenAttCoords0; ++j) { - gen_att_data_0[j] = i.value(); - } - pc_builder.SetAttributeValueForPoint(gen_att_id_0, i, - gen_att_data_0.data()); - - for (int j = 0; j < kNumGenAttCoords1; ++j) { - gen_att_data_1[j] = -i.value(); - } - pc_builder.SetAttributeValueForPoint(gen_att_id_1, i, - gen_att_data_1.data()); - } - - return pc_builder.Finalize(false); - } - - int GetQuantizationBitsFromAttribute(const draco::PointAttribute *att) const { - if (att == nullptr) - return -1; - draco::AttributeQuantizationTransform transform; - if (!transform.InitFromAttribute(*att)) - return -1; - return transform.quantization_bits(); - } - - void VerifyNumQuantizationBits(const draco::EncoderBuffer &buffer, - int pos_quantization, - int tex_coord_0_quantization, - int tex_coord_1_quantization) const { - draco::Decoder decoder; - - // Skip the dequantization for the attributes which will allow us to get - // the number of quantization bits used during encoding. - decoder.SetSkipAttributeTransform(draco::GeometryAttribute::POSITION); - decoder.SetSkipAttributeTransform(draco::GeometryAttribute::TEX_COORD); - - draco::DecoderBuffer in_buffer; - in_buffer.Init(buffer.data(), buffer.size()); - auto mesh = decoder.DecodeMeshFromBuffer(&in_buffer).value(); - ASSERT_NE(mesh, nullptr); - ASSERT_EQ(GetQuantizationBitsFromAttribute(mesh->attribute(0)), - pos_quantization); - ASSERT_EQ(GetQuantizationBitsFromAttribute(mesh->attribute(1)), - tex_coord_0_quantization); - ASSERT_EQ(GetQuantizationBitsFromAttribute(mesh->attribute(2)), - tex_coord_1_quantization); - } - - // Tests that the encoder returns the correct number of encoded points and - // faces for a given mesh or point cloud. - void TestNumberOfEncodedEntries(const std::string &file_name, - int32_t encoding_method) { - std::unique_ptr<draco::PointCloud> geometry; - draco::Mesh *mesh = nullptr; - - if (encoding_method == draco::MESH_EDGEBREAKER_ENCODING || - encoding_method == draco::MESH_SEQUENTIAL_ENCODING) { - std::unique_ptr<draco::Mesh> mesh_tmp = - draco::ReadMeshFromTestFile(file_name); - mesh = mesh_tmp.get(); - if (!mesh->DeduplicateAttributeValues()) - return; - mesh->DeduplicatePointIds(); - geometry = std::move(mesh_tmp); - } else { - geometry = draco::ReadPointCloudFromTestFile(file_name); - } - ASSERT_NE(mesh, nullptr); - - draco::Encoder encoder; - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 14); - encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, 12); - encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, 10); - - encoder.SetEncodingMethod(encoding_method); - - encoder.SetTrackEncodedProperties(true); - - draco::EncoderBuffer buffer; - if (mesh) { - encoder.EncodeMeshToBuffer(*mesh, &buffer); - } else { - encoder.EncodePointCloudToBuffer(*geometry, &buffer); - } - - // Ensure the logged number of encoded points and faces matches the number - // we get from the decoder. - - draco::DecoderBuffer decoder_buffer; - decoder_buffer.Init(buffer.data(), buffer.size()); - draco::Decoder decoder; - - if (mesh) { - auto maybe_mesh = decoder.DecodeMeshFromBuffer(&decoder_buffer); - ASSERT_TRUE(maybe_mesh.ok()); - auto decoded_mesh = std::move(maybe_mesh).value(); - ASSERT_NE(decoded_mesh, nullptr); - ASSERT_EQ(decoded_mesh->num_points(), encoder.num_encoded_points()); - ASSERT_EQ(decoded_mesh->num_faces(), encoder.num_encoded_faces()); - } else { - auto maybe_pc = decoder.DecodePointCloudFromBuffer(&decoder_buffer); - ASSERT_TRUE(maybe_pc.ok()); - auto decoded_pc = std::move(maybe_pc).value(); - ASSERT_EQ(decoded_pc->num_points(), encoder.num_encoded_points()); - } - } -}; - -TEST_F(EncodeTest, TestExpertEncoderQuantization) { - // This test verifies that the expert encoder can quantize individual - // attributes even if they have the same type. - auto mesh = CreateTestMesh(); - ASSERT_NE(mesh, nullptr); - - draco::ExpertEncoder encoder(*mesh.get()); - encoder.SetAttributeQuantization(0, 16); // Position quantization. - encoder.SetAttributeQuantization(1, 15); // Tex-coord 0 quantization. - encoder.SetAttributeQuantization(2, 14); // Tex-coord 1 quantization. - - draco::EncoderBuffer buffer; - encoder.EncodeToBuffer(&buffer); - VerifyNumQuantizationBits(buffer, 16, 15, 14); -} - -TEST_F(EncodeTest, TestEncoderQuantization) { - // This test verifies that Encoder applies the same quantization to all - // attributes of the same type. - auto mesh = CreateTestMesh(); - ASSERT_NE(mesh, nullptr); - - draco::Encoder encoder; - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 16); - encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, 15); - - draco::EncoderBuffer buffer; - encoder.EncodeMeshToBuffer(*mesh.get(), &buffer); - VerifyNumQuantizationBits(buffer, 16, 15, 15); -} - -TEST_F(EncodeTest, TestLinesObj) { - // This test verifies that Encoder can encode file that contains only line - // segments (that are ignored). - std::unique_ptr<draco::Mesh> mesh( - draco::ReadMeshFromTestFile("test_lines.obj")); - ASSERT_NE(mesh, nullptr); - ASSERT_EQ(mesh->num_faces(), 0); - std::unique_ptr<draco::PointCloud> pc( - draco::ReadPointCloudFromTestFile("test_lines.obj")); - ASSERT_NE(pc, nullptr); - - draco::Encoder encoder; - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 16); - - draco::EncoderBuffer buffer; - ASSERT_TRUE(encoder.EncodePointCloudToBuffer(*pc, &buffer).ok()); -} - -TEST_F(EncodeTest, TestKdTreeEncoding) { - // This test verifies that the API can successfully encode a point cloud - // defined by several attributes using the kd tree method. - std::unique_ptr<draco::PointCloud> pc = CreateTestPointCloud(); - ASSERT_NE(pc, nullptr); - - draco::EncoderBuffer buffer; - draco::Encoder encoder; - encoder.SetEncodingMethod(draco::POINT_CLOUD_KD_TREE_ENCODING); - // First try it without quantizing positions which should fail. - ASSERT_FALSE(encoder.EncodePointCloudToBuffer(*pc, &buffer).ok()); - - // Now set quantization for the position attribute which should make - // the encoder happy. - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 16); - ASSERT_TRUE(encoder.EncodePointCloudToBuffer(*pc, &buffer).ok()); -} - -TEST_F(EncodeTest, TestTrackingOfNumberOfEncodedEntries) { - TestNumberOfEncodedEntries("deg_faces.obj", draco::MESH_EDGEBREAKER_ENCODING); - TestNumberOfEncodedEntries("deg_faces.obj", draco::MESH_SEQUENTIAL_ENCODING); - TestNumberOfEncodedEntries("cube_att.obj", draco::MESH_EDGEBREAKER_ENCODING); - TestNumberOfEncodedEntries("test_nm.obj", draco::MESH_EDGEBREAKER_ENCODING); - TestNumberOfEncodedEntries("test_nm.obj", draco::MESH_SEQUENTIAL_ENCODING); - TestNumberOfEncodedEntries("cube_subd.obj", - draco::POINT_CLOUD_KD_TREE_ENCODING); - TestNumberOfEncodedEntries("cube_subd.obj", - draco::POINT_CLOUD_SEQUENTIAL_ENCODING); -} - -TEST_F(EncodeTest, TestTrackingOfNumberOfEncodedEntriesNotSet) { - // Tests that when tracing of encoded properties is disabled, the returned - // number of encoded faces and points is 0. - std::unique_ptr<draco::Mesh> mesh( - draco::ReadMeshFromTestFile("cube_att.obj")); - ASSERT_NE(mesh, nullptr); - - draco::EncoderBuffer buffer; - draco::Encoder encoder; - - ASSERT_TRUE(encoder.EncodeMeshToBuffer(*mesh, &buffer).ok()); - ASSERT_EQ(encoder.num_encoded_points(), 0); - ASSERT_EQ(encoder.num_encoded_faces(), 0); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/shannon_entropy_test.cc b/extern/draco/dracoenc/src/draco/compression/entropy/shannon_entropy_test.cc deleted file mode 100644 index c2fe64440be..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/entropy/shannon_entropy_test.cc +++ /dev/null @@ -1,56 +0,0 @@ -#include "draco/compression/entropy/shannon_entropy.h" -#include "draco/core/draco_test_base.h" - -namespace { - -TEST(ShannonEntropyTest, TestBinaryEntropy) { - // Test verifies that computing binary entropy works as expected. - ASSERT_EQ(draco::ComputeBinaryShannonEntropy(0, 0), 0); - ASSERT_EQ(draco::ComputeBinaryShannonEntropy(10, 0), 0); - ASSERT_EQ(draco::ComputeBinaryShannonEntropy(10, 10), 0); - ASSERT_NEAR(draco::ComputeBinaryShannonEntropy(10, 5), 1.0, 1e-4); -} - -TEST(ShannonEntropyTest, TestStreamEntropy) { - // Test verifies that the entropy of streamed data is computed correctly. - const std::vector<uint32_t> symbols = {1, 5, 1, 100, 2, 1}; - - draco::ShannonEntropyTracker entropy_tracker; - - // Nothing added, 0 entropy. - ASSERT_EQ(entropy_tracker.GetNumberOfDataBits(), 0); - - // Try to push symbols one by one. - uint32_t max_symbol = 0; - for (int i = 0; i < symbols.size(); ++i) { - if (symbols[i] > max_symbol) - max_symbol = symbols[i]; - const auto entropy_data = entropy_tracker.Push(&symbols[i], 1); - - const int64_t stream_entropy_bits = entropy_tracker.GetNumberOfDataBits(); - // Ensure the returned entropy_data is in sync with the stream. - ASSERT_EQ(draco::ShannonEntropyTracker::GetNumberOfDataBits(entropy_data), - stream_entropy_bits); - - // Make sure the entropy is approximately the same as the one we compute - // directly from all symbols. - const int64_t expected_entropy_bits = draco::ComputeShannonEntropy( - symbols.data(), i + 1, max_symbol, nullptr); - - // For now hardcoded tolerance of 2 bits. - ASSERT_NEAR(expected_entropy_bits, stream_entropy_bits, 2); - } - - // Compare it also to the case when we add all symbols in one call. - draco::ShannonEntropyTracker entropy_tracker_2; - entropy_tracker_2.Push(symbols.data(), symbols.size()); - const int64_t stream_2_entropy_bits = entropy_tracker_2.GetNumberOfDataBits(); - ASSERT_EQ(entropy_tracker.GetNumberOfDataBits(), stream_2_entropy_bits); - - // Ensure that peeking does not change the entropy. - entropy_tracker_2.Peek(symbols.data(), 1); - - ASSERT_EQ(stream_2_entropy_bits, entropy_tracker_2.GetNumberOfDataBits()); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_coding_test.cc b/extern/draco/dracoenc/src/draco/compression/entropy/symbol_coding_test.cc deleted file mode 100644 index ba7166bbe75..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/entropy/symbol_coding_test.cc +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/config/compression_shared.h" -#include "draco/compression/entropy/symbol_decoding.h" -#include "draco/compression/entropy/symbol_encoding.h" -#include "draco/core/bit_utils.h" -#include "draco/core/decoder_buffer.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/encoder_buffer.h" - -namespace draco { - -class SymbolCodingTest : public ::testing::Test { - protected: - SymbolCodingTest() : bitstream_version_(kDracoMeshBitstreamVersion) {} - - template <class SignedIntTypeT> - void TestConvertToSymbolAndBack(SignedIntTypeT x) { - typedef typename std::make_unsigned<SignedIntTypeT>::type Symbol; - Symbol symbol = ConvertSignedIntToSymbol(x); - SignedIntTypeT y = ConvertSymbolToSignedInt(symbol); - ASSERT_EQ(x, y); - } - - uint16_t bitstream_version_; -}; - -TEST_F(SymbolCodingTest, TestLargeNumbers) { - // This test verifies that SymbolCoding successfully encodes an array of large - // numbers. - const uint32_t in[] = {12345678, 1223333, 111, 5}; - const int num_values = sizeof(in) / sizeof(uint32_t); - EncoderBuffer eb; - ASSERT_TRUE(EncodeSymbols(in, num_values, 1, nullptr, &eb)); - - std::vector<uint32_t> out; - out.resize(num_values); - DecoderBuffer db; - db.Init(eb.data(), eb.size()); - db.set_bitstream_version(bitstream_version_); - ASSERT_TRUE(DecodeSymbols(num_values, 1, &db, &out[0])); - for (int i = 0; i < num_values; ++i) { - EXPECT_EQ(in[i], out[i]); - } -} - -TEST_F(SymbolCodingTest, TestManyNumbers) { - // This test verifies that SymbolCoding successfully encodes an array of - // several numbers that repeat many times. - - // Value/frequency pairs. - const std::pair<uint32_t, uint32_t> in[] = { - {12, 1500}, {1025, 31000}, {7, 1}, {9, 5}, {0, 6432}}; - - const int num_pairs = sizeof(in) / sizeof(std::pair<uint32_t, uint32_t>); - - std::vector<uint32_t> in_values; - for (int i = 0; i < num_pairs; ++i) { - in_values.insert(in_values.end(), in[i].second, in[i].first); - } - for (int method = 0; method < NUM_SYMBOL_CODING_METHODS; ++method) { - // Test the encoding using all available symbol coding methods. - Options options; - SetSymbolEncodingMethod(&options, static_cast<SymbolCodingMethod>(method)); - - EncoderBuffer eb; - ASSERT_TRUE( - EncodeSymbols(in_values.data(), in_values.size(), 1, &options, &eb)); - std::vector<uint32_t> out_values; - out_values.resize(in_values.size()); - DecoderBuffer db; - db.Init(eb.data(), eb.size()); - db.set_bitstream_version(bitstream_version_); - ASSERT_TRUE(DecodeSymbols(in_values.size(), 1, &db, &out_values[0])); - for (uint32_t i = 0; i < in_values.size(); ++i) { - ASSERT_EQ(in_values[i], out_values[i]); - } - } -} - -TEST_F(SymbolCodingTest, TestEmpty) { - // This test verifies that SymbolCoding successfully encodes an empty array. - EncoderBuffer eb; - ASSERT_TRUE(EncodeSymbols(nullptr, 0, 1, nullptr, &eb)); - DecoderBuffer db; - db.Init(eb.data(), eb.size()); - db.set_bitstream_version(bitstream_version_); - ASSERT_TRUE(DecodeSymbols(0, 1, &db, nullptr)); -} - -TEST_F(SymbolCodingTest, TestOneSymbol) { - // This test verifies that SymbolCoding successfully encodes an a single - // symbol. - EncoderBuffer eb; - const std::vector<uint32_t> in(1200, 0); - ASSERT_TRUE(EncodeSymbols(in.data(), in.size(), 1, nullptr, &eb)); - - std::vector<uint32_t> out(in.size()); - DecoderBuffer db; - db.Init(eb.data(), eb.size()); - db.set_bitstream_version(bitstream_version_); - ASSERT_TRUE(DecodeSymbols(in.size(), 1, &db, &out[0])); - for (uint32_t i = 0; i < in.size(); ++i) { - ASSERT_EQ(in[i], out[i]); - } -} - -TEST_F(SymbolCodingTest, TestBitLengths) { - // This test verifies that SymbolCoding successfully encodes symbols of - // various bit lengths - EncoderBuffer eb; - std::vector<uint32_t> in; - constexpr int bit_lengths = 18; - for (int i = 0; i < bit_lengths; ++i) { - in.push_back(1 << i); - } - std::vector<uint32_t> out(in.size()); - for (int i = 0; i < bit_lengths; ++i) { - eb.Clear(); - ASSERT_TRUE(EncodeSymbols(in.data(), i + 1, 1, nullptr, &eb)); - DecoderBuffer db; - db.Init(eb.data(), eb.size()); - db.set_bitstream_version(bitstream_version_); - ASSERT_TRUE(DecodeSymbols(i + 1, 1, &db, &out[0])); - for (int j = 0; j < i + 1; ++j) { - ASSERT_EQ(in[j], out[j]); - } - } -} - -TEST_F(SymbolCodingTest, TestLargeNumberCondition) { - // This test verifies that SymbolCoding successfully encodes large symbols - // that are on the boundary between raw scheme and tagged scheme (18 bits). - EncoderBuffer eb; - constexpr int num_symbols = 1000000; - const std::vector<uint32_t> in(num_symbols, 1 << 18); - ASSERT_TRUE(EncodeSymbols(in.data(), in.size(), 1, nullptr, &eb)); - - std::vector<uint32_t> out(in.size()); - DecoderBuffer db; - db.Init(eb.data(), eb.size()); - db.set_bitstream_version(bitstream_version_); - ASSERT_TRUE(DecodeSymbols(in.size(), 1, &db, &out[0])); - for (uint32_t i = 0; i < in.size(); ++i) { - ASSERT_EQ(in[i], out[i]); - } -} - -TEST_F(SymbolCodingTest, TestConversionFullRange) { - TestConvertToSymbolAndBack(static_cast<int8_t>(-128)); - TestConvertToSymbolAndBack(static_cast<int8_t>(-127)); - TestConvertToSymbolAndBack(static_cast<int8_t>(-1)); - TestConvertToSymbolAndBack(static_cast<int8_t>(0)); - TestConvertToSymbolAndBack(static_cast<int8_t>(1)); - TestConvertToSymbolAndBack(static_cast<int8_t>(127)); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_decoder_helpers.h b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_decoder_helpers.h deleted file mode 100644 index 12ac46b3698..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_decoder_helpers.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_COMPRESSION_MESH_MESH_DECODER_HELPERS_H_ -#define DRACO_COMPRESSION_MESH_MESH_DECODER_HELPERS_H_ - -#include "draco/compression/mesh/mesh_decoder.h" - -namespace draco { - -// Function for decoding a stream previously encoded by a MeshEncoder. The -// result is stored into a stream of single precision floating point numbers -// in a XYZ|UV format, where one value is stored for every corner of each -// triangle. -// On error, the function sets the input stream "is" to an invalid state. -template <typename InStreamT> -InStreamT &DecodePos3Tex2DataFromStream(InStreamT &&is, - std::vector<float> *out_data) { - // Determine the size of the encoded data and write it into a vector. - const auto start_pos = is.tellg(); - is.seekg(0, std::ios::end); - const std::streampos is_size = is.tellg() - start_pos; - is.seekg(start_pos); - std::vector<char> data(is_size); - is.read(&data[0], is_size); - - // Create a mesh from the data. - std::unique_ptr<Mesh> mesh = draco::DecodeMesh(&data[0], data.size()); - - if (mesh == nullptr) { - is.setstate(ios_base::badbit); - return is; - } - - const PointAttribute *pos_att = - mesh->GetNamedAttribute(GeometryAttribute::POSITION); - const PointAttribute *tex_att = - mesh->GetNamedAttribute(GeometryAttribute::TEX_COORD_0); - - // Both position and texture attributes must be present. - if (pos_att == nullptr || tex_att == nullptr) { - is.setstate(ios_base::badbit); - return is; - } - - // Copy the mesh data into the provided output. - constexpr int data_stride = 5; - // Prepare the output storage for 3 output values per face. - out_data->resize(mesh->num_faces() * 3 * data_stride); - - std::array<float, 3> pos_val; - std::array<float, 2> tex_val; - int out_it = 0; - for (int f = 0; f < mesh->num_faces(); ++f) { - const Mesh::Face &face = mesh->face(f); - for (int p = 0; p < 3; ++p) { - pos_att->ConvertValue<float, 3>(pos_att->mapped_index(face[p]), - &pos_val[0]); - memcpy(&out_data->at(0) + out_it, &pos_val[0], sizeof(pos_val)); - out_it += 3; - tex_att->ConvertValue<float, 2>(tex_att->mapped_index(face[p]), - &tex_val[0]); - memcpy(&out_data->at(0) + out_it, &tex_val[0], sizeof(tex_val)); - out_it += 2; - } - } - - return is; -} - -} // namespace draco - -#endif // DRACO_COMPRESSION_MESH_MESH_DECODER_HELPERS_H_ diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoding_test.cc b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoding_test.cc deleted file mode 100644 index 8313882455b..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoding_test.cc +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include <sstream> - -#include "draco/compression/encode.h" -#include "draco/compression/mesh/mesh_edgebreaker_decoder.h" -#include "draco/compression/mesh/mesh_edgebreaker_encoder.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/mesh_io.h" -#include "draco/io/obj_decoder.h" -#include "draco/mesh/mesh_are_equivalent.h" -#include "draco/mesh/mesh_cleanup.h" -#include "draco/mesh/triangle_soup_mesh_builder.h" - -namespace draco { - -class MeshEdgebreakerEncodingTest : public ::testing::Test { - protected: - void TestFile(const std::string &file_name) { TestFile(file_name, -1); } - - void TestFile(const std::string &file_name, int compression_level) { - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - - TestMesh(mesh.get(), compression_level); - } - - void TestMesh(Mesh *mesh, int compression_level) { - EncoderBuffer buffer; - MeshEdgebreakerEncoder encoder; - EncoderOptions encoder_options = EncoderOptions::CreateDefaultOptions(); - encoder_options.SetSpeed(10 - compression_level, 10 - compression_level); - encoder.SetMesh(*mesh); - ASSERT_TRUE(encoder.Encode(encoder_options, &buffer).ok()); - - DecoderBuffer dec_buffer; - dec_buffer.Init(buffer.data(), buffer.size()); - MeshEdgebreakerDecoder decoder; - - std::unique_ptr<Mesh> decoded_mesh(new Mesh()); - DecoderOptions dec_options; - ASSERT_TRUE( - decoder.Decode(dec_options, &dec_buffer, decoded_mesh.get()).ok()); - - // Cleanup the input mesh to make sure that input and output can be - // compared (edgebreaker method discards degenerated triangles and isolated - // vertices). - const MeshCleanupOptions options; - MeshCleanup cleanup; - ASSERT_TRUE(cleanup(mesh, options)) << "Failed to clean the input mesh."; - - MeshAreEquivalent eq; - ASSERT_TRUE(eq(*mesh, *decoded_mesh.get())) - << "Decoded mesh is not the same as the input"; - } -}; - -TEST_F(MeshEdgebreakerEncodingTest, TestNmOBJ) { - const std::string file_name = "test_nm.obj"; - TestFile(file_name); -} - -TEST_F(MeshEdgebreakerEncodingTest, ThreeFacesOBJ) { - const std::string file_name = "extra_vertex.obj"; - TestFile(file_name); -} - -TEST_F(MeshEdgebreakerEncodingTest, TestPly) { - // Tests whether the edgebreaker successfully encodes and decodes the test - // file (ply with color). - const std::string file_name = "test_pos_color.ply"; - TestFile(file_name); -} - -TEST_F(MeshEdgebreakerEncodingTest, TestMultiAttributes) { - // Tests encoding of model with many attributes. - const std::string file_name = "cube_att.obj"; - TestFile(file_name, 10); -} - -TEST_F(MeshEdgebreakerEncodingTest, TestEncoderReuse) { - // Tests whether the edgebreaker encoder can be reused multiple times to - // encode a given mesh. - const std::string file_name = "test_pos_color.ply"; - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - - MeshEdgebreakerEncoder encoder; - EncoderOptions encoder_options = EncoderOptions::CreateDefaultOptions(); - encoder.SetMesh(*mesh); - EncoderBuffer buffer_0, buffer_1; - ASSERT_TRUE(encoder.Encode(encoder_options, &buffer_0).ok()); - ASSERT_TRUE(encoder.Encode(encoder_options, &buffer_1).ok()); - - // Make sure both buffer are identical. - ASSERT_EQ(buffer_0.size(), buffer_1.size()); - for (int i = 0; i < buffer_0.size(); ++i) { - ASSERT_EQ(buffer_0.data()[i], buffer_1.data()[i]); - } -} - -TEST_F(MeshEdgebreakerEncodingTest, TestDecoderReuse) { - // Tests whether the edgebreaker decoder can be reused multiple times to - // decode a given mesh. - const std::string file_name = "test_pos_color.ply"; - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - - MeshEdgebreakerEncoder encoder; - EncoderOptions encoder_options = EncoderOptions::CreateDefaultOptions(); - encoder.SetMesh(*mesh); - EncoderBuffer buffer; - ASSERT_TRUE(encoder.Encode(encoder_options, &buffer).ok()); - - DecoderBuffer dec_buffer; - dec_buffer.Init(buffer.data(), buffer.size()); - - MeshEdgebreakerDecoder decoder; - - // Decode the mesh two times. - std::unique_ptr<Mesh> decoded_mesh_0(new Mesh()); - DecoderOptions dec_options; - ASSERT_TRUE( - decoder.Decode(dec_options, &dec_buffer, decoded_mesh_0.get()).ok()); - - dec_buffer.Init(buffer.data(), buffer.size()); - std::unique_ptr<Mesh> decoded_mesh_1(new Mesh()); - ASSERT_TRUE( - decoder.Decode(dec_options, &dec_buffer, decoded_mesh_1.get()).ok()); - - // Make sure both of the meshes are identical. - MeshAreEquivalent eq; - ASSERT_TRUE(eq(*decoded_mesh_0.get(), *decoded_mesh_1.get())) - << "Decoded meshes are not the same"; -} - -TEST_F(MeshEdgebreakerEncodingTest, TestSingleConnectivityEncoding) { - // Tests whether the edgebreaker method successfully encodes a mesh with - // multiple attributes using single connectivity by breaking the mesh along - // attribute seams. - const std::string file_name = "cube_att.obj"; - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - - for (int i = 0; i < 2; ++i) { - // Set the option to enable/disable single connectivity encoding. - EncoderOptionsBase<GeometryAttribute::Type> options = - EncoderOptionsBase<GeometryAttribute::Type>::CreateDefaultOptions(); - options.SetGlobalBool("split_mesh_on_seams", i == 0 ? true : false); - - EncoderBuffer buffer; - draco::Encoder encoder; - encoder.Reset(options); - encoder.SetSpeedOptions(0, 0); - encoder.SetAttributeQuantization(GeometryAttribute::POSITION, 8); - encoder.SetAttributeQuantization(GeometryAttribute::TEX_COORD, 8); - encoder.SetAttributeQuantization(GeometryAttribute::NORMAL, 8); - encoder.SetEncodingMethod(MESH_EDGEBREAKER_ENCODING); - ASSERT_TRUE(encoder.EncodeMeshToBuffer(*mesh, &buffer).ok()); - - DecoderBuffer dec_buffer; - dec_buffer.Init(buffer.data(), buffer.size()); - - Decoder decoder; - auto dec_mesh = decoder.DecodeMeshFromBuffer(&dec_buffer).value(); - ASSERT_NE(dec_mesh, nullptr); - ASSERT_EQ(dec_mesh->num_points(), 24); - ASSERT_EQ(dec_mesh->num_attributes(), 3); - ASSERT_EQ(dec_mesh->attribute(0)->size(), i == 0 ? 24 : 8); - ASSERT_EQ(dec_mesh->attribute(1)->size(), 24); - ASSERT_EQ(dec_mesh->attribute(2)->size(), 24); - } -} - -TEST_F(MeshEdgebreakerEncodingTest, TestWrongAttributeOrder) { - // Tests whether the edgebreaker method successfully encodes a mesh where the - // input attributes are in wrong order (because of their internal - // dependencies). In such case the attributes should be rearranged to the - // correct order. - TriangleSoupMeshBuilder mb; - mb.Start(1); - const int32_t norm_att_id = - mb.AddAttribute(GeometryAttribute::NORMAL, 3, DT_FLOAT32); - const int32_t pos_att_id = - mb.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - - mb.SetAttributeValuesForFace( - pos_att_id, FaceIndex(0), Vector3f(0.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), Vector3f(0.f, 1.f, 0.f).data()); - - mb.SetAttributeValuesForFace( - norm_att_id, FaceIndex(0), Vector3f(0.f, 0.f, 1.f).data(), - Vector3f(0.f, 0.f, 0.f).data(), Vector3f(0.f, 0.f, 1.f).data()); - std::unique_ptr<Mesh> mesh = mb.Finalize(); - ASSERT_NE(mesh, nullptr); - ASSERT_EQ(mesh->num_attributes(), 2); - ASSERT_EQ(mesh->attribute(0)->attribute_type(), GeometryAttribute::NORMAL); - ASSERT_EQ(mesh->attribute(1)->attribute_type(), GeometryAttribute::POSITION); - - EncoderBuffer buffer; - draco::Encoder encoder; - encoder.SetSpeedOptions(3, 3); - encoder.SetAttributeQuantization(GeometryAttribute::POSITION, 8); - encoder.SetAttributeQuantization(GeometryAttribute::NORMAL, 8); - encoder.SetEncodingMethod(MESH_EDGEBREAKER_ENCODING); - ASSERT_TRUE(encoder.EncodeMeshToBuffer(*mesh, &buffer).ok()); - - DecoderBuffer dec_buffer; - dec_buffer.Init(buffer.data(), buffer.size()); - - Decoder decoder; - auto dec_mesh = decoder.DecodeMeshFromBuffer(&dec_buffer).value(); - ASSERT_NE(dec_mesh, nullptr); - ASSERT_EQ(dec_mesh->num_attributes(), 2); - ASSERT_EQ(dec_mesh->attribute(0)->attribute_type(), - GeometryAttribute::POSITION); - ASSERT_EQ(dec_mesh->attribute(1)->attribute_type(), - GeometryAttribute::NORMAL); -} - -TEST_F(MeshEdgebreakerEncodingTest, TestDegenerateMesh) { - // Tests whether we can process a mesh that contains degenerate faces only. - const std::string file_name = "degenerate_mesh.obj"; - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - EncoderBuffer buffer; - MeshEdgebreakerEncoder encoder; - EncoderOptions encoder_options = EncoderOptions::CreateDefaultOptions(); - encoder.SetMesh(*mesh); - // We expect the encoding to fail as edgebreaker can only process valid faces. - ASSERT_FALSE(encoder.Encode(encoder_options, &buffer).ok()); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_helpers.h b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_helpers.h deleted file mode 100644 index d809a521369..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_helpers.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_COMPRESSION_MESH_MESH_ENCODER_HELPERS_H_ -#define DRACO_COMPRESSION_MESH_MESH_ENCODER_HELPERS_H_ - -#include "draco/compression/mesh/mesh_encoder.h" -#include "draco/mesh/triangle_soup_mesh_builder.h" - -namespace draco { - -// Helper class for encoding data supplied in a stream of single precision -// floating point numbers formatted as XYZ|UV. The stream must contain three -// XYZ|UV values for every face of the mesh. -// The encoded data is written into the output stream "os". -// In case of error, the stream is set to an invalid state (ios_base::bad_bit). -template <typename OStreamT> -OStreamT EncodePos3Tex2DataToStream( - const float *data, int num_faces, CompressionMethod method, - const MeshCompressionOptions &compression_options, - const MeshAttributeCompressionOptions &pos_options, - const MeshAttributeCompressionOptions &tex_options, OStreamT &&os) { - // Build the mesh. - TriangleSoupMeshBuilder mb; - mb.Start(num_faces); - const int pos_att_id = - mb.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int tex_att_id = - mb.AddAttribute(GeometryAttribute::TEX_COORD_0, 2, DT_FLOAT32); - constexpr int data_stride = 5; - constexpr int tex_offset = 3; - for (int f = 0; f < num_faces; ++f) { - int offset = 3 * f * data_stride; - // Add position data for the face. - mb.SetAttributeValuesForFace(pos_att_id, f, data + offset, - data + offset + data_stride, - data + offset + 2 * data_stride); - // Add texture data for the face. - offset += tex_offset; - mb.SetAttributeValuesForFace(tex_att_id, f, data + offset, - data + offset + data_stride, - data + offset + 2 * data_stride); - } - std::unique_ptr<Mesh> mesh = mb.Finalize(); - if (mesh == nullptr) { - os.setstate(ios_base::badbit); - return os; - } - - // Set up the encoder. - std::unique_ptr<MeshEncoder> encoder = - MeshEncoder::CreateEncoderForMethod(method); - encoder->SetGlobalOptions(compression_options); - encoder->SetAttributeOptions(GeometryAttribute::POSITION, pos_options); - encoder->SetAttributeOptions(GeometryAttribute::TEX_COORD_0, tex_options); - - if (!encoder->EncodeMesh(mesh.get())) { - os.setstate(ios_base::badbit); - return os; - } - - // Write the encoded data into the stream. - os.write(static_cast<const char *>(encoder->buffer()->data()), - encoder->buffer()->size()); - return os; -} - -} // namespace draco - -#endif // DRACO_COMPRESSION_MESH_MESH_ENCODER_HELPERS_H_ diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc deleted file mode 100644 index 9f056fc22e3..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/mesh/mesh_encoder.h" - -#include "draco/compression/expert_encode.h" -#include "draco/core/decoder_buffer.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/obj_decoder.h" - -namespace draco { - -class MeshEncoderTest : public ::testing::TestWithParam<const char *> { - protected: - MeshEncoderTest() {} - - // Fills out_method with id of the encoding method used for the test. - // Returns false if the encoding method is not set properly. - bool GetMethod(MeshEncoderMethod *out_method) const { - if (strcmp(GetParam(), "sequential") == 0) { - *out_method = MESH_SEQUENTIAL_ENCODING; - return true; - } - if (strcmp(GetParam(), "edgebreaker") == 0) { - *out_method = MESH_EDGEBREAKER_ENCODING; - return true; - } - return false; - } -}; - -TEST_P(MeshEncoderTest, EncodeGoldenMesh) { - // This test verifies that a given set of meshes are encoded to an expected - // output. This is useful for catching bugs in code changes that are not - // supposed to change the encoding. - // The test is expected to fail when the encoding is modified. In such case, - // the golden files need to be updated to reflect the changes. - MeshEncoderMethod method; - ASSERT_TRUE(GetMethod(&method)) - << "Test is run for an unknown encoding method"; - - const std::string file_name = "test_nm.obj"; - std::string golden_file_name = file_name; - golden_file_name += '.'; - golden_file_name += GetParam(); - golden_file_name += ".1.2.0.drc"; - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - - ExpertEncoder encoder(*mesh.get()); - encoder.SetEncodingMethod(method); - encoder.SetAttributeQuantization(0, 20); - EncoderBuffer buffer; - ASSERT_TRUE(encoder.EncodeToBuffer(&buffer).ok()) - << "Failed encoding test mesh " << file_name << " with method " - << GetParam(); - // Check that the encoded mesh was really encoded with the selected method. - DecoderBuffer decoder_buffer; - decoder_buffer.Init(buffer.data(), buffer.size()); - decoder_buffer.Advance(8); // Skip the header to the encoding method id. - uint8_t encoded_method; - decoder_buffer.Decode(&encoded_method); - ASSERT_EQ(encoded_method, method); - if (!FLAGS_update_golden_files) { - EXPECT_TRUE( - CompareGoldenFile(golden_file_name, buffer.data(), buffer.size())) - << "Encoded data is different from the golden file. Please verify that " - "the encoding works as expected and update the golden file if " - "necessary (run the test with --update_golden_files flag)."; - } else { - // Save the files into the local folder. - EXPECT_TRUE( - GenerateGoldenFile(golden_file_name, buffer.data(), buffer.size())) - << "Failed to generate new golden file for " << file_name; - } -} - -INSTANTIATE_TEST_SUITE_P(MeshEncoderTests, MeshEncoderTest, - ::testing::Values("sequential", "edgebreaker")); - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoding_test.cc b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoding_test.cc deleted file mode 100644 index 6156cfe02b5..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoding_test.cc +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/point_cloud/point_cloud_kd_tree_decoder.h" -#include "draco/compression/point_cloud/point_cloud_kd_tree_encoder.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/core/vector_d.h" -#include "draco/io/obj_decoder.h" -#include "draco/point_cloud/point_cloud_builder.h" - -namespace draco { - -class PointCloudKdTreeEncodingTest : public ::testing::Test { - protected: - void ComparePointClouds(const PointCloud &p0, const PointCloud &p1) const { - ASSERT_EQ(p0.num_points(), p1.num_points()); - ASSERT_EQ(p0.num_attributes(), p1.num_attributes()); - // Currently works only with one attribute. - ASSERT_EQ(p0.num_attributes(), p1.num_attributes()); - for (auto index = 0; index < p0.num_attributes(); index += 1) { - ASSERT_EQ(p0.attribute(index)->num_components(), - p1.attribute(index)->num_components()); - std::vector<double> points_0, points_1; - std::vector<double> att_entry_0(p0.attribute(index)->num_components()); - std::vector<double> att_entry_1(p0.attribute(index)->num_components()); - for (PointIndex i(0); i < p0.num_points(); ++i) { - p0.attribute(index)->ConvertValue(p0.attribute(index)->mapped_index(i), - &att_entry_0[0]); - p1.attribute(index)->ConvertValue(p1.attribute(index)->mapped_index(i), - &att_entry_1[0]); - for (int d = 0; d < p0.attribute(index)->num_components(); ++d) { - points_0.push_back(att_entry_0[d]); - points_1.push_back(att_entry_1[d]); - } - } - // To compare the point clouds we sort points components from both inputs - // separately, and then we compare all matching coordinates one by one. - // TODO(ostava): Note that this is not guaranteed to work for quantized - // point clouds because the order of points may actually change because - // of the quantization. The test should be make more robust to handle such - // case. - std::sort(points_0.begin(), points_0.end()); - std::sort(points_1.begin(), points_1.end()); - for (uint32_t i = 0; i < points_0.size(); ++i) { - ASSERT_LE(std::fabs(points_0[i] - points_1[i]), 1e-2); - } - } - } - - void TestKdTreeEncoding(const PointCloud &pc) { - EncoderBuffer buffer; - PointCloudKdTreeEncoder encoder; - EncoderOptions options = EncoderOptions::CreateDefaultOptions(); - options.SetGlobalInt("quantization_bits", 16); - for (int compression_level = 0; compression_level <= 6; - ++compression_level) { - options.SetSpeed(10 - compression_level, 10 - compression_level); - encoder.SetPointCloud(pc); - ASSERT_TRUE(encoder.Encode(options, &buffer).ok()); - - DecoderBuffer dec_buffer; - dec_buffer.Init(buffer.data(), buffer.size()); - PointCloudKdTreeDecoder decoder; - - std::unique_ptr<PointCloud> out_pc(new PointCloud()); - DecoderOptions dec_options; - ASSERT_TRUE(decoder.Decode(dec_options, &dec_buffer, out_pc.get()).ok()); - - ComparePointClouds(pc, *out_pc); - } - } - - void TestFloatEncoding(const std::string &file_name) { - std::unique_ptr<PointCloud> pc = ReadPointCloudFromTestFile(file_name); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc.get()); - } -}; - -TEST_F(PointCloudKdTreeEncodingTest, TestFloatKdTreeEncoding) { - TestFloatEncoding("cube_subd.obj"); -} - -TEST_F(PointCloudKdTreeEncodingTest, TestIntKdTreeEncoding) { - constexpr int num_points = 120; - std::vector<std::array<uint32_t, 3>> points(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 3> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127); - pos[1] = 13 * ((i * 3) % 321); - pos[2] = 29 * ((i * 19) % 450); - points[i] = pos; - } - - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id, PointIndex(i), - &(points[i.value()])[0]); - } - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -// test higher dimensions with more attributes -TEST_F(PointCloudKdTreeEncodingTest, TestIntKdTreeEncodingHigherDimension) { - constexpr int num_points = 120; - std::vector<std::array<uint32_t, 3>> points3(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 3> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127); - pos[1] = 13 * ((i * 3) % 321); - pos[2] = 29 * ((i * 19) % 450); - points3[i] = pos; - } - std::vector<std::array<uint32_t, 2>> points2(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 2> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 1; - pos[1] = 13 * ((i * 3) % 321) + 1; - points2[i] = pos; - } - std::vector<std::array<uint32_t, 1>> points1(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 1> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 11; - points1[i] = pos; - } - - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id3 = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id3, PointIndex(i), - &(points3[i.value()])[0]); - } - const int att_id2 = - builder.AddAttribute(GeometryAttribute::POSITION, 2, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id2, PointIndex(i), - &(points2[i.value()])[0]); - } - const int att_id1 = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id1, PointIndex(i), - &(points1[i.value()])[0]); - } - - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -// Test 16 and 8 bit encoding. -TEST_F(PointCloudKdTreeEncodingTest, - TestIntKdTreeEncodingHigherDimensionVariedTypes) { - constexpr int num_points = 120; - std::vector<std::array<uint32_t, 3>> points3(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 3> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127); - pos[1] = 13 * ((i * 3) % 321); - pos[2] = 29 * ((i * 19) % 450); - points3[i] = pos; - } - std::vector<std::array<uint16_t, 2>> points2(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint16_t, 2> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 1; - pos[1] = 13 * ((i * 3) % 321) + 1; - points2[i] = pos; - } - std::vector<std::array<uint8_t, 1>> points1(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint8_t, 1> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 11; - points1[i] = pos; - } - - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id3 = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id3, PointIndex(i), - &(points3[i.value()])[0]); - } - const int att_id2 = - builder.AddAttribute(GeometryAttribute::POSITION, 2, DT_UINT16); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id2, PointIndex(i), - &(points2[i.value()])[0]); - } - const int att_id1 = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_UINT8); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id1, PointIndex(i), - &(points1[i.value()])[0]); - } - - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -// Test 16 only encoding for one attribute. -TEST_F(PointCloudKdTreeEncodingTest, TestIntKdTreeEncoding16Bit) { - constexpr int num_points = 120; - std::vector<std::array<uint16_t, 3>> points3(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint16_t, 3> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127); - pos[1] = 13 * ((i * 3) % 321); - pos[2] = 29 * ((i * 19) % 450); - points3[i] = pos; - } - - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id3 = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT16); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id3, PointIndex(i), - &(points3[i.value()])[0]); - } - - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -// Test 16 and 8 bit encoding with size bigger than 32bit encoding. -TEST_F(PointCloudKdTreeEncodingTest, - TestIntKdTreeEncodingHigherDimensionVariedTypesBig16BitEncoding) { - constexpr int num_points = 120; - std::vector<std::array<uint32_t, 3>> points3(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 3> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127); - pos[1] = 13 * ((i * 3) % 321); - pos[2] = 29 * ((i * 19) % 450); - points3[i] = pos; - } - // The total size of the 16bit encoding must be bigger than the total size of - // the 32bit encoding. - std::vector<std::array<uint16_t, 7>> points7(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint16_t, 7> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 1; - pos[1] = 13 * ((i * 3) % 321) + 1; - pos[2] = pos[0] + 13; - pos[3] = pos[2] + 13; - pos[4] = pos[3] + 13; - pos[5] = pos[4] + 13; - pos[6] = pos[5] + 13; - points7[i] = pos; - } - std::vector<std::array<uint8_t, 1>> points1(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint8_t, 1> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 11; - points1[i] = pos; - } - - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id3 = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id3, PointIndex(i), - &(points3[i.value()])[0]); - } - const int att_id2 = - builder.AddAttribute(GeometryAttribute::POSITION, 7, DT_UINT16); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id2, PointIndex(i), - &(points7[i.value()])[0]); - } - const int att_id1 = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_UINT8); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id1, PointIndex(i), - &(points1[i.value()])[0]); - } - - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -// Test encoding of quantized values. -TEST_F(PointCloudKdTreeEncodingTest, - TestIntKdTreeEncodingHigherDimensionFloatTypes) { - constexpr int num_points = 130; - std::vector<std::array<uint32_t, 3>> points3(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 3> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 125); - pos[1] = 13 * ((i * 3) % 334); - pos[2] = 29 * ((i * 19) % 470); - points3[i] = pos; - } - std::vector<std::array<float, 2>> points_float(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<float, 2> pos; - // Generate some pseudo-random points. - pos[0] = static_cast<float>(8 * ((i * 7) % 127) + 1) / 2.5f; - pos[1] = static_cast<float>(13 * ((i * 3) % 321) + 1) / 3.2f; - points_float[i] = pos; - } - - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id3 = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id3, PointIndex(i), - &(points3[i.value()])[0]); - } - const int att_id_float = - builder.AddAttribute(GeometryAttribute::GENERIC, 2, DT_FLOAT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id_float, PointIndex(i), - &(points_float[i.value()])[0]); - } - - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -// Test encoding of signed integer values -TEST_F(PointCloudKdTreeEncodingTest, TestIntKdTreeEncodingSignedTypes) { - constexpr int num_points = 120; - std::vector<std::array<uint32_t, 3>> points3(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, 3> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127); - pos[1] = 13 * ((i * 3) % 321); - pos[2] = 29 * ((i * 19) % 450); - points3[i] = pos; - } - std::vector<std::array<int32_t, 2>> points2(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<int32_t, 2> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 1; - if (i % 3 == 0) - pos[0] = -pos[0]; - pos[1] = 13 * ((i * 3) % 321) + 1; - points2[i] = pos; - } - std::vector<std::array<int16_t, 1>> points1(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<int16_t, 1> pos; - // Generate some pseudo-random points. - pos[0] = 8 * ((i * 7) % 127) + 11; - if (i % 5 == 0) - pos[0] = -pos[0]; - points1[i] = pos; - } - - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id3 = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id3, PointIndex(i), - &(points3[i.value()])[0]); - } - const int att_id2 = - builder.AddAttribute(GeometryAttribute::POSITION, 2, DT_INT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id2, PointIndex(i), - &(points2[i.value()])[0]); - } - - const int att_id1 = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT16); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id1, PointIndex(i), - &(points1[i.value()])[0]); - } - - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -// Test encoding of integer point clouds with > 16 dimensions. -TEST_F(PointCloudKdTreeEncodingTest, TestIntKdTreeEncodingHighDimensional) { - constexpr int num_points = 120; - constexpr int num_dims = 42; - std::vector<std::array<uint32_t, num_dims>> points(num_points); - for (int i = 0; i < num_points; ++i) { - std::array<uint32_t, num_dims> pos; - // Generate some pseudo-random points. - for (int d = 0; d < num_dims; ++d) { - pos[d] = 8 * ((i + d) * (7 + (d % 4)) % (127 + d % 3)); - } - points[i] = pos; - } - PointCloudBuilder builder; - builder.Start(num_points); - const int att_id = - builder.AddAttribute(GeometryAttribute::POSITION, num_dims, DT_UINT32); - for (PointIndex i(0); i < num_points; ++i) { - builder.SetAttributeValueForPoint(att_id, PointIndex(i), - &(points[i.value()])[0]); - } - - std::unique_ptr<PointCloud> pc = builder.Finalize(false); - ASSERT_NE(pc, nullptr); - - TestKdTreeEncoding(*pc); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoding_test.cc b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoding_test.cc deleted file mode 100644 index beab4bcd7e9..00000000000 --- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoding_test.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/compression/point_cloud/point_cloud_sequential_decoder.h" -#include "draco/compression/point_cloud/point_cloud_sequential_encoder.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/obj_decoder.h" - -namespace draco { - -class PointCloudSequentialEncodingTest : public ::testing::Test { - protected: - std::unique_ptr<PointCloud> EncodeAndDecodePointCloud(const PointCloud *pc) { - EncoderBuffer buffer; - PointCloudSequentialEncoder encoder; - EncoderOptions options = EncoderOptions::CreateDefaultOptions(); - encoder.SetPointCloud(*pc); - if (!encoder.Encode(options, &buffer).ok()) - return nullptr; - - DecoderBuffer dec_buffer; - dec_buffer.Init(buffer.data(), buffer.size()); - PointCloudSequentialDecoder decoder; - - std::unique_ptr<PointCloud> out_pc(new PointCloud()); - DecoderOptions dec_options; - if (!decoder.Decode(dec_options, &dec_buffer, out_pc.get()).ok()) - return nullptr; - return out_pc; - } - - void TestEncoding(const std::string &file_name) { - std::unique_ptr<PointCloud> pc = ReadPointCloudFromTestFile(file_name); - ASSERT_NE(pc, nullptr); - - std::unique_ptr<PointCloud> decoded_pc = - EncodeAndDecodePointCloud(pc.get()); - ASSERT_NE(decoded_pc.get(), nullptr); - ASSERT_EQ(decoded_pc->num_points(), pc->num_points()); - } -}; - -TEST_F(PointCloudSequentialEncodingTest, DoesEncodeAndDecode) { - TestEncoding("test_nm.obj"); -} - -TEST_F(PointCloudSequentialEncodingTest, EncodingPointCloudWithMetadata) { - std::unique_ptr<PointCloud> pc = ReadPointCloudFromTestFile("test_nm.obj"); - ASSERT_NE(pc, nullptr); - // Add metadata to point cloud. - std::unique_ptr<GeometryMetadata> metadata = - std::unique_ptr<GeometryMetadata>(new GeometryMetadata()); - const uint32_t pos_att_id = - pc->GetNamedAttributeId(GeometryAttribute::POSITION); - std::unique_ptr<AttributeMetadata> pos_metadata = - std::unique_ptr<AttributeMetadata>(new AttributeMetadata()); - pos_metadata->AddEntryString("name", "position"); - pc->AddAttributeMetadata(pos_att_id, std::move(pos_metadata)); - - std::unique_ptr<PointCloud> decoded_pc = EncodeAndDecodePointCloud(pc.get()); - ASSERT_NE(decoded_pc.get(), nullptr); - - const GeometryMetadata *const pc_metadata = decoded_pc->GetMetadata(); - ASSERT_NE(pc_metadata, nullptr); - // Test getting attribute metadata by id. - ASSERT_NE(pc->GetAttributeMetadataByAttributeId(pos_att_id), nullptr); - // Test getting attribute metadata by entry name value pair. - const AttributeMetadata *const requested_att_metadata = - pc_metadata->GetAttributeMetadataByStringEntry("name", "position"); - ASSERT_NE(requested_att_metadata, nullptr); - ASSERT_EQ(requested_att_metadata->att_unique_id(), - pc->attribute(pos_att_id)->unique_id()); -} - -// TODO(ostava): Test the reusability of a single instance of the encoder and -// decoder class. - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/core/buffer_bit_coding_test.cc b/extern/draco/dracoenc/src/draco/core/buffer_bit_coding_test.cc deleted file mode 100644 index e761284e236..00000000000 --- a/extern/draco/dracoenc/src/draco/core/buffer_bit_coding_test.cc +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/core/decoder_buffer.h" -#include "draco/core/encoder_buffer.h" - -#include "draco/core/draco_test_base.h" - -namespace draco { - -class BufferBitCodingTest : public ::testing::Test { - public: - typedef DecoderBuffer::BitDecoder BitDecoder; - typedef EncoderBuffer::BitEncoder BitEncoder; -}; - -TEST_F(BufferBitCodingTest, TestBitCodersByteAligned) { - constexpr int buffer_size = 32; - char buffer[buffer_size]; - BitEncoder encoder(buffer); - const uint8_t data[] = {0x76, 0x54, 0x32, 0x10, 0x76, 0x54, 0x32, 0x10}; - const int bytes_to_encode = sizeof(data); - - for (int i = 0; i < bytes_to_encode; ++i) { - encoder.PutBits(data[i], sizeof(data[i]) * 8); - ASSERT_EQ((i + 1) * sizeof(data[i]) * 8, encoder.Bits()); - } - - BitDecoder decoder; - decoder.reset(static_cast<const void *>(buffer), bytes_to_encode); - for (int i = 0; i < bytes_to_encode; ++i) { - uint32_t x = 0; - ASSERT_TRUE(decoder.GetBits(8, &x)); - ASSERT_EQ(x, data[i]); - } - - ASSERT_EQ(bytes_to_encode * 8u, decoder.BitsDecoded()); -} - -TEST_F(BufferBitCodingTest, TestBitCodersNonByte) { - constexpr int buffer_size = 32; - char buffer[buffer_size]; - BitEncoder encoder(buffer); - const uint8_t data[] = {0x76, 0x54, 0x32, 0x10, 0x76, 0x54, 0x32, 0x10}; - const uint32_t bits_to_encode = 51; - const int bytes_to_encode = (bits_to_encode / 8) + 1; - - for (int i = 0; i < bytes_to_encode; ++i) { - const int num_bits = (encoder.Bits() + 8 <= bits_to_encode) - ? 8 - : bits_to_encode - encoder.Bits(); - encoder.PutBits(data[i], num_bits); - } - - BitDecoder decoder; - decoder.reset(static_cast<const void *>(buffer), bytes_to_encode); - int64_t bits_to_decode = encoder.Bits(); - for (int i = 0; i < bytes_to_encode; ++i) { - uint32_t x = 0; - const int num_bits = (bits_to_decode > 8) ? 8 : bits_to_decode; - ASSERT_TRUE(decoder.GetBits(num_bits, &x)); - const int bits_to_shift = 8 - num_bits; - const uint8_t test_byte = - ((data[i] << bits_to_shift) & 0xff) >> bits_to_shift; - ASSERT_EQ(x, test_byte); - bits_to_decode -= 8; - } - - ASSERT_EQ(bits_to_encode, decoder.BitsDecoded()); -} - -TEST_F(BufferBitCodingTest, TestSingleBits) { - const int data = 0xaaaa; - - BitDecoder decoder; - decoder.reset(static_cast<const void *>(&data), sizeof(data)); - - for (uint32_t i = 0; i < 16; ++i) { - uint32_t x = 0; - ASSERT_TRUE(decoder.GetBits(1, &x)); - ASSERT_EQ(x, (i % 2)); - } - - ASSERT_EQ(16u, decoder.BitsDecoded()); -} - -TEST_F(BufferBitCodingTest, TestMultipleBits) { - const uint8_t data[] = {0x76, 0x54, 0x32, 0x10, 0x76, 0x54, 0x32, 0x10}; - - BitDecoder decoder; - decoder.reset(static_cast<const void *>(data), sizeof(data)); - - uint32_t x = 0; - for (uint32_t i = 0; i < 2; ++i) { - ASSERT_TRUE(decoder.GetBits(16, &x)); - ASSERT_EQ(x, 0x5476u); - ASSERT_EQ(16 + (i * 32), decoder.BitsDecoded()); - - ASSERT_TRUE(decoder.GetBits(16, &x)); - ASSERT_EQ(x, 0x1032u); - ASSERT_EQ(32 + (i * 32), decoder.BitsDecoded()); - } -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/core/draco_test_base.h b/extern/draco/dracoenc/src/draco/core/draco_test_base.h deleted file mode 100644 index f5c9d751e03..00000000000 --- a/extern/draco/dracoenc/src/draco/core/draco_test_base.h +++ /dev/null @@ -1,11 +0,0 @@ -// Wrapper for including googletest indirectly. Useful when the location of the -// googletest sources must change depending on build environment and repository -// source location. -#ifndef DRACO_CORE_DRACO_TEST_BASE_H_ -#define DRACO_CORE_DRACO_TEST_BASE_H_ - -static bool FLAGS_update_golden_files; -#include "gtest/gtest.h" -#include "testing/draco_test_config.h" - -#endif // DRACO_CORE_DRACO_TEST_BASE_H_ diff --git a/extern/draco/dracoenc/src/draco/core/draco_test_utils.cc b/extern/draco/dracoenc/src/draco/core/draco_test_utils.cc deleted file mode 100644 index a39e19f6b15..00000000000 --- a/extern/draco/dracoenc/src/draco/core/draco_test_utils.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/core/draco_test_utils.h" - -#include <fstream> - -#include "draco/core/macros.h" -#include "draco_test_base.h" - -namespace draco { - -namespace { -static constexpr char kTestDataDir[] = DRACO_TEST_DATA_DIR; -static constexpr char kTestTempDir[] = DRACO_TEST_TEMP_DIR; -} // namespace - -std::string GetTestFileFullPath(const std::string &file_name) { - return std::string(kTestDataDir) + std::string("/") + file_name; -} - -std::string GetTestTempFileFullPath(const std::string &file_name) { - return std::string(kTestTempDir) + std::string("/") + file_name; -} - -bool GenerateGoldenFile(const std::string &golden_file_name, const void *data, - int data_size) { - const std::string path = GetTestFileFullPath(golden_file_name); - std::ofstream file(path, std::ios::binary); - if (!file) - return false; - file.write(static_cast<const char *>(data), data_size); - file.close(); - return true; -} - -bool CompareGoldenFile(const std::string &golden_file_name, const void *data, - int data_size) { - const std::string golden_path = GetTestFileFullPath(golden_file_name); - std::ifstream in_file(golden_path, std::ios::binary); - if (!in_file || data_size < 0) - return false; - const char *const data_c8 = static_cast<const char *>(data); - constexpr int buffer_size = 1024; - char buffer[buffer_size]; - size_t extracted_size = 0; - size_t remaining_data_size = data_size; - int offset = 0; - while ((extracted_size = in_file.read(buffer, buffer_size).gcount()) > 0) { - if (remaining_data_size <= 0) - break; // Input and golden sizes are different. - size_t size_to_check = extracted_size; - if (remaining_data_size < size_to_check) - size_to_check = remaining_data_size; - for (uint32_t i = 0; i < size_to_check; ++i) { - if (buffer[i] != data_c8[offset++]) { - LOG(INFO) << "Test output differed from golden file at byte " - << offset - 1; - return false; - } - } - remaining_data_size -= extracted_size; - } - if (remaining_data_size != extracted_size) { - // Both of these values should be 0 at the end. - LOG(INFO) << "Test output size differed from golden file size"; - return false; - } - return true; -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/core/draco_test_utils.h b/extern/draco/dracoenc/src/draco/core/draco_test_utils.h deleted file mode 100644 index 3113a5d2676..00000000000 --- a/extern/draco/dracoenc/src/draco/core/draco_test_utils.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_CORE_DRACO_TEST_UTILS_H_ -#define DRACO_CORE_DRACO_TEST_UTILS_H_ - -#include "draco/core/draco_test_base.h" -#include "draco/io/mesh_io.h" -#include "draco/io/point_cloud_io.h" - -namespace draco { - -// Returns the full path to a given file system entry, such as test file or test -// directory. -std::string GetTestFileFullPath(const std::string &entry_name); - -// Returns the full path to a given temporary file (a location where tests store -// generated files). -std::string GetTestTempFileFullPath(const std::string &file_name); - -// Generates a new golden file and saves it into the correct folder. -// Returns false if the file couldn't be created. -bool GenerateGoldenFile(const std::string &golden_file_name, const void *data, - int data_size); - -// Compare a golden file content with the input data. -// Function will log the first byte position where the data differ. -// Returns false if there are any differences. -bool CompareGoldenFile(const std::string &golden_file_name, const void *data, - int data_size); - -// Loads a mesh / point cloud specified by a |file_name| that is going to be -// automatically converted to the correct path available to the testing -// instance. -inline std::unique_ptr<Mesh> ReadMeshFromTestFile( - const std::string &file_name) { - const std::string path = GetTestFileFullPath(file_name); - return ReadMeshFromFile(path).value(); -} -inline std::unique_ptr<Mesh> ReadMeshFromTestFile(const std::string &file_name, - bool use_metadata) { - const std::string path = GetTestFileFullPath(file_name); - return ReadMeshFromFile(path, use_metadata).value(); -} -inline std::unique_ptr<Mesh> ReadMeshFromTestFile(const std::string &file_name, - const Options &options) { - const std::string path = GetTestFileFullPath(file_name); - return ReadMeshFromFile(path, options).value(); -} - -inline std::unique_ptr<PointCloud> ReadPointCloudFromTestFile( - const std::string &file_name) { - const std::string path = GetTestFileFullPath(file_name); - return ReadPointCloudFromFile(path).value(); -} - -} // namespace draco - -#endif // DRACO_CORE_DRACO_TEST_UTILS_H_ diff --git a/extern/draco/dracoenc/src/draco/core/draco_tests.cc b/extern/draco/dracoenc/src/draco/core/draco_tests.cc deleted file mode 100644 index fdaa14da508..00000000000 --- a/extern/draco/dracoenc/src/draco/core/draco_tests.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "draco/core/draco_test_base.h" - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/extern/draco/dracoenc/src/draco/core/math_utils_test.cc b/extern/draco/dracoenc/src/draco/core/math_utils_test.cc deleted file mode 100644 index 8c255d04680..00000000000 --- a/extern/draco/dracoenc/src/draco/core/math_utils_test.cc +++ /dev/null @@ -1,22 +0,0 @@ -#include "draco/core/math_utils.h" - -#include <cmath> -#include <random> - -#include "draco/core/draco_test_base.h" - -using draco::Vector3f; - -TEST(MathUtils, Mod) { EXPECT_EQ(DRACO_INCREMENT_MOD(1, 1 << 1), 0); } - -TEST(MathUtils, IntSqrt) { - ASSERT_EQ(IntSqrt(0), 0); - // 64-bit pseudo random number generator seeded with a predefined number. - std::mt19937_64 generator(109); - std::uniform_int_distribution<uint64_t> distribution(0, 1ull << 60); - - for (int i = 0; i < 10000; ++i) { - const uint64_t number = distribution(generator); - ASSERT_EQ(IntSqrt(number), static_cast<uint64_t>(floor(std::sqrt(number)))); - } -} diff --git a/extern/draco/dracoenc/src/draco/core/quantization_utils_test.cc b/extern/draco/dracoenc/src/draco/core/quantization_utils_test.cc deleted file mode 100644 index b4f0473f204..00000000000 --- a/extern/draco/dracoenc/src/draco/core/quantization_utils_test.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/core/quantization_utils.h" - -#include "draco/core/draco_test_base.h" - -namespace draco { - -class QuantizationUtilsTest : public ::testing::Test {}; - -TEST_F(QuantizationUtilsTest, TestQuantizer) { - Quantizer quantizer; - quantizer.Init(10.f, 255); - EXPECT_EQ(quantizer.QuantizeFloat(0.f), 0); - EXPECT_EQ(quantizer.QuantizeFloat(10.f), 255); - EXPECT_EQ(quantizer.QuantizeFloat(-10.f), -255); - EXPECT_EQ(quantizer.QuantizeFloat(4.999f), 127); - EXPECT_EQ(quantizer.QuantizeFloat(5.f), 128); - EXPECT_EQ(quantizer.QuantizeFloat(-4.9999f), -127); - // Note: Both -5.f and +5.f lie exactly on the boundary between two - // quantized values (127.5f and -127.5f). Due to rounding, both values are - // then converted to 128 and -127 respectively. - EXPECT_EQ(quantizer.QuantizeFloat(-5.f), -127); - EXPECT_EQ(quantizer.QuantizeFloat(-5.0001f), -128); - - // Out of range quantization. - // The behavior is technically undefined, but both quantizer and dequantizer - // should still work correctly unless the quantized values overflow. - EXPECT_LT(quantizer.QuantizeFloat(-15.f), -255); - EXPECT_GT(quantizer.QuantizeFloat(15.f), 255); -} - -TEST_F(QuantizationUtilsTest, TestDequantizer) { - Dequantizer dequantizer; - ASSERT_TRUE(dequantizer.Init(10.f, 255)); - EXPECT_EQ(dequantizer.DequantizeFloat(0), 0.f); - EXPECT_EQ(dequantizer.DequantizeFloat(255), 10.f); - EXPECT_EQ(dequantizer.DequantizeFloat(-255), -10.f); - EXPECT_EQ(dequantizer.DequantizeFloat(128), 10.f * (128.f / 255.f)); - - // Test that the dequantizer fails to initialize with invalid input - // parameters. - ASSERT_FALSE(dequantizer.Init(1.f, 0)); - ASSERT_FALSE(dequantizer.Init(1.f, -4)); -} - -TEST_F(QuantizationUtilsTest, TestDeltaQuantization) { - // Test verifies that the quantizer and dequantizer work correctly when - // initialized with a delta value. - Quantizer quantizer_delta; - quantizer_delta.Init(0.5f); - - Quantizer quantizer_range; - quantizer_range.Init(50.f, 100); - - EXPECT_EQ(quantizer_delta.QuantizeFloat(1.2f), 2); - EXPECT_EQ(quantizer_delta.QuantizeFloat(10.f), - quantizer_range.QuantizeFloat(10.f)); - EXPECT_EQ(quantizer_delta.QuantizeFloat(-3.3f), - quantizer_range.QuantizeFloat(-3.3f)); - EXPECT_EQ(quantizer_delta.QuantizeFloat(0.25f), - quantizer_range.QuantizeFloat(0.25f)); - - Dequantizer dequantizer_delta; - dequantizer_delta.Init(0.5f); - - Dequantizer dequantizer_range; - dequantizer_range.Init(50.f, 100); - - EXPECT_EQ(dequantizer_delta.DequantizeFloat(2), 1.f); - EXPECT_EQ(dequantizer_delta.DequantizeFloat(-4), - dequantizer_range.DequantizeFloat(-4)); - EXPECT_EQ(dequantizer_delta.DequantizeFloat(9), - dequantizer_range.DequantizeFloat(9)); - EXPECT_EQ(dequantizer_delta.DequantizeFloat(0), - dequantizer_range.DequantizeFloat(0)); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/core/status_test.cc b/extern/draco/dracoenc/src/draco/core/status_test.cc deleted file mode 100644 index c1ad4ab30f4..00000000000 --- a/extern/draco/dracoenc/src/draco/core/status_test.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/core/status.h" - -#include <sstream> - -#include "draco/core/draco_test_base.h" - -namespace { - -class StatusTest : public ::testing::Test { - protected: - StatusTest() {} -}; - -TEST_F(StatusTest, TestStatusOutput) { - // Tests that the Status can be stored in a provided std::ostream. - const draco::Status status(draco::Status::DRACO_ERROR, "Error msg."); - ASSERT_EQ(status.code(), draco::Status::DRACO_ERROR); - - std::stringstream str; - str << status; - ASSERT_EQ(str.str(), "Error msg."); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/core/statusor.h b/extern/draco/dracoenc/src/draco/core/statusor.h deleted file mode 100644 index 7fa42098442..00000000000 --- a/extern/draco/dracoenc/src/draco/core/statusor.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_CORE_STATUSOR_H_ -#define DRACO_CORE_STATUSOR_H_ - -#include "draco/core/macros.h" -#include "draco/core/status.h" - -namespace draco { - -// Class StatusOr is used to wrap a Status along with a value of a specified -// type |T|. StatusOr is intended to be returned from functions in situations -// where it is desirable to carry over more information about the potential -// errors encountered during the function execution. If there are not errors, -// the caller can simply use the return value, otherwise the Status object -// provides more info about the encountered problem. -template <class T> -class StatusOr { - public: - StatusOr() {} - // Note: Constructors are intentionally not explicit to allow returning - // Status or the return value directly from functions. - StatusOr(const StatusOr &) = default; - StatusOr(StatusOr &&) = default; - StatusOr(const Status &status) : status_(status) {} - StatusOr(const T &value) : status_(OkStatus()), value_(value) {} - StatusOr(T &&value) : status_(OkStatus()), value_(std::move(value)) {} - StatusOr(const Status &status, const T &value) - : status_(status), value_(value) {} - - const Status &status() const { return status_; } - const T &value() const & { return value_; } - const T &&value() const && { return std::move(value_); } - T &&value() && { return std::move(value_); } - - // For consistency with existing Google StatusOr API we also include - // ValueOrDie() that currently returns the value(). - const T &ValueOrDie() const & { return value(); } - T &&ValueOrDie() && { return std::move(value()); } - - bool ok() const { return status_.ok(); } - - private: - Status status_; - T value_; -}; - -// In case StatusOr<T> is ok(), this macro assigns value stored in StatusOr<T> -// to |lhs|, otherwise it returns the error Status. -// -// DRACO_ASSIGN_OR_RETURN(lhs, expression) -// -#define DRACO_ASSIGN_OR_RETURN(lhs, expression) \ - DRACO_ASSIGN_OR_RETURN_IMPL_(DRACO_MACROS_IMPL_CONCAT_(_statusor, __LINE__), \ - lhs, expression, _status) - -// The actual implementation of the above macro. -#define DRACO_ASSIGN_OR_RETURN_IMPL_(statusor, lhs, expression, error_expr) \ - auto statusor = (expression); \ - if (!statusor.ok()) { \ - auto _status = std::move(statusor.status()); \ - (void)_status; /* error_expression may not use it */ \ - return error_expr; \ - } \ - lhs = std::move(statusor).value(); - -} // namespace draco - -#endif // DRACO_CORE_STATUSOR_H_ diff --git a/extern/draco/dracoenc/src/draco/core/vector_d_test.cc b/extern/draco/dracoenc/src/draco/core/vector_d_test.cc deleted file mode 100644 index bc2bdadaa9f..00000000000 --- a/extern/draco/dracoenc/src/draco/core/vector_d_test.cc +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/core/vector_d.h" - -#include <sstream> - -#include "draco/core/draco_test_base.h" - -namespace { - -typedef draco::Vector2f Vector2f; -typedef draco::Vector3f Vector3f; -typedef draco::Vector4f Vector4f; -typedef draco::Vector5f Vector5f; -typedef draco::Vector2ui Vector2ui; -typedef draco::Vector3ui Vector3ui; -typedef draco::Vector4ui Vector4ui; -typedef draco::Vector5ui Vector5ui; - -typedef draco::VectorD<int32_t, 3> Vector3i; -typedef draco::VectorD<int32_t, 4> Vector4i; - -template <class CoeffT, int dimension_t> -void TestSquaredDistance(const draco::VectorD<CoeffT, dimension_t> v1, - const draco::VectorD<CoeffT, dimension_t> v2, - const CoeffT result) { - CoeffT squared_distance = SquaredDistance(v1, v2); - ASSERT_EQ(squared_distance, result); - squared_distance = SquaredDistance(v2, v1); - ASSERT_EQ(squared_distance, result); -} - -TEST(VectorDTest, TestOperators) { - { - const Vector3f v; - ASSERT_EQ(v[0], 0); - ASSERT_EQ(v[1], 0); - ASSERT_EQ(v[2], 0); - } - Vector3f v(1, 2, 3); - ASSERT_EQ(v[0], 1); - ASSERT_EQ(v[1], 2); - ASSERT_EQ(v[2], 3); - - Vector3f w = v; - ASSERT_TRUE(v == w); - ASSERT_FALSE(v != w); - ASSERT_EQ(w[0], 1); - ASSERT_EQ(w[1], 2); - ASSERT_EQ(w[2], 3); - - w = -v; - ASSERT_EQ(w[0], -1); - ASSERT_EQ(w[1], -2); - ASSERT_EQ(w[2], -3); - - w = v + v; - ASSERT_EQ(w[0], 2); - ASSERT_EQ(w[1], 4); - ASSERT_EQ(w[2], 6); - - w = w - v; - ASSERT_EQ(w[0], 1); - ASSERT_EQ(w[1], 2); - ASSERT_EQ(w[2], 3); - - // Scalar multiplication from left and right. - w = v * 2.f; - ASSERT_EQ(w[0], 2); - ASSERT_EQ(w[1], 4); - ASSERT_EQ(w[2], 6); - w = 2.f * v; - ASSERT_EQ(w[0], 2); - ASSERT_EQ(w[1], 4); - ASSERT_EQ(w[2], 6); - - ASSERT_EQ(v.SquaredNorm(), 14); - ASSERT_EQ(v.Dot(v), 14); - - Vector3f new_v = v; - new_v.Normalize(); - const float eps = 0.001; - const float magnitude = std::sqrt(v.SquaredNorm()); - const float new_magnitude = std::sqrt(new_v.SquaredNorm()); - ASSERT_LE(new_magnitude, 1 + eps); - ASSERT_GE(new_magnitude, 1 - eps); - for (int i = 0; i < 3; ++i) { - new_v[i] *= magnitude; - ASSERT_LE(new_v[i], v[i] + eps); - ASSERT_GE(new_v[i], v[i] - eps); - } - - Vector3f x(0, 0, 0); - x.Normalize(); - for (int i = 0; i < 3; ++i) { - ASSERT_EQ(0, x[i]); - } -} - -TEST(VectorDTest, TestSquaredDistance) { - // Test Vector2f: float, 2D. - Vector2f v1_2f(5.5, 10.5); - Vector2f v2_2f(3.5, 15.5); - float result_f = 29; - TestSquaredDistance(v1_2f, v2_2f, result_f); - - // Test Vector3f: float, 3D. - Vector3f v1_3f(5.5, 10.5, 2.3); - Vector3f v2_3f(3.5, 15.5, 0); - result_f = 34.29; - TestSquaredDistance(v1_3f, v2_3f, result_f); - - // Test Vector4f: float, 4D. - Vector4f v1_4f(5.5, 10.5, 2.3, 7.2); - Vector4f v2_4f(3.5, 15.5, 0, 9.9); - result_f = 41.58; - TestSquaredDistance(v1_4f, v2_4f, result_f); - - // Test Vector5f: float, 5D. - Vector5f v1_5f(5.5, 10.5, 2.3, 7.2, 1.0); - Vector5f v2_5f(3.5, 15.5, 0, 9.9, 0.2); - result_f = 42.22; - TestSquaredDistance(v1_5f, v2_5f, result_f); - - // Test Vector 2ui: uint32_t, 2D. - Vector2ui v1_2ui(5, 10); - Vector2ui v2_2ui(3, 15); - uint32_t result_ui = 29; - TestSquaredDistance(v1_2ui, v2_2ui, result_ui); - - // Test Vector 3ui: uint32_t, 3D. - Vector3ui v1_3ui(5, 10, 2); - Vector3ui v2_3ui(3, 15, 0); - result_ui = 33; - TestSquaredDistance(v1_3ui, v2_3ui, result_ui); - - // Test Vector 4ui: uint32_t, 4D. - Vector4ui v1_4ui(5, 10, 2, 7); - Vector4ui v2_4ui(3, 15, 0, 9); - result_ui = 37; - TestSquaredDistance(v1_4ui, v2_4ui, result_ui); - - // Test Vector 5ui: uint32_t, 5D. - Vector5ui v1_5ui(5, 10, 2, 7, 1); - Vector5ui v2_5ui(3, 15, 0, 9, 12); - result_ui = 158; - TestSquaredDistance(v1_5ui, v2_5ui, result_ui); -} - -TEST(VectorDTest, TestCrossProduct3D) { - const Vector3i e1(1, 0, 0); - const Vector3i e2(0, 1, 0); - const Vector3i e3(0, 0, 1); - const Vector3i o(0, 0, 0); - ASSERT_EQ(e3, draco::CrossProduct(e1, e2)); - ASSERT_EQ(e1, draco::CrossProduct(e2, e3)); - ASSERT_EQ(e2, draco::CrossProduct(e3, e1)); - ASSERT_EQ(-e3, draco::CrossProduct(e2, e1)); - ASSERT_EQ(-e1, draco::CrossProduct(e3, e2)); - ASSERT_EQ(-e2, draco::CrossProduct(e1, e3)); - ASSERT_EQ(o, draco::CrossProduct(e1, e1)); - ASSERT_EQ(o, draco::CrossProduct(e2, e2)); - ASSERT_EQ(o, draco::CrossProduct(e3, e3)); - - // Orthogonality of result for some general vectors. - const Vector3i v1(123, -62, 223); - const Vector3i v2(734, 244, -13); - const Vector3i orth = draco::CrossProduct(v1, v2); - ASSERT_EQ(0, v1.Dot(orth)); - ASSERT_EQ(0, v2.Dot(orth)); -} - -TEST(VectorDTest, TestAbsSum) { - // Testing const of function and zero. - const Vector3i v(0, 0, 0); - ASSERT_EQ(v.AbsSum(), 0); - // Testing semantic. - ASSERT_EQ(Vector3i(0, 0, 0).AbsSum(), 0); - ASSERT_EQ(Vector3i(1, 2, 3).AbsSum(), 6); - ASSERT_EQ(Vector3i(-1, -2, -3).AbsSum(), 6); - ASSERT_EQ(Vector3i(-2, 4, -8).AbsSum(), 14); - // Other dimension. - ASSERT_EQ(Vector4i(-2, 4, -8, 3).AbsSum(), 17); -} - -TEST(VectorDTest, TestMinMaxCoeff) { - // Test verifies that MinCoeff() and MaxCoeff() functions work as intended. - const Vector4i vi(-10, 5, 2, 3); - ASSERT_EQ(vi.MinCoeff(), -10); - ASSERT_EQ(vi.MaxCoeff(), 5); - - const Vector3f vf(6.f, 1000.f, -101.f); - ASSERT_EQ(vf.MinCoeff(), -101.f); - ASSERT_EQ(vf.MaxCoeff(), 1000.f); -} - -TEST(VectorDTest, TestOstream) { - // Tests that the vector can be stored in a provided std::ostream. - const draco::VectorD<int64_t, 3> vector(1, 2, 3); - std::stringstream str; - str << vector << " "; - ASSERT_EQ(str.str(), "1 2 3 "); -} - -TEST(VectorDTest, TestConvertConstructor) { - // Tests that a vector can be constructed from another vector with a different - // type. - const draco::VectorD<int64_t, 3> vector(1, 2, 3); - - const draco::VectorD<float, 3> vector3f(vector); - ASSERT_EQ(vector3f, draco::Vector3f(1.f, 2.f, 3.f)); - - const draco::VectorD<float, 2> vector2f(vector); - ASSERT_EQ(vector2f, draco::Vector2f(1.f, 2.f)); - - const draco::VectorD<float, 4> vector4f(vector3f); - ASSERT_EQ(vector4f, draco::Vector4f(1.f, 2.f, 3.f, 0.f)); - - const draco::VectorD<double, 1> vector1d(vector3f); - ASSERT_EQ(vector1d[0], 1.0); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/draco_features.h b/extern/draco/dracoenc/src/draco/draco_features.h deleted file mode 100644 index f067ca44dd0..00000000000 --- a/extern/draco/dracoenc/src/draco/draco_features.h +++ /dev/null @@ -1,8 +0,0 @@ -// GENERATED FILE -- DO NOT EDIT - -#ifndef DRACO_FEATURES_H_ -#define DRACO_FEATURES_H_ - -#define DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED - -#endif // DRACO_FEATURES_H_
\ No newline at end of file diff --git a/extern/draco/dracoenc/src/draco/io/mesh_io.cc b/extern/draco/dracoenc/src/draco/io/mesh_io.cc deleted file mode 100644 index 5e2f9f51d7a..00000000000 --- a/extern/draco/dracoenc/src/draco/io/mesh_io.cc +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/mesh_io.h" - -#include <fstream> - -#include "draco/io/file_utils.h" -#include "draco/io/obj_decoder.h" -#include "draco/io/ply_decoder.h" - -namespace draco { - -StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name) { - const Options options; - return ReadMeshFromFile(file_name, options); -} - -StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name, - bool use_metadata) { - Options options; - options.SetBool("use_metadata", use_metadata); - return ReadMeshFromFile(file_name, options); -} - -StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name, - const Options &options) { - std::unique_ptr<Mesh> mesh(new Mesh()); - // Analyze file extension. - const std::string extension = LowercaseFileExtension(file_name); - if (extension == "obj") { - // Wavefront OBJ file format. - ObjDecoder obj_decoder; - obj_decoder.set_use_metadata(options.GetBool("use_metadata", false)); - const Status obj_status = obj_decoder.DecodeFromFile(file_name, mesh.get()); - if (!obj_status.ok()) - return obj_status; - return std::move(mesh); - } - if (extension == "ply") { - // Wavefront PLY file format. - PlyDecoder ply_decoder; - DRACO_RETURN_IF_ERROR(ply_decoder.DecodeFromFile(file_name, mesh.get())); - return std::move(mesh); - } - - // Otherwise not an obj file. Assume the file was encoded with one of the - // draco encoding methods. - std::ifstream is(file_name.c_str(), std::ios::binary); - if (!is) - return Status(Status::DRACO_ERROR, "Invalid input stream."); - if (!ReadMeshFromStream(&mesh, is).good()) - return Status(Status::DRACO_ERROR, - "Unknown error."); // Error reading the stream. - return std::move(mesh); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/mesh_io.h b/extern/draco/dracoenc/src/draco/io/mesh_io.h deleted file mode 100644 index 15cfbb30b97..00000000000 --- a/extern/draco/dracoenc/src/draco/io/mesh_io.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_MESH_MESH_IO_H_ -#define DRACO_MESH_MESH_IO_H_ - -#include "draco/compression/config/compression_shared.h" -#include "draco/compression/decode.h" -#include "draco/compression/expert_encode.h" -#include "draco/core/options.h" - -namespace draco { - -template <typename OutStreamT> -OutStreamT WriteMeshIntoStream(const Mesh *mesh, OutStreamT &&os, - MeshEncoderMethod method, - const EncoderOptions &options) { - EncoderBuffer buffer; - EncoderOptions local_options = options; - ExpertEncoder encoder(*mesh); - encoder.Reset(local_options); - encoder.SetEncodingMethod(method); - if (!encoder.EncodeToBuffer(&buffer).ok()) { - os.setstate(std::ios_base::badbit); - return os; - } - - os.write(static_cast<const char *>(buffer.data()), buffer.size()); - - return os; -} - -template <typename OutStreamT> -OutStreamT WriteMeshIntoStream(const Mesh *mesh, OutStreamT &&os, - MeshEncoderMethod method) { - const EncoderOptions options = EncoderOptions::CreateDefaultOptions(); - return WriteMeshIntoStream(mesh, os, method, options); -} - -template <typename OutStreamT> -OutStreamT &WriteMeshIntoStream(const Mesh *mesh, OutStreamT &&os) { - return WriteMeshIntoStream(mesh, os, MESH_EDGEBREAKER_ENCODING); -} - -template <typename InStreamT> -InStreamT &ReadMeshFromStream(std::unique_ptr<Mesh> *mesh, InStreamT &&is) { - // Determine size of stream and write into a vector - const auto start_pos = is.tellg(); - is.seekg(0, std::ios::end); - const std::streampos is_size = is.tellg() - start_pos; - is.seekg(start_pos); - std::vector<char> data(is_size); - is.read(&data[0], is_size); - - // Create a mesh from that data. - DecoderBuffer buffer; - buffer.Init(&data[0], data.size()); - Decoder decoder; - auto statusor = decoder.DecodeMeshFromBuffer(&buffer); - *mesh = std::move(statusor).value(); - if (!statusor.ok() || *mesh == nullptr) { - is.setstate(std::ios_base::badbit); - } - - return is; -} - -// Reads a mesh from a file. The function automatically chooses the correct -// decoder based on the extension of the files. Currently, .obj and .ply files -// are supported. Other file extensions are processed by the default -// draco::MeshDecoder. -// Returns nullptr with an error status if the decoding failed. -StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name); - -// Reads a mesh from a file. The function does the same thing as the previous -// one except using metadata to encode additional information when -// |use_metadata| is set to true. -// Returns nullptr with an error status if the decoding failed. -StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name, - bool use_metadata); - -// Reads a mesh from a file. Reading is configured with |options|: -// use_metadata : Read obj file info like material names and object names into -// metadata. Default is false. -// Returns nullptr with an error status if the decoding failed. -StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name, - const Options &options); - -} // namespace draco - -#endif // DRACO_MESH_MESH_IO_H_ diff --git a/extern/draco/dracoenc/src/draco/io/obj_decoder.cc b/extern/draco/dracoenc/src/draco/io/obj_decoder.cc deleted file mode 100644 index 88f470f8b4a..00000000000 --- a/extern/draco/dracoenc/src/draco/io/obj_decoder.cc +++ /dev/null @@ -1,689 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/obj_decoder.h" - -#include <cctype> -#include <cmath> -#include <fstream> - -#include "draco/io/file_utils.h" -#include "draco/io/parser_utils.h" -#include "draco/metadata/geometry_metadata.h" - -namespace draco { - -ObjDecoder::ObjDecoder() - : counting_mode_(true), - num_obj_faces_(0), - num_positions_(0), - num_tex_coords_(0), - num_normals_(0), - num_materials_(0), - last_sub_obj_id_(0), - pos_att_id_(-1), - tex_att_id_(-1), - norm_att_id_(-1), - material_att_id_(-1), - sub_obj_att_id_(-1), - deduplicate_input_values_(true), - last_material_id_(0), - use_metadata_(false), - out_mesh_(nullptr), - out_point_cloud_(nullptr) {} - -Status ObjDecoder::DecodeFromFile(const std::string &file_name, - Mesh *out_mesh) { - out_mesh_ = out_mesh; - return DecodeFromFile(file_name, static_cast<PointCloud *>(out_mesh)); -} - -Status ObjDecoder::DecodeFromFile(const std::string &file_name, - PointCloud *out_point_cloud) { - std::ifstream file(file_name, std::ios::binary); - if (!file) - return Status(Status::IO_ERROR); - // Read the whole file into a buffer. - auto pos0 = file.tellg(); - file.seekg(0, std::ios::end); - auto file_size = file.tellg() - pos0; - if (file_size == 0) - return Status(Status::IO_ERROR); - file.seekg(0, std::ios::beg); - std::vector<char> data(file_size); - file.read(&data[0], file_size); - buffer_.Init(&data[0], file_size); - - out_point_cloud_ = out_point_cloud; - input_file_name_ = file_name; - return DecodeInternal(); -} - -Status ObjDecoder::DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh) { - out_mesh_ = out_mesh; - return DecodeFromBuffer(buffer, static_cast<PointCloud *>(out_mesh)); -} - -Status ObjDecoder::DecodeFromBuffer(DecoderBuffer *buffer, - PointCloud *out_point_cloud) { - out_point_cloud_ = out_point_cloud; - buffer_.Init(buffer->data_head(), buffer->remaining_size()); - return DecodeInternal(); -} - -Status ObjDecoder::DecodeInternal() { - // In the first pass, count the number of different elements in the geometry. - // In case the desired output is just a point cloud (i.e., when - // out_mesh_ == nullptr) the decoder will ignore all information about the - // connectivity that may be included in the source data. - counting_mode_ = true; - ResetCounters(); - material_name_to_id_.clear(); - last_sub_obj_id_ = 0; - // Parse all lines. - Status status(Status::OK); - while (ParseDefinition(&status) && status.ok()) { - } - if (!status.ok()) - return status; - bool use_identity_mapping = false; - if (num_obj_faces_ == 0) { - // Mesh has no faces. In this case we try to read the geometry as a point - // cloud where every attribute entry is a point. - - // Ensure the number of all entries is same for all attributes. - if (num_positions_ == 0) - return Status(Status::DRACO_ERROR, "No position attribute"); - if (num_tex_coords_ > 0 && num_tex_coords_ != num_positions_) - return Status(Status::DRACO_ERROR, - "Invalid number of texture coordinates for a point cloud"); - if (num_normals_ > 0 && num_normals_ != num_positions_) - return Status(Status::DRACO_ERROR, - "Invalid number of normals for a point cloud"); - - out_mesh_ = nullptr; // Treat the output geometry as a point cloud. - use_identity_mapping = true; - } - - // Initialize point cloud and mesh properties. - if (out_mesh_) { - // Start decoding a mesh with the given number of faces. For point clouds we - // silently ignore all data about the mesh connectivity. - out_mesh_->SetNumFaces(num_obj_faces_); - } - if (num_obj_faces_ > 0) { - out_point_cloud_->set_num_points(3 * num_obj_faces_); - } else { - out_point_cloud_->set_num_points(num_positions_); - } - - // Add attributes if they are present in the input data. - if (num_positions_ > 0) { - GeometryAttribute va; - va.Init(GeometryAttribute::POSITION, nullptr, 3, DT_FLOAT32, false, - sizeof(float) * 3, 0); - pos_att_id_ = out_point_cloud_->AddAttribute(va, use_identity_mapping, - num_positions_); - } - if (num_tex_coords_ > 0) { - GeometryAttribute va; - va.Init(GeometryAttribute::TEX_COORD, nullptr, 2, DT_FLOAT32, false, - sizeof(float) * 2, 0); - tex_att_id_ = out_point_cloud_->AddAttribute(va, use_identity_mapping, - num_tex_coords_); - } - if (num_normals_ > 0) { - GeometryAttribute va; - va.Init(GeometryAttribute::NORMAL, nullptr, 3, DT_FLOAT32, false, - sizeof(float) * 3, 0); - norm_att_id_ = - out_point_cloud_->AddAttribute(va, use_identity_mapping, num_normals_); - } - if (num_materials_ > 0 && num_obj_faces_ > 0) { - GeometryAttribute va; - const auto geometry_attribute_type = GeometryAttribute::GENERIC; - if (num_materials_ < 256) { - va.Init(geometry_attribute_type, nullptr, 1, DT_UINT8, false, 1, 0); - } else if (num_materials_ < (1 << 16)) { - va.Init(geometry_attribute_type, nullptr, 1, DT_UINT16, false, 2, 0); - } else { - va.Init(geometry_attribute_type, nullptr, 1, DT_UINT32, false, 4, 0); - } - material_att_id_ = - out_point_cloud_->AddAttribute(va, false, num_materials_); - - // Fill the material entries. - for (int i = 0; i < num_materials_; ++i) { - const AttributeValueIndex avi(i); - out_point_cloud_->attribute(material_att_id_)->SetAttributeValue(avi, &i); - } - - if (use_metadata_) { - // Use metadata to store the name of materials. - std::unique_ptr<AttributeMetadata> material_metadata = - std::unique_ptr<AttributeMetadata>(new AttributeMetadata()); - material_metadata->AddEntryString("name", "material"); - // Add all material names. - for (const auto &itr : material_name_to_id_) { - material_metadata->AddEntryInt(itr.first, itr.second); - } - if (!material_file_name_.empty()) { - material_metadata->AddEntryString("file_name", material_file_name_); - } - - out_point_cloud_->AddAttributeMetadata(material_att_id_, - std::move(material_metadata)); - } - } - if (!obj_name_to_id_.empty() && num_obj_faces_ > 0) { - GeometryAttribute va; - if (obj_name_to_id_.size() < 256) { - va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT8, false, 1, 0); - } else if (obj_name_to_id_.size() < (1 << 16)) { - va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT16, false, 2, 0); - } else { - va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT32, false, 4, 0); - } - sub_obj_att_id_ = out_point_cloud_->AddAttribute( - va, false, static_cast<uint32_t>(obj_name_to_id_.size())); - // Fill the sub object id entries. - for (const auto &itr : obj_name_to_id_) { - const AttributeValueIndex i(itr.second); - out_point_cloud_->attribute(sub_obj_att_id_)->SetAttributeValue(i, &i); - } - if (use_metadata_) { - // Use metadata to store the name of materials. - std::unique_ptr<AttributeMetadata> sub_obj_metadata = - std::unique_ptr<AttributeMetadata>(new AttributeMetadata()); - sub_obj_metadata->AddEntryString("name", "sub_obj"); - // Add all sub object names. - for (const auto &itr : obj_name_to_id_) { - const AttributeValueIndex i(itr.second); - sub_obj_metadata->AddEntryInt(itr.first, itr.second); - } - out_point_cloud_->AddAttributeMetadata(sub_obj_att_id_, - std::move(sub_obj_metadata)); - } - } - - // Perform a second iteration of parsing and fill all the data. - counting_mode_ = false; - ResetCounters(); - // Start parsing from the beginning of the buffer again. - buffer()->StartDecodingFrom(0); - while (ParseDefinition(&status) && status.ok()) { - } - if (!status.ok()) - return status; - if (out_mesh_) { - // Add faces with identity mapping between vertex and corner indices. - // Duplicate vertices will get removed later. - Mesh::Face face; - for (FaceIndex i(0); i < num_obj_faces_; ++i) { - for (int c = 0; c < 3; ++c) - face[c] = 3 * i.value() + c; - out_mesh_->SetFace(i, face); - } - } - -#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED - if (deduplicate_input_values_) { - out_point_cloud_->DeduplicateAttributeValues(); - } -#endif -#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED - out_point_cloud_->DeduplicatePointIds(); -#endif - return status; -} - -void ObjDecoder::ResetCounters() { - num_obj_faces_ = 0; - num_positions_ = 0; - num_tex_coords_ = 0; - num_normals_ = 0; - last_material_id_ = 0; - last_sub_obj_id_ = 0; -} - -bool ObjDecoder::ParseDefinition(Status *status) { - char c; - parser::SkipWhitespace(buffer()); - if (!buffer()->Peek(&c)) { - // End of file reached?. - return false; - } - if (c == '#') { - // Comment, ignore the line. - parser::SkipLine(buffer()); - return true; - } - if (ParseVertexPosition(status)) - return true; - if (ParseNormal(status)) - return true; - if (ParseTexCoord(status)) - return true; - if (ParseFace(status)) - return true; - if (ParseMaterial(status)) - return true; - if (ParseMaterialLib(status)) - return true; - if (ParseObject(status)) - return true; - // No known definition was found. Ignore the line. - parser::SkipLine(buffer()); - return true; -} - -bool ObjDecoder::ParseVertexPosition(Status *status) { - std::array<char, 2> c; - if (!buffer()->Peek(&c)) { - return false; - } - if (c[0] != 'v' || c[1] != ' ') - return false; - // Vertex definition found! - buffer()->Advance(2); - if (!counting_mode_) { - // Parse three float numbers for vertex position coordinates. - float val[3]; - for (int i = 0; i < 3; ++i) { - parser::SkipWhitespace(buffer()); - if (!parser::ParseFloat(buffer(), val + i)) { - *status = Status(Status::DRACO_ERROR, "Failed to parse a float number"); - // The definition is processed so return true. - return true; - } - } - out_point_cloud_->attribute(pos_att_id_) - ->SetAttributeValue(AttributeValueIndex(num_positions_), val); - } - ++num_positions_; - parser::SkipLine(buffer()); - return true; -} - -bool ObjDecoder::ParseNormal(Status *status) { - std::array<char, 2> c; - if (!buffer()->Peek(&c)) { - return false; - } - if (c[0] != 'v' || c[1] != 'n') - return false; - // Normal definition found! - buffer()->Advance(2); - if (!counting_mode_) { - // Parse three float numbers for the normal vector. - float val[3]; - for (int i = 0; i < 3; ++i) { - parser::SkipWhitespace(buffer()); - if (!parser::ParseFloat(buffer(), val + i)) { - *status = Status(Status::DRACO_ERROR, "Failed to parse a float number"); - // The definition is processed so return true. - return true; - } - } - out_point_cloud_->attribute(norm_att_id_) - ->SetAttributeValue(AttributeValueIndex(num_normals_), val); - } - ++num_normals_; - parser::SkipLine(buffer()); - return true; -} - -bool ObjDecoder::ParseTexCoord(Status *status) { - std::array<char, 2> c; - if (!buffer()->Peek(&c)) { - return false; - } - if (c[0] != 'v' || c[1] != 't') - return false; - // Texture coord definition found! - buffer()->Advance(2); - if (!counting_mode_) { - // Parse two float numbers for the texture coordinate. - float val[2]; - for (int i = 0; i < 2; ++i) { - parser::SkipWhitespace(buffer()); - if (!parser::ParseFloat(buffer(), val + i)) { - *status = Status(Status::DRACO_ERROR, "Failed to parse a float number"); - // The definition is processed so return true. - return true; - } - } - out_point_cloud_->attribute(tex_att_id_) - ->SetAttributeValue(AttributeValueIndex(num_tex_coords_), val); - } - ++num_tex_coords_; - parser::SkipLine(buffer()); - return true; -} - -bool ObjDecoder::ParseFace(Status *status) { - char c; - if (!buffer()->Peek(&c)) { - return false; - } - if (c != 'f') - return false; - // Face definition found! - buffer()->Advance(1); - if (!counting_mode_) { - std::array<int32_t, 3> indices[4]; - // Parse face indices (we try to look for up to four to support quads). - int num_valid_indices = 0; - for (int i = 0; i < 4; ++i) { - if (!ParseVertexIndices(&indices[i])) { - if (i == 3) { - break; // It's OK if there is no fourth vertex index. - } - *status = Status(Status::DRACO_ERROR, "Failed to parse vertex indices"); - return true; - } - ++num_valid_indices; - } - // Process the first face. - for (int i = 0; i < 3; ++i) { - const PointIndex vert_id(3 * num_obj_faces_ + i); - MapPointToVertexIndices(vert_id, indices[i]); - } - ++num_obj_faces_; - if (num_valid_indices == 4) { - // Add an additional triangle for the quad. - // - // 3----2 - // | / | - // | / | - // 0----1 - // - const PointIndex vert_id(3 * num_obj_faces_); - MapPointToVertexIndices(vert_id, indices[0]); - MapPointToVertexIndices(vert_id + 1, indices[2]); - MapPointToVertexIndices(vert_id + 2, indices[3]); - ++num_obj_faces_; - } - } else { - // We are in the counting mode. - // We need to determine how many triangles are in the obj face. - // Go over the line and check how many gaps there are between non-empty - // sub-strings. - parser::SkipWhitespace(buffer()); - int num_indices = 0; - bool is_end = false; - while (buffer()->Peek(&c) && c != '\n') { - if (parser::PeekWhitespace(buffer(), &is_end)) { - buffer()->Advance(1); - } else { - // Non-whitespace reached.. assume it's index declaration, skip it. - num_indices++; - while (!parser::PeekWhitespace(buffer(), &is_end) && !is_end) { - buffer()->Advance(1); - } - } - } - if (num_indices < 3 || num_indices > 4) { - *status = - Status(Status::DRACO_ERROR, "Invalid number of indices on a face"); - return false; - } - // Either one or two new triangles. - num_obj_faces_ += num_indices - 2; - } - parser::SkipLine(buffer()); - return true; -} - -bool ObjDecoder::ParseMaterialLib(Status *status) { - // Allow only one material library per file for now. - if (material_name_to_id_.size() > 0) - return false; - std::array<char, 6> c; - if (!buffer()->Peek(&c)) { - return false; - } - if (std::memcmp(&c[0], "mtllib", 6) != 0) - return false; - buffer()->Advance(6); - DecoderBuffer line_buffer = parser::ParseLineIntoDecoderBuffer(buffer()); - parser::SkipWhitespace(&line_buffer); - material_file_name_.clear(); - if (!parser::ParseString(&line_buffer, &material_file_name_)) { - *status = Status(Status::DRACO_ERROR, "Failed to parse material file name"); - return true; - } - parser::SkipLine(&line_buffer); - - if (material_file_name_.size() > 0) { - if (!ParseMaterialFile(material_file_name_, status)) { - // Silently ignore problems with material files for now. - return true; - } - } - return true; -} - -bool ObjDecoder::ParseMaterial(Status * /* status */) { - // In second pass, skip when we don't use materials. - if (!counting_mode_ && material_att_id_ < 0) - return false; - std::array<char, 6> c; - if (!buffer()->Peek(&c)) { - return false; - } - if (std::memcmp(&c[0], "usemtl", 6) != 0) - return false; - buffer()->Advance(6); - DecoderBuffer line_buffer = parser::ParseLineIntoDecoderBuffer(buffer()); - parser::SkipWhitespace(&line_buffer); - std::string mat_name; - parser::ParseLine(&line_buffer, &mat_name); - if (mat_name.length() == 0) - return false; - auto it = material_name_to_id_.find(mat_name); - if (it == material_name_to_id_.end()) { - // In first pass, materials found in obj that's not in the .mtl file - // will be added to the list. - last_material_id_ = num_materials_; - material_name_to_id_[mat_name] = num_materials_++; - - return true; - } - last_material_id_ = it->second; - return true; -} - -bool ObjDecoder::ParseObject(Status *status) { - std::array<char, 2> c; - if (!buffer()->Peek(&c)) { - return false; - } - if (std::memcmp(&c[0], "o ", 2) != 0) - return false; - buffer()->Advance(1); - DecoderBuffer line_buffer = parser::ParseLineIntoDecoderBuffer(buffer()); - parser::SkipWhitespace(&line_buffer); - std::string obj_name; - if (!parser::ParseString(&line_buffer, &obj_name)) - return false; - if (obj_name.length() == 0) - return true; // Ignore empty name entries. - auto it = obj_name_to_id_.find(obj_name); - if (it == obj_name_to_id_.end()) { - const int num_obj = static_cast<int>(obj_name_to_id_.size()); - obj_name_to_id_[obj_name] = num_obj; - last_sub_obj_id_ = num_obj; - } else { - last_sub_obj_id_ = it->second; - } - return true; -} - -bool ObjDecoder::ParseVertexIndices(std::array<int32_t, 3> *out_indices) { - // Parsed attribute indices can be in format: - // 1. POS_INDEX - // 2. POS_INDEX/TEX_COORD_INDEX - // 3. POS_INDEX/TEX_COORD_INDEX/NORMAL_INDEX - // 4. POS_INDEX//NORMAL_INDEX - parser::SkipCharacters(buffer(), " \t"); - if (!parser::ParseSignedInt(buffer(), &(*out_indices)[0]) || - (*out_indices)[0] == 0) - return false; // Position index must be present and valid. - (*out_indices)[1] = (*out_indices)[2] = 0; - char ch; - if (!buffer()->Peek(&ch)) - return true; // It may be OK if we cannot read any more characters. - if (ch != '/') - return true; - buffer()->Advance(1); - // Check if we should skip texture index or not. - if (!buffer()->Peek(&ch)) - return false; // Here, we should be always able to read the next char. - if (ch != '/') { - // Must be texture coord index. - if (!parser::ParseSignedInt(buffer(), &(*out_indices)[1]) || - (*out_indices)[1] == 0) - return false; // Texture index must be present and valid. - } - if (!buffer()->Peek(&ch)) - return true; - if (ch == '/') { - buffer()->Advance(1); - // Read normal index. - if (!parser::ParseSignedInt(buffer(), &(*out_indices)[2]) || - (*out_indices)[2] == 0) - return false; // Normal index must be present and valid. - } - return true; -} - -void ObjDecoder::MapPointToVertexIndices( - PointIndex vert_id, const std::array<int32_t, 3> &indices) { - // Use face entries to store mapping between vertex and attribute indices - // (positions, texture coordinates and normal indices). - // Any given index is used when indices[x] != 0. For positive values, the - // point is mapped directly to the specified attribute index. Negative input - // indices indicate addressing from the last element (e.g. -1 is the last - // attribute value of a given type, -2 the second last, etc.). - if (indices[0] > 0) { - out_point_cloud_->attribute(pos_att_id_) - ->SetPointMapEntry(vert_id, AttributeValueIndex(indices[0] - 1)); - } else if (indices[0] < 0) { - out_point_cloud_->attribute(pos_att_id_) - ->SetPointMapEntry(vert_id, - AttributeValueIndex(num_positions_ + indices[0])); - } - - if (tex_att_id_ >= 0) { - if (indices[1] > 0) { - out_point_cloud_->attribute(tex_att_id_) - ->SetPointMapEntry(vert_id, AttributeValueIndex(indices[1] - 1)); - } else if (indices[1] < 0) { - out_point_cloud_->attribute(tex_att_id_) - ->SetPointMapEntry(vert_id, - AttributeValueIndex(num_tex_coords_ + indices[1])); - } else { - // Texture index not provided but expected. Insert 0 entry as the - // default value. - out_point_cloud_->attribute(tex_att_id_) - ->SetPointMapEntry(vert_id, AttributeValueIndex(0)); - } - } - - if (norm_att_id_ >= 0) { - if (indices[2] > 0) { - out_point_cloud_->attribute(norm_att_id_) - ->SetPointMapEntry(vert_id, AttributeValueIndex(indices[2] - 1)); - } else if (indices[2] < 0) { - out_point_cloud_->attribute(norm_att_id_) - ->SetPointMapEntry(vert_id, - AttributeValueIndex(num_normals_ + indices[2])); - } else { - // Normal index not provided but expected. Insert 0 entry as the default - // value. - out_point_cloud_->attribute(norm_att_id_) - ->SetPointMapEntry(vert_id, AttributeValueIndex(0)); - } - } - - // Assign material index to the point if it is available. - if (material_att_id_ >= 0) { - out_point_cloud_->attribute(material_att_id_) - ->SetPointMapEntry(vert_id, AttributeValueIndex(last_material_id_)); - } - - // Assign sub-object index to the point if it is available. - if (sub_obj_att_id_ >= 0) { - out_point_cloud_->attribute(sub_obj_att_id_) - ->SetPointMapEntry(vert_id, AttributeValueIndex(last_sub_obj_id_)); - } -} - -bool ObjDecoder::ParseMaterialFile(const std::string &file_name, - Status *status) { - const std::string full_path = GetFullPath(file_name, input_file_name_); - std::ifstream file(full_path, std::ios::binary); - if (!file) - return false; - // Read the whole file into a buffer. - file.seekg(0, std::ios::end); - const std::string::size_type file_size = file.tellg(); - if (file_size == 0) - return false; - file.seekg(0, std::ios::beg); - std::vector<char> data(file_size); - file.read(&data[0], file_size); - - // Backup the original decoder buffer. - DecoderBuffer old_buffer = buffer_; - - buffer_.Init(&data[0], file_size); - - num_materials_ = 0; - while (ParseMaterialFileDefinition(status)) { - } - - // Restore the original buffer. - buffer_ = old_buffer; - return true; -} - -bool ObjDecoder::ParseMaterialFileDefinition(Status * /* status */) { - char c; - parser::SkipWhitespace(buffer()); - if (!buffer()->Peek(&c)) { - // End of file reached?. - return false; - } - if (c == '#') { - // Comment, ignore the line. - parser::SkipLine(buffer()); - return true; - } - std::string str; - if (!parser::ParseString(buffer(), &str)) - return false; - if (str == "newmtl") { - parser::SkipWhitespace(buffer()); - parser::ParseLine(buffer(), &str); - if (str.empty()) - return false; - // Add new material to our map. - material_name_to_id_[str] = num_materials_++; - } - return true; -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/obj_decoder.h b/extern/draco/dracoenc/src/draco/io/obj_decoder.h deleted file mode 100644 index 33b9dee2414..00000000000 --- a/extern/draco/dracoenc/src/draco/io/obj_decoder.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_OBJ_DECODER_H_ -#define DRACO_IO_OBJ_DECODER_H_ - -#include <string> -#include <unordered_map> - -#include "draco/draco_features.h" - -#include "draco/core/decoder_buffer.h" -#include "draco/core/status.h" -#include "draco/mesh/mesh.h" - -namespace draco { - -// Decodes a Wavefront OBJ file into draco::Mesh (or draco::PointCloud if the -// connectivity data is not needed).. This decoder can handle decoding of -// positions, texture coordinates, normals and triangular faces. -// All other geometry properties are ignored. -class ObjDecoder { - public: - ObjDecoder(); - - // Decodes an obj file stored in the input file. - // Returns nullptr if the decoding failed. - Status DecodeFromFile(const std::string &file_name, Mesh *out_mesh); - Status DecodeFromFile(const std::string &file_name, - PointCloud *out_point_cloud); - - Status DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh); - Status DecodeFromBuffer(DecoderBuffer *buffer, PointCloud *out_point_cloud); - - // Flag that can be used to turn on/off deduplication of input values. - // This should be disabled only when we are sure that the input data does not - // contain any duplicate entries. - // Default: true - void set_deduplicate_input_values(bool v) { deduplicate_input_values_ = v; } - // Flag for whether using metadata to record other information in the obj - // file, e.g. material names, object names. - void set_use_metadata(bool flag) { use_metadata_ = flag; } - - protected: - Status DecodeInternal(); - DecoderBuffer *buffer() { return &buffer_; } - - private: - // Resets internal counters for attributes and faces. - void ResetCounters(); - - // Parses the next mesh property definition (position, tex coord, normal, or - // face). If the parsed data is unrecognized, it will be skipped. - // Returns false when the end of file was reached. - bool ParseDefinition(Status *status); - - // Attempts to parse definition of position, normal, tex coord, or face - // respectively. - // Returns false when the parsed data didn't contain the given definition. - bool ParseVertexPosition(Status *status); - bool ParseNormal(Status *status); - bool ParseTexCoord(Status *status); - bool ParseFace(Status *status); - bool ParseMaterialLib(Status *status); - bool ParseMaterial(Status *status); - bool ParseObject(Status *status); - - // Parses triplet of position, tex coords and normal indices. - // Returns false on error. - bool ParseVertexIndices(std::array<int32_t, 3> *out_indices); - - // Maps specified point index to the parsed vertex indices (triplet of - // position, texture coordinate, and normal indices) . - void MapPointToVertexIndices(PointIndex pi, - const std::array<int32_t, 3> &indices); - - // Parses material file definitions from a separate file. - bool ParseMaterialFile(const std::string &file_name, Status *status); - bool ParseMaterialFileDefinition(Status *status); - - // If set to true, the parser will count the number of various definitions - // but it will not parse the actual data or add any new entries to the mesh. - bool counting_mode_; - int num_obj_faces_; - int num_positions_; - int num_tex_coords_; - int num_normals_; - int num_materials_; - int last_sub_obj_id_; - - int pos_att_id_; - int tex_att_id_; - int norm_att_id_; - int material_att_id_; - int sub_obj_att_id_; // Attribute id for storing sub-objects. - - bool deduplicate_input_values_; - - int last_material_id_; - std::string material_file_name_; - - std::string input_file_name_; - - std::unordered_map<std::string, int> material_name_to_id_; - std::unordered_map<std::string, int> obj_name_to_id_; - - bool use_metadata_; - - DecoderBuffer buffer_; - - // Data structure that stores the decoded data. |out_point_cloud_| must be - // always set but |out_mesh_| is optional. - Mesh *out_mesh_; - PointCloud *out_point_cloud_; -}; - -} // namespace draco - -#endif // DRACO_IO_OBJ_DECODER_H_ diff --git a/extern/draco/dracoenc/src/draco/io/obj_decoder_test.cc b/extern/draco/dracoenc/src/draco/io/obj_decoder_test.cc deleted file mode 100644 index 3d319a9d44a..00000000000 --- a/extern/draco/dracoenc/src/draco/io/obj_decoder_test.cc +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include <sstream> - -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/obj_decoder.h" - -namespace draco { - -class ObjDecoderTest : public ::testing::Test { - protected: - template <class Geometry> - std::unique_ptr<Geometry> DecodeObj(const std::string &file_name) const { - return DecodeObj<Geometry>(file_name, false); - } - - template <class Geometry> - std::unique_ptr<Geometry> DecodeObj(const std::string &file_name, - bool deduplicate_input_values) const { - const std::string path = GetTestFileFullPath(file_name); - ObjDecoder decoder; - decoder.set_deduplicate_input_values(deduplicate_input_values); - std::unique_ptr<Geometry> geometry(new Geometry()); - if (!decoder.DecodeFromFile(path, geometry.get()).ok()) - return nullptr; - return geometry; - } - - template <class Geometry> - std::unique_ptr<Geometry> DecodeObjWithMetadata( - const std::string &file_name) const { - const std::string path = GetTestFileFullPath(file_name); - ObjDecoder decoder; - decoder.set_use_metadata(true); - std::unique_ptr<Geometry> geometry(new Geometry()); - if (!decoder.DecodeFromFile(path, geometry.get()).ok()) - return nullptr; - return geometry; - } - - void test_decoding(const std::string &file_name) { - const std::unique_ptr<Mesh> mesh(DecodeObj<Mesh>(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - ASSERT_GT(mesh->num_faces(), 0); - - const std::unique_ptr<PointCloud> pc(DecodeObj<PointCloud>(file_name)); - ASSERT_NE(pc, nullptr) << "Failed to load test model " << file_name; - ASSERT_GT(pc->num_points(), 0); - } -}; - -TEST_F(ObjDecoderTest, ExtraVertexOBJ) { - const std::string file_name = "extra_vertex.obj"; - test_decoding(file_name); -} - -TEST_F(ObjDecoderTest, PartialAttributesOBJ) { - const std::string file_name = "cube_att_partial.obj"; - test_decoding(file_name); -} - -TEST_F(ObjDecoderTest, SubObjects) { - // Tests loading an Obj with sub objects. - const std::string file_name = "cube_att_sub_o.obj"; - const std::unique_ptr<Mesh> mesh(DecodeObj<Mesh>(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - ASSERT_GT(mesh->num_faces(), 0); - - // A sub object attribute should be the fourth attribute of the mesh (in this - // case). - ASSERT_EQ(mesh->num_attributes(), 4); - ASSERT_EQ(mesh->attribute(3)->attribute_type(), GeometryAttribute::GENERIC); - // There should be 3 different sub objects used in the model. - ASSERT_EQ(mesh->attribute(3)->size(), 3); - // Verify that the sub object attribute has unique id == 3. - ASSERT_EQ(mesh->attribute(3)->unique_id(), 3); -} - -TEST_F(ObjDecoderTest, SubObjectsWithMetadata) { - // Tests loading an Obj with sub objects. - const std::string file_name = "cube_att_sub_o.obj"; - const std::unique_ptr<Mesh> mesh(DecodeObjWithMetadata<Mesh>(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - ASSERT_GT(mesh->num_faces(), 0); - - ASSERT_EQ(mesh->num_attributes(), 4); - ASSERT_EQ(mesh->attribute(3)->attribute_type(), GeometryAttribute::GENERIC); - // There should be 3 different sub objects used in the model. - ASSERT_EQ(mesh->attribute(3)->size(), 3); - - // Test material names stored in metadata. - ASSERT_NE(mesh->GetMetadata(), nullptr); - ASSERT_NE(mesh->GetAttributeMetadataByAttributeId(3), nullptr); - int32_t sub_obj_id = 0; - ASSERT_TRUE(mesh->GetAttributeMetadataByAttributeId(3)->GetEntryInt( - "obj2", &sub_obj_id)); - ASSERT_EQ(sub_obj_id, 2); -} - -TEST_F(ObjDecoderTest, QuadOBJ) { - // Tests loading an Obj with quad faces. - const std::string file_name = "cube_quads.obj"; - const std::unique_ptr<Mesh> mesh(DecodeObj<Mesh>(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - ASSERT_EQ(mesh->num_faces(), 12); - - ASSERT_EQ(mesh->num_attributes(), 3); - ASSERT_EQ(mesh->num_points(), 4 * 6); // Four points per quad face. -} - -TEST_F(ObjDecoderTest, ComplexPolyOBJ) { - // Tests that we fail to load an obj with complex polygon (expected failure). - const std::string file_name = "invalid/complex_poly.obj"; - const std::unique_ptr<Mesh> mesh(DecodeObj<Mesh>(file_name)); - ASSERT_EQ(mesh, nullptr); -} - -TEST_F(ObjDecoderTest, EmptyNameOBJ) { - // Tests that we load an obj file that has an sub-object defined with an empty - // name. - const std::string file_name = "empty_name.obj"; - const std::unique_ptr<Mesh> mesh(DecodeObj<Mesh>(file_name)); - ASSERT_NE(mesh, nullptr); - ASSERT_EQ(mesh->num_attributes(), 1); - // Three valid entries in the attribute are expected. - ASSERT_EQ(mesh->attribute(0)->size(), 3); -} - -TEST_F(ObjDecoderTest, PointCloudOBJ) { - // Tests that we load an obj file that does not contain any faces. - const std::string file_name = "test_lines.obj"; - const std::unique_ptr<Mesh> mesh(DecodeObj<Mesh>(file_name, false)); - ASSERT_NE(mesh, nullptr); - ASSERT_EQ(mesh->num_faces(), 0); - ASSERT_EQ(mesh->num_attributes(), 1); - ASSERT_EQ(mesh->attribute(0)->size(), 484); -} - -TEST_F(ObjDecoderTest, WrongAttributeMapping) { - // Tests that we load an obj file that contains invalid mapping between - // attribute indices and values. In such case the invalid indices should be - // ignored. - const std::string file_name = "test_wrong_attribute_mapping.obj"; - const std::unique_ptr<Mesh> mesh(DecodeObj<Mesh>(file_name, false)); - ASSERT_NE(mesh, nullptr); - ASSERT_EQ(mesh->num_faces(), 1); - ASSERT_EQ(mesh->num_attributes(), 1); - ASSERT_EQ(mesh->attribute(0)->size(), 3); -} - -TEST_F(ObjDecoderTest, TestObjDecodingAll) { - // test if we can read all obj that are currently in test folder. - test_decoding("bunny_norm.obj"); - // test_decoding("complex_poly.obj"); // not supported see test above - test_decoding("cube_att.obj"); - test_decoding("cube_att_partial.obj"); - test_decoding("cube_att_sub_o.obj"); - test_decoding("cube_quads.obj"); - test_decoding("cube_subd.obj"); - test_decoding("eof_test.obj"); - test_decoding("extra_vertex.obj"); - test_decoding("mat_test.obj"); - test_decoding("one_face_123.obj"); - test_decoding("one_face_312.obj"); - test_decoding("one_face_321.obj"); - test_decoding("sphere.obj"); - test_decoding("test_nm.obj"); - test_decoding("test_nm_trans.obj"); - test_decoding("test_sphere.obj"); - test_decoding("three_faces_123.obj"); - test_decoding("three_faces_312.obj"); - test_decoding("two_faces_123.obj"); - test_decoding("two_faces_312.obj"); - test_decoding("inf_nan.obj"); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/obj_encoder.cc b/extern/draco/dracoenc/src/draco/io/obj_encoder.cc deleted file mode 100644 index 807506e3536..00000000000 --- a/extern/draco/dracoenc/src/draco/io/obj_encoder.cc +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/obj_encoder.h" - -#include <fstream> - -#include "draco/metadata/geometry_metadata.h" - -namespace draco { - -ObjEncoder::ObjEncoder() - : pos_att_(nullptr), - tex_coord_att_(nullptr), - normal_att_(nullptr), - material_att_(nullptr), - sub_obj_att_(nullptr), - out_buffer_(nullptr), - in_point_cloud_(nullptr), - in_mesh_(nullptr), - current_sub_obj_id_(-1), - current_material_id_(-1) {} - -bool ObjEncoder::EncodeToFile(const PointCloud &pc, - const std::string &file_name) { - std::ofstream file(file_name); - if (!file) - return false; // File could not be opened. - file_name_ = file_name; - // Encode the mesh into a buffer. - EncoderBuffer buffer; - if (!EncodeToBuffer(pc, &buffer)) - return false; - // Write the buffer into the file. - file.write(buffer.data(), buffer.size()); - return true; -} - -bool ObjEncoder::EncodeToFile(const Mesh &mesh, const std::string &file_name) { - in_mesh_ = &mesh; - return EncodeToFile(static_cast<const PointCloud &>(mesh), file_name); -} - -bool ObjEncoder::EncodeToBuffer(const PointCloud &pc, - EncoderBuffer *out_buffer) { - in_point_cloud_ = &pc; - out_buffer_ = out_buffer; - if (!EncodeInternal()) - return ExitAndCleanup(false); - return ExitAndCleanup(true); -} - -bool ObjEncoder::EncodeToBuffer(const Mesh &mesh, EncoderBuffer *out_buffer) { - in_mesh_ = &mesh; - return EncodeToBuffer(static_cast<const PointCloud &>(mesh), out_buffer); -} - -bool ObjEncoder::EncodeInternal() { - pos_att_ = nullptr; - tex_coord_att_ = nullptr; - normal_att_ = nullptr; - material_att_ = nullptr; - sub_obj_att_ = nullptr; - current_sub_obj_id_ = -1; - current_material_id_ = -1; - if (!GetSubObjects()) - return false; - if (!EncodeMaterialFileName()) - return false; - if (!EncodePositions()) - return false; - if (!EncodeTextureCoordinates()) - return false; - if (!EncodeNormals()) - return false; - if (in_mesh_ && !EncodeFaces()) - return false; - return true; -} - -bool ObjEncoder::ExitAndCleanup(bool return_value) { - in_mesh_ = nullptr; - in_point_cloud_ = nullptr; - out_buffer_ = nullptr; - pos_att_ = nullptr; - tex_coord_att_ = nullptr; - normal_att_ = nullptr; - material_att_ = nullptr; - sub_obj_att_ = nullptr; - current_sub_obj_id_ = -1; - current_material_id_ = -1; - file_name_.clear(); - return return_value; -} - -bool ObjEncoder::GetSubObjects() { - const GeometryMetadata *pc_metadata = in_point_cloud_->GetMetadata(); - if (!pc_metadata) - return true; - const AttributeMetadata *sub_obj_metadata = - pc_metadata->GetAttributeMetadataByStringEntry("name", "sub_obj"); - if (!sub_obj_metadata) - return true; - sub_obj_id_to_name_.clear(); - for (const auto &entry : sub_obj_metadata->entries()) { - // Sub-object id must be int. - int value = 0; - if (!entry.second.GetValue(&value)) - continue; - sub_obj_id_to_name_[value] = entry.first; - } - sub_obj_att_ = in_point_cloud_->GetAttributeByUniqueId( - sub_obj_metadata->att_unique_id()); - if (sub_obj_att_ == nullptr || sub_obj_att_->size() == 0) - return false; - return true; -} - -bool ObjEncoder::EncodeMaterialFileName() { - const GeometryMetadata *pc_metadata = in_point_cloud_->GetMetadata(); - const AttributeMetadata *material_metadata = nullptr; - if (pc_metadata) { - material_metadata = - pc_metadata->GetAttributeMetadataByStringEntry("name", "material"); - } - std::string material_file_name; - std::string material_full_path; - if (!material_metadata) - return true; - if (!material_metadata->GetEntryString("file_name", &material_file_name)) - return false; - buffer()->Encode("mtllib ", 7); - buffer()->Encode(material_file_name.c_str(), material_file_name.size()); - buffer()->Encode("\n", 1); - material_id_to_name_.clear(); - for (const auto &entry : material_metadata->entries()) { - // Material id must be int. - int value = 0; - // Found entry that are not material id, e.g. file name as a string. - if (!entry.second.GetValue(&value)) - continue; - material_id_to_name_[value] = entry.first; - } - material_att_ = in_point_cloud_->GetAttributeByUniqueId( - material_metadata->att_unique_id()); - if (material_att_ == nullptr || material_att_->size() == 0) - return false; - return true; -} - -bool ObjEncoder::EncodePositions() { - const PointAttribute *const att = - in_point_cloud_->GetNamedAttribute(GeometryAttribute::POSITION); - if (att == nullptr || att->size() == 0) - return false; // Position attribute must be valid. - std::array<float, 3> value; - for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size()); ++i) { - if (!att->ConvertValue<float, 3>(i, &value[0])) - return false; - buffer()->Encode("v ", 2); - EncodeFloatList(&value[0], 3); - buffer()->Encode("\n", 1); - } - pos_att_ = att; - return true; -} - -bool ObjEncoder::EncodeTextureCoordinates() { - const PointAttribute *const att = - in_point_cloud_->GetNamedAttribute(GeometryAttribute::TEX_COORD); - if (att == nullptr || att->size() == 0) - return true; // It's OK if we don't have texture coordinates. - std::array<float, 2> value; - for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size()); ++i) { - if (!att->ConvertValue<float, 2>(i, &value[0])) - return false; - buffer()->Encode("vt ", 3); - EncodeFloatList(&value[0], 2); - buffer()->Encode("\n", 1); - } - tex_coord_att_ = att; - return true; -} - -bool ObjEncoder::EncodeNormals() { - const PointAttribute *const att = - in_point_cloud_->GetNamedAttribute(GeometryAttribute::NORMAL); - if (att == nullptr || att->size() == 0) - return true; // It's OK if we don't have normals. - std::array<float, 3> value; - for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size()); ++i) { - if (!att->ConvertValue<float, 3>(i, &value[0])) - return false; - buffer()->Encode("vn ", 3); - EncodeFloatList(&value[0], 3); - buffer()->Encode("\n", 1); - } - normal_att_ = att; - return true; -} - -bool ObjEncoder::EncodeFaces() { - for (FaceIndex i(0); i < in_mesh_->num_faces(); ++i) { - if (sub_obj_att_) - if (!EncodeSubObject(i)) - return false; - if (material_att_) - if (!EncodeMaterial(i)) - return false; - buffer()->Encode('f'); - for (int j = 0; j < 3; ++j) { - if (!EncodeFaceCorner(i, j)) - return false; - } - buffer()->Encode("\n", 1); - } - return true; -} - -bool ObjEncoder::EncodeMaterial(FaceIndex face_id) { - int material_id = 0; - // Pick the first corner, all corners of a face should have same id. - const PointIndex vert_index = in_mesh_->face(face_id)[0]; - const AttributeValueIndex index_id(material_att_->mapped_index(vert_index)); - if (!material_att_->ConvertValue<int>(index_id, &material_id)) { - return false; - } - - if (material_id != current_material_id_) { - // Update material information. - buffer()->Encode("usemtl ", 7); - const auto mat_ptr = material_id_to_name_.find(material_id); - // If the material id is not found. - if (mat_ptr == material_id_to_name_.end()) - return false; - buffer()->Encode(mat_ptr->second.c_str(), mat_ptr->second.size()); - buffer()->Encode("\n", 1); - current_material_id_ = material_id; - } - return true; -} - -bool ObjEncoder::EncodeSubObject(FaceIndex face_id) { - int sub_obj_id = 0; - // Pick the first corner, all corners of a face should have same id. - const PointIndex vert_index = in_mesh_->face(face_id)[0]; - const AttributeValueIndex index_id(sub_obj_att_->mapped_index(vert_index)); - if (!sub_obj_att_->ConvertValue<int>(index_id, &sub_obj_id)) { - return false; - } - if (sub_obj_id != current_sub_obj_id_) { - buffer()->Encode("o ", 2); - const auto sub_obj_ptr = sub_obj_id_to_name_.find(sub_obj_id); - if (sub_obj_ptr == sub_obj_id_to_name_.end()) - return false; - buffer()->Encode(sub_obj_ptr->second.c_str(), sub_obj_ptr->second.size()); - buffer()->Encode("\n", 1); - current_sub_obj_id_ = sub_obj_id; - } - return true; -} - -bool ObjEncoder::EncodeFaceCorner(FaceIndex face_id, int local_corner_id) { - buffer()->Encode(' '); - const PointIndex vert_index = in_mesh_->face(face_id)[local_corner_id]; - // Note that in the OBJ format, all indices are encoded starting from index 1. - // Encode position index. - EncodeInt(pos_att_->mapped_index(vert_index).value() + 1); - if (tex_coord_att_ || normal_att_) { - // Encoding format is pos_index/tex_coord_index/normal_index. - // If tex_coords are not present, we must encode pos_index//normal_index. - buffer()->Encode('/'); - if (tex_coord_att_) { - EncodeInt(tex_coord_att_->mapped_index(vert_index).value() + 1); - } - if (normal_att_) { - buffer()->Encode('/'); - EncodeInt(normal_att_->mapped_index(vert_index).value() + 1); - } - } - return true; -} - -void ObjEncoder::EncodeFloat(float val) { - snprintf(num_buffer_, sizeof(num_buffer_), "%f", val); - buffer()->Encode(num_buffer_, strlen(num_buffer_)); -} - -void ObjEncoder::EncodeFloatList(float *vals, int num_vals) { - for (int i = 0; i < num_vals; ++i) { - if (i > 0) { - buffer()->Encode(' '); - } - EncodeFloat(vals[i]); - } -} - -void ObjEncoder::EncodeInt(int32_t val) { - snprintf(num_buffer_, sizeof(num_buffer_), "%d", val); - buffer()->Encode(num_buffer_, strlen(num_buffer_)); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/obj_encoder.h b/extern/draco/dracoenc/src/draco/io/obj_encoder.h deleted file mode 100644 index 509d39baf39..00000000000 --- a/extern/draco/dracoenc/src/draco/io/obj_encoder.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_OBJ_ENCODER_H_ -#define DRACO_IO_OBJ_ENCODER_H_ - -#include <unordered_map> - -#include "draco/core/encoder_buffer.h" -#include "draco/mesh/mesh.h" - -namespace draco { - -// Class for encoding input draco::Mesh or draco::PointCloud into the Wavefront -// OBJ format. -class ObjEncoder { - public: - ObjEncoder(); - - // Encodes the mesh or a point cloud and saves it into a file. - // Returns false when either the encoding failed or when the file couldn't be - // opened. - bool EncodeToFile(const PointCloud &pc, const std::string &file_name); - bool EncodeToFile(const Mesh &mesh, const std::string &file_name); - - // Encodes the mesh or the point cloud into a buffer. - bool EncodeToBuffer(const PointCloud &pc, EncoderBuffer *out_buffer); - bool EncodeToBuffer(const Mesh &mesh, EncoderBuffer *out_buffer); - - protected: - bool EncodeInternal(); - EncoderBuffer *buffer() const { return out_buffer_; } - bool ExitAndCleanup(bool return_value); - - private: - bool GetSubObjects(); - bool EncodeMaterialFileName(); - bool EncodePositions(); - bool EncodeTextureCoordinates(); - bool EncodeNormals(); - bool EncodeFaces(); - bool EncodeSubObject(FaceIndex face_id); - bool EncodeMaterial(FaceIndex face_id); - bool EncodeFaceCorner(FaceIndex face_id, int local_corner_id); - - void EncodeFloat(float val); - void EncodeFloatList(float *vals, int num_vals); - void EncodeInt(int32_t val); - - // Various attributes used by the encoder. If an attribute is not used, it is - // set to nullptr. - const PointAttribute *pos_att_; - const PointAttribute *tex_coord_att_; - const PointAttribute *normal_att_; - const PointAttribute *material_att_; - const PointAttribute *sub_obj_att_; - - // Buffer used for encoding float/int numbers. - char num_buffer_[20]; - - EncoderBuffer *out_buffer_; - - const PointCloud *in_point_cloud_; - const Mesh *in_mesh_; - - // Store sub object name for each value. - std::unordered_map<int, std::string> sub_obj_id_to_name_; - // Current sub object id of faces. - int current_sub_obj_id_; - - // Store material name for each value in material attribute. - std::unordered_map<int, std::string> material_id_to_name_; - // Current material id of faces. - int current_material_id_; - - std::string file_name_; -}; - -} // namespace draco - -#endif // DRACO_IO_OBJ_ENCODER_H_ diff --git a/extern/draco/dracoenc/src/draco/io/obj_encoder_test.cc b/extern/draco/dracoenc/src/draco/io/obj_encoder_test.cc deleted file mode 100644 index 79ea1712806..00000000000 --- a/extern/draco/dracoenc/src/draco/io/obj_encoder_test.cc +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include <fstream> -#include <sstream> - -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/obj_decoder.h" -#include "draco/io/obj_encoder.h" - -namespace draco { - -class ObjEncoderTest : public ::testing::Test { - protected: - void CompareMeshes(const Mesh *mesh0, const Mesh *mesh1) { - ASSERT_EQ(mesh0->num_faces(), mesh1->num_faces()); - ASSERT_EQ(mesh0->num_attributes(), mesh1->num_attributes()); - for (size_t att_id = 0; att_id < mesh0->num_attributes(); ++att_id) { - ASSERT_EQ(mesh0->attribute(att_id)->size(), - mesh1->attribute(att_id)->size()); - } - } - - // Encode a mesh using the ObjEncoder and then decode to verify the encoding. - std::unique_ptr<Mesh> EncodeAndDecodeMesh(const Mesh *mesh) { - EncoderBuffer encoder_buffer; - ObjEncoder encoder; - if (!encoder.EncodeToBuffer(*mesh, &encoder_buffer)) - return nullptr; - - DecoderBuffer decoder_buffer; - decoder_buffer.Init(encoder_buffer.data(), encoder_buffer.size()); - std::unique_ptr<Mesh> decoded_mesh(new Mesh()); - ObjDecoder decoder; - decoder.set_use_metadata(true); - if (!decoder.DecodeFromBuffer(&decoder_buffer, decoded_mesh.get()).ok()) - return nullptr; - return decoded_mesh; - } - - void test_encoding(const std::string &file_name) { - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name, true)); - - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - ASSERT_GT(mesh->num_faces(), 0); - - const std::unique_ptr<Mesh> decoded_mesh = EncodeAndDecodeMesh(mesh.get()); - CompareMeshes(mesh.get(), decoded_mesh.get()); - } -}; - -TEST_F(ObjEncoderTest, HasSubObject) { test_encoding("cube_att_sub_o.obj"); } - -TEST_F(ObjEncoderTest, HasMaterial) { - const std::unique_ptr<Mesh> mesh0(ReadMeshFromTestFile("mat_test.obj", true)); - ASSERT_NE(mesh0, nullptr); - const std::unique_ptr<Mesh> mesh1 = EncodeAndDecodeMesh(mesh0.get()); - ASSERT_NE(mesh1, nullptr); - ASSERT_EQ(mesh0->num_faces(), mesh1->num_faces()); - ASSERT_EQ(mesh0->num_attributes(), mesh1->num_attributes()); - // Position attribute should be the same. - ASSERT_EQ(mesh0->attribute(0)->size(), mesh1->attribute(0)->size()); - // Since |mesh1| is decoded from buffer, it has not material file. So the - // size of material attribute is the number of materials used in the obj - // file which is 7. The size of material attribute of |mesh0| decoded from - // the obj file will be the number of materials defined in the .mtl file. - ASSERT_EQ(mesh0->attribute(1)->size(), 29); - ASSERT_EQ(mesh1->attribute(1)->size(), 7); -} - -TEST_F(ObjEncoderTest, TestObjEncodingAll) { - // Test decoded mesh from encoded obj file stays the same. - test_encoding("bunny_norm.obj"); - test_encoding("cube_att.obj"); - test_encoding("cube_att_partial.obj"); - test_encoding("cube_quads.obj"); - test_encoding("cube_subd.obj"); - test_encoding("extra_vertex.obj"); - test_encoding("multiple_isolated_triangles.obj"); - test_encoding("multiple_tetrahedrons.obj"); - test_encoding("one_face_123.obj"); - test_encoding("one_face_312.obj"); - test_encoding("one_face_321.obj"); - test_encoding("sphere.obj"); - test_encoding("test_nm.obj"); - test_encoding("test_nm_trans.obj"); - test_encoding("test_sphere.obj"); - test_encoding("three_faces_123.obj"); - test_encoding("three_faces_312.obj"); - test_encoding("two_faces_123.obj"); - test_encoding("two_faces_312.obj"); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/parser_utils.cc b/extern/draco/dracoenc/src/draco/io/parser_utils.cc deleted file mode 100644 index 0a22ba114ab..00000000000 --- a/extern/draco/dracoenc/src/draco/io/parser_utils.cc +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/parser_utils.h" - -#include <algorithm> -#include <cctype> -#include <cmath> -#include <iterator> - -namespace draco { -namespace parser { - -void SkipCharacters(DecoderBuffer *buffer, const char *skip_chars) { - if (skip_chars == nullptr) - return; - const int num_skip_chars = static_cast<int>(strlen(skip_chars)); - char c; - while (buffer->Peek(&c)) { - // Check all characters in the pattern. - bool skip = false; - for (int i = 0; i < num_skip_chars; ++i) { - if (c == skip_chars[i]) { - skip = true; - break; - } - } - if (!skip) - return; - buffer->Advance(1); - } -} - -void SkipWhitespace(DecoderBuffer *buffer) { - bool end_reached = false; - while (PeekWhitespace(buffer, &end_reached) && !end_reached) { - // Skip the whitespace character - buffer->Advance(1); - } -} - -bool PeekWhitespace(DecoderBuffer *buffer, bool *end_reached) { - uint8_t c; - if (!buffer->Peek(&c)) { - *end_reached = true; - return false; // eof reached. - } - if (!isspace(c)) - return false; // Non-whitespace character reached. - return true; -} - -void SkipLine(DecoderBuffer *buffer) { - char c; - while (buffer->Peek(&c)) { - // Skip the character. - buffer->Advance(1); - if (c == '\n') - return; // Return at the end of line - } -} - -bool ParseFloat(DecoderBuffer *buffer, float *value) { - // Read optional sign. - char ch; - if (!buffer->Peek(&ch)) - return false; - int sign = GetSignValue(ch); - if (sign != 0) { - buffer->Advance(1); - } else { - sign = 1; - } - - // Parse integer component. - bool have_digits = false; - double v = 0.0; - while (buffer->Peek(&ch) && ch >= '0' && ch <= '9') { - v *= 10.0; - v += (ch - '0'); - buffer->Advance(1); - have_digits = true; - } - if (ch == '.') { - // Parse fractional component. - buffer->Advance(1); - double fraction = 1.0; - while (buffer->Peek(&ch) && ch >= '0' && ch <= '9') { - fraction *= 0.1; - v += (ch - '0') * fraction; - buffer->Advance(1); - have_digits = true; - } - } - - if (!have_digits) { - // Check for special constants (inf, nan, ...). - std::string text; - if (!ParseString(buffer, &text)) - return false; - if (text == "inf" || text == "Inf") { - v = std::numeric_limits<double>::infinity(); - } else if (text == "nan" || text == "NaN") { - v = nan(""); - } else { - // Invalid string. - return false; - } - } else { - // Handle exponent if present. - if (ch == 'e' || ch == 'E') { - buffer->Advance(1); // Skip 'e' marker. - - // Parse integer exponent. - int32_t exponent = 0; - if (!ParseSignedInt(buffer, &exponent)) - return false; - - // Apply exponent scaling to value. - v *= pow(static_cast<double>(10.0), exponent); - } - } - - *value = (sign < 0) ? static_cast<float>(-v) : static_cast<float>(v); - return true; -} - -bool ParseSignedInt(DecoderBuffer *buffer, int32_t *value) { - // Parse any explicit sign and set the appropriate largest magnitude - // value that can be represented without overflow. - char ch; - if (!buffer->Peek(&ch)) - return false; - const int sign = GetSignValue(ch); - if (sign != 0) - buffer->Advance(1); - - // Attempt to parse integer body. - uint32_t v; - if (!ParseUnsignedInt(buffer, &v)) - return false; - *value = (sign < 0) ? -v : v; - return true; -} - -bool ParseUnsignedInt(DecoderBuffer *buffer, uint32_t *value) { - // Parse the number until we run out of digits. - uint32_t v = 0; - char ch; - bool have_digits = false; - while (buffer->Peek(&ch) && ch >= '0' && ch <= '9') { - v *= 10; - v += (ch - '0'); - buffer->Advance(1); - have_digits = true; - } - if (!have_digits) - return false; - *value = v; - return true; -} - -int GetSignValue(char c) { - if (c == '-') - return -1; - if (c == '+') - return 1; - return 0; -} - -bool ParseString(DecoderBuffer *buffer, std::string *out_string) { - out_string->clear(); - SkipWhitespace(buffer); - bool end_reached = false; - while (!PeekWhitespace(buffer, &end_reached) && !end_reached) { - char c; - if (!buffer->Decode(&c)) - return false; - *out_string += c; - } - return true; -} - -void ParseLine(DecoderBuffer *buffer, std::string *out_string) { - out_string->clear(); - char c; - while (buffer->Peek(&c)) { - // Skip the character. - buffer->Advance(1); - if (c == '\n') - return; // Return at the end of line. - if (c == '\r') - continue; // Ignore extra line ending characters. - *out_string += c; - } -} - -DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer) { - const char *const head = buffer->data_head(); - char c; - while (buffer->Peek(&c)) { - // Skip the character. - buffer->Advance(1); - if (c == '\n') - break; // End of the line reached. - if (c == '\r') - continue; // Ignore extra line ending characters. - } - DecoderBuffer out_buffer; - out_buffer.Init(head, buffer->data_head() - head); - return out_buffer; -} - -std::string ToLower(const std::string &str) { - std::string out; - std::transform(str.begin(), str.end(), std::back_inserter(out), tolower); - return out; -} - -} // namespace parser -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/parser_utils.h b/extern/draco/dracoenc/src/draco/io/parser_utils.h deleted file mode 100644 index aa629053068..00000000000 --- a/extern/draco/dracoenc/src/draco/io/parser_utils.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_PARSER_UTILS_H_ -#define DRACO_IO_PARSER_UTILS_H_ - -#include "draco/core/decoder_buffer.h" - -namespace draco { -namespace parser { - -// Skips to first character not included in |skip_chars|. -void SkipCharacters(DecoderBuffer *buffer, const char *skip_chars); - -// Skips any whitespace until a regular character is reached. -void SkipWhitespace(DecoderBuffer *buffer); - -// Returns true if the next character is a whitespace. -// |end_reached| is set to true when the end of the stream is reached. -bool PeekWhitespace(DecoderBuffer *buffer, bool *end_reached); -void SkipLine(DecoderBuffer *buffer); - -// Parses signed floating point number or returns false on error. -bool ParseFloat(DecoderBuffer *buffer, float *value); - -// Parses a signed integer (can be preceded by '-' or '+' characters. -bool ParseSignedInt(DecoderBuffer *buffer, int32_t *value); - -// Parses an unsigned integer. It cannot be preceded by '-' or '+' -// characters. -bool ParseUnsignedInt(DecoderBuffer *buffer, uint32_t *value); - -// Returns -1 if c == '-'. -// Returns +1 if c == '+'. -// Returns 0 otherwise. -int GetSignValue(char c); - -// Parses a string until a whitespace or end of file is reached. -bool ParseString(DecoderBuffer *buffer, std::string *out_string); - -// Parses the entire line into the buffer (excluding the new line character). -void ParseLine(DecoderBuffer *buffer, std::string *out_string); - -// Parses line and stores into a new decoder buffer. -DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer); - -// Returns a string with all characters converted to lower case. -std::string ToLower(const std::string &str); - -} // namespace parser -} // namespace draco - -#endif // DRACO_IO_PARSER_UTILS_H_ diff --git a/extern/draco/dracoenc/src/draco/io/ply_decoder.cc b/extern/draco/dracoenc/src/draco/io/ply_decoder.cc deleted file mode 100644 index 69a1c546cf7..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_decoder.cc +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/ply_decoder.h" - -#include <fstream> - -#include "draco/core/macros.h" -#include "draco/core/status.h" -#include "draco/io/ply_property_reader.h" - -namespace draco { - -PlyDecoder::PlyDecoder() : out_mesh_(nullptr), out_point_cloud_(nullptr) {} - -Status PlyDecoder::DecodeFromFile(const std::string &file_name, - Mesh *out_mesh) { - out_mesh_ = out_mesh; - return DecodeFromFile(file_name, static_cast<PointCloud *>(out_mesh)); -} - -Status PlyDecoder::DecodeFromFile(const std::string &file_name, - PointCloud *out_point_cloud) { - std::ifstream file(file_name, std::ios::binary); - if (!file) - return Status(Status::IO_ERROR, "Couldn't open file"); - // Read the whole file into a buffer. - auto pos0 = file.tellg(); - file.seekg(0, std::ios::end); - auto file_size = file.tellg() - pos0; - if (file_size == 0) - return Status(Status::IO_ERROR, "Zero file size"); - file.seekg(0, std::ios::beg); - std::vector<char> data(file_size); - file.read(&data[0], file_size); - - buffer_.Init(&data[0], file_size); - return DecodeFromBuffer(&buffer_, out_point_cloud); -} - -Status PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh) { - out_mesh_ = out_mesh; - return DecodeFromBuffer(buffer, static_cast<PointCloud *>(out_mesh)); -} - -Status PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, - PointCloud *out_point_cloud) { - out_point_cloud_ = out_point_cloud; - buffer_.Init(buffer->data_head(), buffer->remaining_size()); - return DecodeInternal(); -} - -Status PlyDecoder::DecodeInternal() { - PlyReader ply_reader; - DRACO_RETURN_IF_ERROR(ply_reader.Read(buffer())); - // First, decode the connectivity data. - if (out_mesh_) - DRACO_RETURN_IF_ERROR(DecodeFaceData(ply_reader.GetElementByName("face"))); - // Decode all attributes. - DRACO_RETURN_IF_ERROR( - DecodeVertexData(ply_reader.GetElementByName("vertex"))); - // In case there are no faces this is just a point cloud which does - // not require deduplication. - if (out_mesh_ && out_mesh_->num_faces() != 0) { -#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED - if (!out_point_cloud_->DeduplicateAttributeValues()) - return Status(Status::DRACO_ERROR, - "Could not deduplicate attribute values"); -#endif -#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED - out_point_cloud_->DeduplicatePointIds(); -#endif - } - return OkStatus(); -} - -Status PlyDecoder::DecodeFaceData(const PlyElement *face_element) { - // We accept point clouds now. - if (face_element == nullptr) { - return Status(Status::INVALID_PARAMETER, "face_element is null"); - } - const int64_t num_faces = face_element->num_entries(); - out_mesh_->SetNumFaces(num_faces); - const PlyProperty *vertex_indices = - face_element->GetPropertyByName("vertex_indices"); - if (vertex_indices == nullptr) { - // The property name may be named either "vertex_indices" or "vertex_index". - vertex_indices = face_element->GetPropertyByName("vertex_index"); - } - if (vertex_indices == nullptr || !vertex_indices->is_list()) { - return Status(Status::DRACO_ERROR, "No faces defined"); - } - - PlyPropertyReader<PointIndex::ValueType> vertex_index_reader(vertex_indices); - Mesh::Face face; - FaceIndex face_index(0); - for (int i = 0; i < num_faces; ++i) { - const int64_t list_offset = vertex_indices->GetListEntryOffset(i); - const int64_t list_size = vertex_indices->GetListEntryNumValues(i); - // TODO(ostava): Assume triangular faces only for now. - if (list_size != 3) - continue; // All non-triangular faces are skipped. - for (int64_t c = 0; c < 3; ++c) - face[c] = - vertex_index_reader.ReadValue(static_cast<int>(list_offset + c)); - out_mesh_->SetFace(face_index, face); - face_index++; - } - out_mesh_->SetNumFaces(face_index.value()); - return OkStatus(); -} - -template <typename DataTypeT> -bool PlyDecoder::ReadPropertiesToAttribute( - const std::vector<const PlyProperty *> &properties, - PointAttribute *attribute, int num_vertices) { - std::vector<std::unique_ptr<PlyPropertyReader<DataTypeT>>> readers; - readers.reserve(properties.size()); - for (int prop = 0; prop < properties.size(); ++prop) { - readers.push_back(std::unique_ptr<PlyPropertyReader<DataTypeT>>( - new PlyPropertyReader<DataTypeT>(properties[prop]))); - } - std::vector<DataTypeT> memory(properties.size()); - for (PointIndex::ValueType i = 0; i < static_cast<uint32_t>(num_vertices); - ++i) { - for (int prop = 0; prop < properties.size(); ++prop) { - memory[prop] = readers[prop]->ReadValue(i); - } - attribute->SetAttributeValue(AttributeValueIndex(i), memory.data()); - } - return true; -} - -Status PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) { - if (vertex_element == nullptr) - return Status(Status::INVALID_PARAMETER, "vertex_element is null"); - // TODO(ostava): For now, try to load x,y,z vertices and red,green,blue,alpha - // colors. We need to add other properties later. - const PlyProperty *const x_prop = vertex_element->GetPropertyByName("x"); - const PlyProperty *const y_prop = vertex_element->GetPropertyByName("y"); - const PlyProperty *const z_prop = vertex_element->GetPropertyByName("z"); - if (!x_prop || !y_prop || !z_prop) { - // Currently, we require 3 vertex coordinates (this should be generalized - // later on). - return Status(Status::INVALID_PARAMETER, "x, y, or z property is missing"); - } - const PointIndex::ValueType num_vertices = vertex_element->num_entries(); - out_point_cloud_->set_num_points(num_vertices); - // Decode vertex positions. - { - // All properties must have the same type. - if (x_prop->data_type() != y_prop->data_type() || - y_prop->data_type() != z_prop->data_type()) { - return Status(Status::INVALID_PARAMETER, - "x, y, and z properties must have the same type"); - } - // TODO(ostava): For now assume the position types are float32 or int32. - const DataType dt = x_prop->data_type(); - if (dt != DT_FLOAT32 && dt != DT_INT32) - return Status(Status::INVALID_PARAMETER, - "x, y, and z properties must be of type float32 or int32"); - - GeometryAttribute va; - va.Init(GeometryAttribute::POSITION, nullptr, 3, dt, false, - DataTypeLength(dt) * 3, 0); - const int att_id = out_point_cloud_->AddAttribute(va, true, num_vertices); - std::vector<const PlyProperty *> properties; - properties.push_back(x_prop); - properties.push_back(y_prop); - properties.push_back(z_prop); - if (dt == DT_FLOAT32) { - ReadPropertiesToAttribute<float>( - properties, out_point_cloud_->attribute(att_id), num_vertices); - } else if (dt == DT_INT32) { - ReadPropertiesToAttribute<int32_t>( - properties, out_point_cloud_->attribute(att_id), num_vertices); - } - } - - // Decode normals if present. - const PlyProperty *const n_x_prop = vertex_element->GetPropertyByName("nx"); - const PlyProperty *const n_y_prop = vertex_element->GetPropertyByName("ny"); - const PlyProperty *const n_z_prop = vertex_element->GetPropertyByName("nz"); - if (n_x_prop != nullptr && n_y_prop != nullptr && n_z_prop != nullptr) { - // For now, all normal properties must be set and of type float32 - if (n_x_prop->data_type() == DT_FLOAT32 && - n_y_prop->data_type() == DT_FLOAT32 && - n_z_prop->data_type() == DT_FLOAT32) { - PlyPropertyReader<float> x_reader(n_x_prop); - PlyPropertyReader<float> y_reader(n_y_prop); - PlyPropertyReader<float> z_reader(n_z_prop); - GeometryAttribute va; - va.Init(GeometryAttribute::NORMAL, nullptr, 3, DT_FLOAT32, false, - sizeof(float) * 3, 0); - const int att_id = out_point_cloud_->AddAttribute(va, true, num_vertices); - for (PointIndex::ValueType i = 0; i < num_vertices; ++i) { - std::array<float, 3> val; - val[0] = x_reader.ReadValue(i); - val[1] = y_reader.ReadValue(i); - val[2] = z_reader.ReadValue(i); - out_point_cloud_->attribute(att_id)->SetAttributeValue( - AttributeValueIndex(i), &val[0]); - } - } - } - - // Decode color data if present. - int num_colors = 0; - const PlyProperty *const r_prop = vertex_element->GetPropertyByName("red"); - const PlyProperty *const g_prop = vertex_element->GetPropertyByName("green"); - const PlyProperty *const b_prop = vertex_element->GetPropertyByName("blue"); - const PlyProperty *const a_prop = vertex_element->GetPropertyByName("alpha"); - if (r_prop) - ++num_colors; - if (g_prop) - ++num_colors; - if (b_prop) - ++num_colors; - if (a_prop) - ++num_colors; - - if (num_colors) { - std::vector<std::unique_ptr<PlyPropertyReader<uint8_t>>> color_readers; - const PlyProperty *p; - if (r_prop) { - p = r_prop; - // TODO(ostava): For now ensure the data type of all components is uint8. - DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); - if (p->data_type() != DT_UINT8) - return Status(Status::INVALID_PARAMETER, - "Type of 'red' property must be uint8"); - color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( - new PlyPropertyReader<uint8_t>(p))); - } - if (g_prop) { - p = g_prop; - // TODO(ostava): For now ensure the data type of all components is uint8. - DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); - if (p->data_type() != DT_UINT8) - return Status(Status::INVALID_PARAMETER, - "Type of 'green' property must be uint8"); - color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( - new PlyPropertyReader<uint8_t>(p))); - } - if (b_prop) { - p = b_prop; - // TODO(ostava): For now ensure the data type of all components is uint8. - DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); - if (p->data_type() != DT_UINT8) - return Status(Status::INVALID_PARAMETER, - "Type of 'blue' property must be uint8"); - color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( - new PlyPropertyReader<uint8_t>(p))); - } - if (a_prop) { - p = a_prop; - // TODO(ostava): For now ensure the data type of all components is uint8. - DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8); - if (p->data_type() != DT_UINT8) - return Status(Status::INVALID_PARAMETER, - "Type of 'alpha' property must be uint8"); - color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>( - new PlyPropertyReader<uint8_t>(p))); - } - - GeometryAttribute va; - va.Init(GeometryAttribute::COLOR, nullptr, num_colors, DT_UINT8, true, - sizeof(uint8_t) * num_colors, 0); - const int32_t att_id = - out_point_cloud_->AddAttribute(va, true, num_vertices); - for (PointIndex::ValueType i = 0; i < num_vertices; ++i) { - std::array<uint8_t, 4> val; - for (int j = 0; j < num_colors; j++) { - val[j] = color_readers[j]->ReadValue(i); - } - out_point_cloud_->attribute(att_id)->SetAttributeValue( - AttributeValueIndex(i), &val[0]); - } - } - - return OkStatus(); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/ply_decoder.h b/extern/draco/dracoenc/src/draco/io/ply_decoder.h deleted file mode 100644 index 9e667ab192f..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_decoder.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_MESH_PLY_DECODER_H_ -#define DRACO_IO_MESH_PLY_DECODER_H_ - -#include <string> - -#include "draco/draco_features.h" - -#include "draco/core/decoder_buffer.h" -#include "draco/core/status.h" -#include "draco/io/ply_reader.h" -#include "draco/mesh/mesh.h" - -namespace draco { - -// Decodes a Wavefront OBJ file into draco::Mesh (or draco::PointCloud if the -// connectivity data is not needed). -// TODO(ostava): The current implementation assumes that the input vertices are -// defined with x, y, z properties. The decoder also reads uint8 red, green, -// blue, alpha color information, but all other attributes are ignored for now. -class PlyDecoder { - public: - PlyDecoder(); - - // Decodes an obj file stored in the input file. - Status DecodeFromFile(const std::string &file_name, Mesh *out_mesh); - Status DecodeFromFile(const std::string &file_name, - PointCloud *out_point_cloud); - - Status DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh); - Status DecodeFromBuffer(DecoderBuffer *buffer, PointCloud *out_point_cloud); - - protected: - Status DecodeInternal(); - DecoderBuffer *buffer() { return &buffer_; } - - private: - Status DecodeFaceData(const PlyElement *face_element); - Status DecodeVertexData(const PlyElement *vertex_element); - - template <typename DataTypeT> - bool ReadPropertiesToAttribute( - const std::vector<const PlyProperty *> &properties, - PointAttribute *attribute, int num_vertices); - - DecoderBuffer buffer_; - - // Data structure that stores the decoded data. |out_point_cloud_| must be - // always set but |out_mesh_| is optional. - Mesh *out_mesh_; - PointCloud *out_point_cloud_; -}; - -} // namespace draco - -#endif // DRACO_IO_MESH_PLY_DECODER_H_ diff --git a/extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc b/extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc deleted file mode 100644 index 647324ea904..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/ply_decoder.h" - -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" - -namespace draco { - -class PlyDecoderTest : public ::testing::Test { - protected: - template <class Geometry> - std::unique_ptr<Geometry> DecodePly(const std::string &file_name) const { - const std::string path = GetTestFileFullPath(file_name); - PlyDecoder decoder; - std::unique_ptr<Geometry> geometry(new Geometry()); - Status status = decoder.DecodeFromFile(path, geometry.get()); - if (!status.ok()) { - LOG(DRACO_ERROR) << "Failed to decode " << file_name << ": " << status; - return nullptr; - } - return geometry; - } - - void test_decoding(const std::string &file_name, int num_faces, - uint32_t num_points, std::unique_ptr<Mesh> *out_mesh) { - // Don't test mesh decoding when the input is point cloud. - if (num_faces > 0) { - std::unique_ptr<Mesh> mesh(DecodePly<Mesh>(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - ASSERT_EQ(mesh->num_faces(), num_faces); - if (out_mesh) - *out_mesh = std::move(mesh); - } - - const std::unique_ptr<PointCloud> pc(DecodePly<PointCloud>(file_name)); - ASSERT_NE(pc, nullptr) << "Failed to load test model " << file_name; - ASSERT_EQ(pc->num_points(), num_points); - } - void test_decoding(const std::string &file_name) { - const std::unique_ptr<Mesh> mesh(DecodePly<Mesh>(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name; - ASSERT_GT(mesh->num_faces(), 0); - - const std::unique_ptr<PointCloud> pc(DecodePly<PointCloud>(file_name)); - ASSERT_NE(pc, nullptr) << "Failed to load test model " << file_name; - ASSERT_GT(pc->num_points(), 0); - } -}; - -TEST_F(PlyDecoderTest, TestPlyDecoding) { - const std::string file_name = "test_pos_color.ply"; - test_decoding(file_name, 224, 114, nullptr); -} - -TEST_F(PlyDecoderTest, TestPlyNormals) { - const std::string file_name = "cube_att.ply"; - std::unique_ptr<Mesh> mesh; - test_decoding(file_name, 12, 3 * 8, &mesh); - ASSERT_NE(mesh, nullptr); - const int att_id = mesh->GetNamedAttributeId(GeometryAttribute::NORMAL); - ASSERT_GE(att_id, 0); - const PointAttribute *const att = mesh->attribute(att_id); - ASSERT_EQ(att->size(), 6); // 6 unique normal values. -} - -TEST_F(PlyDecoderTest, TestPlyDecodingAll) { - // test if we can read all ply that are currently in test folder. - test_decoding("bun_zipper.ply"); - // test_decoding("cube_att.ply"); // tested - test_decoding("test_extra_whitespace.ply"); - test_decoding("test_more_datatypes.ply"); - test_decoding("test_pos_color_ascii.ply"); - test_decoding("int_point_cloud.ply", 0, 16, nullptr); - // test_decoding("test_pos_color.ply"); // tested -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/ply_encoder.cc b/extern/draco/dracoenc/src/draco/io/ply_encoder.cc deleted file mode 100644 index cb25b21d4f8..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_encoder.cc +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/ply_encoder.h" - -#include <fstream> -#include <sstream> - -namespace draco { - -PlyEncoder::PlyEncoder() - : out_buffer_(nullptr), in_point_cloud_(nullptr), in_mesh_(nullptr) {} - -bool PlyEncoder::EncodeToFile(const PointCloud &pc, - const std::string &file_name) { - std::ofstream file(file_name, std::ios::binary); - if (!file) - return false; // File couldn't be opened. - // Encode the mesh into a buffer. - EncoderBuffer buffer; - if (!EncodeToBuffer(pc, &buffer)) - return false; - // Write the buffer into the file. - file.write(buffer.data(), buffer.size()); - return true; -} - -bool PlyEncoder::EncodeToFile(const Mesh &mesh, const std::string &file_name) { - in_mesh_ = &mesh; - return EncodeToFile(static_cast<const PointCloud &>(mesh), file_name); -} - -bool PlyEncoder::EncodeToBuffer(const PointCloud &pc, - EncoderBuffer *out_buffer) { - in_point_cloud_ = &pc; - out_buffer_ = out_buffer; - if (!EncodeInternal()) - return ExitAndCleanup(false); - return ExitAndCleanup(true); -} - -bool PlyEncoder::EncodeToBuffer(const Mesh &mesh, EncoderBuffer *out_buffer) { - in_mesh_ = &mesh; - return EncodeToBuffer(static_cast<const PointCloud &>(mesh), out_buffer); -} -bool PlyEncoder::EncodeInternal() { - // Write PLY header. - // TODO(ostava): Currently works only for xyz positions and rgb(a) colors. - std::stringstream out; - out << "ply" << std::endl; - out << "format binary_little_endian 1.0" << std::endl; - out << "element vertex " << in_point_cloud_->num_points() << std::endl; - - const int pos_att_id = - in_point_cloud_->GetNamedAttributeId(GeometryAttribute::POSITION); - int normal_att_id = - in_point_cloud_->GetNamedAttributeId(GeometryAttribute::NORMAL); - int tex_coord_att_id = - in_point_cloud_->GetNamedAttributeId(GeometryAttribute::TEX_COORD); - const int color_att_id = - in_point_cloud_->GetNamedAttributeId(GeometryAttribute::COLOR); - - if (pos_att_id < 0) - return false; - - // Ensure normals are 3 component. Don't encode them otherwise. - if (normal_att_id >= 0 && - in_point_cloud_->attribute(normal_att_id)->num_components() != 3) - normal_att_id = -1; - - // Ensure texture coordinates have only 2 components. Don't encode them - // otherwise. TODO(ostava): Add support for 3 component normals (uvw). - if (tex_coord_att_id >= 0 && - in_point_cloud_->attribute(tex_coord_att_id)->num_components() != 2) - tex_coord_att_id = -1; - - out << "property " << GetAttributeDataType(pos_att_id) << " x" << std::endl; - out << "property " << GetAttributeDataType(pos_att_id) << " y" << std::endl; - out << "property " << GetAttributeDataType(pos_att_id) << " z" << std::endl; - if (normal_att_id >= 0) { - out << "property " << GetAttributeDataType(normal_att_id) << " nx" - << std::endl; - out << "property " << GetAttributeDataType(normal_att_id) << " ny" - << std::endl; - out << "property " << GetAttributeDataType(normal_att_id) << " nz" - << std::endl; - } - if (color_att_id >= 0) { - const auto *const attribute = in_point_cloud_->attribute(color_att_id); - if (attribute->num_components() > 0) { - out << "property " << GetAttributeDataType(color_att_id) << " red" - << std::endl; - } - if (attribute->num_components() > 1) { - out << "property " << GetAttributeDataType(color_att_id) << " green" - << std::endl; - } - if (attribute->num_components() > 2) { - out << "property " << GetAttributeDataType(color_att_id) << " blue" - << std::endl; - } - if (attribute->num_components() > 3) { - out << "property " << GetAttributeDataType(color_att_id) << " alpha" - << std::endl; - } - } - if (in_mesh_) { - out << "element face " << in_mesh_->num_faces() << std::endl; - out << "property list uchar int vertex_indices" << std::endl; - if (tex_coord_att_id >= 0) { - // Texture coordinates are usually encoded in the property list (one value - // per corner). - out << "property list uchar " << GetAttributeDataType(tex_coord_att_id) - << " texcoord" << std::endl; - } - } - out << "end_header" << std::endl; - - // Not very efficient but the header should be small so just copy the stream - // to a string. - const std::string header_str = out.str(); - buffer()->Encode(header_str.data(), header_str.length()); - - // Store point attributes. - for (PointIndex v(0); v < in_point_cloud_->num_points(); ++v) { - const auto *const pos_att = in_point_cloud_->attribute(pos_att_id); - buffer()->Encode(pos_att->GetAddress(pos_att->mapped_index(v)), - pos_att->byte_stride()); - if (normal_att_id >= 0) { - const auto *const normal_att = in_point_cloud_->attribute(normal_att_id); - buffer()->Encode(normal_att->GetAddress(normal_att->mapped_index(v)), - normal_att->byte_stride()); - } - if (color_att_id >= 0) { - const auto *const color_att = in_point_cloud_->attribute(color_att_id); - buffer()->Encode(color_att->GetAddress(color_att->mapped_index(v)), - color_att->byte_stride()); - } - } - - if (in_mesh_) { - // Write face data. - for (FaceIndex i(0); i < in_mesh_->num_faces(); ++i) { - // Write the number of face indices (always 3). - buffer()->Encode(static_cast<uint8_t>(3)); - - const auto &f = in_mesh_->face(i); - buffer()->Encode(f[0]); - buffer()->Encode(f[1]); - buffer()->Encode(f[2]); - - if (tex_coord_att_id >= 0) { - // Two coordinates for every corner -> 6. - buffer()->Encode(static_cast<uint8_t>(6)); - - const auto *const tex_att = - in_point_cloud_->attribute(tex_coord_att_id); - for (int c = 0; c < 3; ++c) { - buffer()->Encode(tex_att->GetAddress(tex_att->mapped_index(f[c])), - tex_att->byte_stride()); - } - } - } - } - return true; -} - -bool PlyEncoder::ExitAndCleanup(bool return_value) { - in_mesh_ = nullptr; - in_point_cloud_ = nullptr; - out_buffer_ = nullptr; - return return_value; -} - -const char *PlyEncoder::GetAttributeDataType(int attribute) { - // TODO(ostava): Add support for more types. - switch (in_point_cloud_->attribute(attribute)->data_type()) { - case DT_FLOAT32: - return "float"; - case DT_UINT8: - return "uchar"; - case DT_INT32: - return "int"; - default: - break; - } - return nullptr; -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/ply_encoder.h b/extern/draco/dracoenc/src/draco/io/ply_encoder.h deleted file mode 100644 index 242bbd6d464..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_encoder.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_PLY_ENCODER_H_ -#define DRACO_IO_PLY_ENCODER_H_ - -#include "draco/core/encoder_buffer.h" -#include "draco/mesh/mesh.h" - -namespace draco { - -// Class for encoding draco::Mesh or draco::PointCloud into the PLY file format. -class PlyEncoder { - public: - PlyEncoder(); - - // Encodes the mesh or a point cloud and saves it into a file. - // Returns false when either the encoding failed or when the file couldn't be - // opened. - bool EncodeToFile(const PointCloud &pc, const std::string &file_name); - bool EncodeToFile(const Mesh &mesh, const std::string &file_name); - - // Encodes the mesh or the point cloud into a buffer. - bool EncodeToBuffer(const PointCloud &pc, EncoderBuffer *out_buffer); - bool EncodeToBuffer(const Mesh &mesh, EncoderBuffer *out_buffer); - - protected: - bool EncodeInternal(); - EncoderBuffer *buffer() const { return out_buffer_; } - bool ExitAndCleanup(bool return_value); - - private: - const char *GetAttributeDataType(int attribute); - - EncoderBuffer *out_buffer_; - - const PointCloud *in_point_cloud_; - const Mesh *in_mesh_; -}; - -} // namespace draco - -#endif // DRACO_IO_PLY_ENCODER_H_ diff --git a/extern/draco/dracoenc/src/draco/io/ply_property_reader.h b/extern/draco/dracoenc/src/draco/io/ply_property_reader.h deleted file mode 100644 index efb8a3a1f9d..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_property_reader.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_PLY_PROPERTY_READER_H_ -#define DRACO_IO_PLY_PROPERTY_READER_H_ - -#include <functional> - -#include "draco/io/ply_reader.h" - -namespace draco { - -// Class for reading PlyProperty with a given type, performing data conversion -// if necessary. -template <typename ReadTypeT> -class PlyPropertyReader { - public: - explicit PlyPropertyReader(const PlyProperty *property) - : property_(property) { - // Find the suitable function for converting values. - switch (property->data_type()) { - case DT_UINT8: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<uint8_t>(val_id); - }; - break; - case DT_INT8: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<int8_t>(val_id); - }; - break; - case DT_UINT16: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<uint16_t>(val_id); - }; - break; - case DT_INT16: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<int16_t>(val_id); - }; - break; - case DT_UINT32: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<uint32_t>(val_id); - }; - break; - case DT_INT32: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<int32_t>(val_id); - }; - break; - case DT_FLOAT32: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<float>(val_id); - }; - break; - case DT_FLOAT64: - convert_value_func_ = [=](int val_id) { - return this->ConvertValue<double>(val_id); - }; - break; - default: - break; - } - } - - ReadTypeT ReadValue(int value_id) const { - return convert_value_func_(value_id); - } - - private: - template <typename SourceTypeT> - ReadTypeT ConvertValue(int value_id) const { - const void *const address = property_->GetDataEntryAddress(value_id); - const SourceTypeT src_val = *reinterpret_cast<const SourceTypeT *>(address); - return static_cast<ReadTypeT>(src_val); - } - - const PlyProperty *property_; - std::function<ReadTypeT(int)> convert_value_func_; -}; - -} // namespace draco - -#endif // DRACO_IO_PLY_PROPERTY_READER_H_ diff --git a/extern/draco/dracoenc/src/draco/io/ply_property_writer.h b/extern/draco/dracoenc/src/draco/io/ply_property_writer.h deleted file mode 100644 index 4f243b2860f..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_property_writer.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_PLY_PROPERTY_WRITER_H_ -#define DRACO_IO_PLY_PROPERTY_WRITER_H_ - -#include <functional> - -#include "draco/io/ply_reader.h" - -namespace draco { - -// Class for writing PlyProperty with a given type, performing data conversion -// if necessary. -template <typename WriteTypeT> -class PlyPropertyWriter { - public: - explicit PlyPropertyWriter(PlyProperty *property) : property_(property) { - // Find the suitable function for converting values. - switch (property->data_type()) { - case DT_UINT8: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<uint8_t>(val); - }; - break; - case DT_INT8: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<int8_t>(val); - }; - break; - case DT_UINT16: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<uint16_t>(val); - }; - break; - case DT_INT16: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<int16_t>(val); - }; - break; - case DT_UINT32: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<uint32_t>(val); - }; - break; - case DT_INT32: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<int32_t>(val); - }; - break; - case DT_FLOAT32: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<float>(val); - }; - break; - case DT_FLOAT64: - convert_value_func_ = [=](WriteTypeT val) { - return this->ConvertValue<double>(val); - }; - break; - default: - break; - } - } - - void PushBackValue(WriteTypeT value) const { - return convert_value_func_(value); - } - - private: - template <typename SourceTypeT> - void ConvertValue(WriteTypeT value) const { - const SourceTypeT src_val = static_cast<SourceTypeT>(value); - property_->push_back_value(&src_val); - } - - PlyProperty *property_; - std::function<void(WriteTypeT)> convert_value_func_; -}; - -} // namespace draco - -#endif // DRACO_IO_PLY_PROPERTY_WRITER_H_ diff --git a/extern/draco/dracoenc/src/draco/io/ply_reader.cc b/extern/draco/dracoenc/src/draco/io/ply_reader.cc deleted file mode 100644 index 772c4381176..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_reader.cc +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/ply_reader.h" - -#include <array> -#include <regex> - -#include "draco/core/status.h" -#include "draco/io/parser_utils.h" -#include "draco/io/ply_property_writer.h" - -namespace draco { - -PlyProperty::PlyProperty(const std::string &name, DataType data_type, - DataType list_type) - : name_(name), data_type_(data_type), list_data_type_(list_type) { - data_type_num_bytes_ = DataTypeLength(data_type); - list_data_type_num_bytes_ = DataTypeLength(list_type); -} - -PlyElement::PlyElement(const std::string &name, int64_t num_entries) - : name_(name), num_entries_(num_entries) {} - -PlyReader::PlyReader() : format_(kLittleEndian) {} - -Status PlyReader::Read(DecoderBuffer *buffer) { - std::string value; - // The first line needs to by "ply". - if (!parser::ParseString(buffer, &value) || value != "ply") { - return Status(Status::INVALID_PARAMETER, "Not a valid ply file"); - } - parser::SkipLine(buffer); - - // The second line needs to be the format of the ply file. - parser::ParseLine(buffer, &value); - std::string format, version; - const std::vector<std::string> words = SplitWords(value); - if (words.size() >= 3 && words[0] == "format") { - format = words[1]; - version = words[2]; - } else { - return Status(Status::INVALID_PARAMETER, "Missing or wrong format line"); - } - if (version != "1.0") { - return Status(Status::UNSUPPORTED_VERSION, "Unsupported PLY version"); - } - if (format == "binary_big_endian") { - return Status(Status::UNSUPPORTED_VERSION, - "Unsupported format. Currently we support only ascii and" - " binary_little_endian format."); - } - if (format == "ascii") { - format_ = kAscii; - } else { - format_ = kLittleEndian; - } - DRACO_RETURN_IF_ERROR(ParseHeader(buffer)); - if (!ParsePropertiesData(buffer)) { - return Status(Status::INVALID_PARAMETER, "Couldn't parse properties"); - } - return OkStatus(); -} - -Status PlyReader::ParseHeader(DecoderBuffer *buffer) { - while (true) { - DRACO_ASSIGN_OR_RETURN(bool end, ParseEndHeader(buffer)); - if (end) - break; - if (ParseElement(buffer)) - continue; - DRACO_ASSIGN_OR_RETURN(bool property_parsed, ParseProperty(buffer)); - if (property_parsed) - continue; - parser::SkipLine(buffer); - } - return OkStatus(); -} - -StatusOr<bool> PlyReader::ParseEndHeader(DecoderBuffer *buffer) { - parser::SkipWhitespace(buffer); - std::array<char, 10> c; - if (!buffer->Peek(&c)) { - return Status(Status::INVALID_PARAMETER, - "End of file reached before the end_header"); - } - if (std::memcmp(&c[0], "end_header", 10) != 0) - return false; - parser::SkipLine(buffer); - return true; -} - -bool PlyReader::ParseElement(DecoderBuffer *buffer) { - DecoderBuffer line_buffer(*buffer); - std::string line; - parser::ParseLine(&line_buffer, &line); - - std::string element_name; - int64_t count; - const std::vector<std::string> words = SplitWords(line); - if (words.size() >= 3 && words[0] == "element") { - element_name = words[1]; - const std::string count_str = words[2]; - count = strtoll(count_str.c_str(), NULL, 10); - } else { - return false; - } - element_index_[element_name] = static_cast<uint32_t>(elements_.size()); - elements_.emplace_back(PlyElement(element_name, count)); - *buffer = line_buffer; - return true; -} - -StatusOr<bool> PlyReader::ParseProperty(DecoderBuffer *buffer) { - if (elements_.empty()) - return false; // Ignore properties if there is no active element. - DecoderBuffer line_buffer(*buffer); - std::string line; - parser::ParseLine(&line_buffer, &line); - - std::string data_type_str, list_type_str, property_name; - bool property_search = false; - const std::vector<std::string> words = SplitWords(line); - if (words.size() >= 3 && words[0] == "property" && words[1] != "list") { - property_search = true; - data_type_str = words[1]; - property_name = words[2]; - } - - bool property_list_search = false; - if (words.size() >= 5 && words[0] == "property" && words[1] == "list") { - property_list_search = true; - list_type_str = words[2]; - data_type_str = words[3]; - property_name = words[4]; - } - if (!property_search && !property_list_search) { - return false; - } - const DataType data_type = GetDataTypeFromString(data_type_str); - if (data_type == DT_INVALID) { - return Status(Status::INVALID_PARAMETER, "Wrong property data type"); - } - DataType list_type = DT_INVALID; - if (property_list_search) { - list_type = GetDataTypeFromString(list_type_str); - if (list_type == DT_INVALID) { - return Status(Status::INVALID_PARAMETER, "Wrong property list type"); - } - } - elements_.back().AddProperty( - PlyProperty(property_name, data_type, list_type)); - *buffer = line_buffer; - return true; -} - -bool PlyReader::ParsePropertiesData(DecoderBuffer *buffer) { - for (int i = 0; i < static_cast<int>(elements_.size()); ++i) { - if (format_ == kLittleEndian) { - if (!ParseElementData(buffer, i)) { - return false; - } - } else if (format_ == kAscii) { - if (!ParseElementDataAscii(buffer, i)) { - return false; - } - } - } - return true; -} - -bool PlyReader::ParseElementData(DecoderBuffer *buffer, int element_index) { - PlyElement &element = elements_[element_index]; - for (int entry = 0; entry < element.num_entries(); ++entry) { - for (int i = 0; i < element.num_properties(); ++i) { - PlyProperty &prop = element.property(i); - if (prop.is_list()) { - // Parse the number of entries for the list element. - int64_t num_entries = 0; - buffer->Decode(&num_entries, prop.list_data_type_num_bytes()); - // Store offset to the main data entry. - prop.list_data_.push_back(prop.data_.size() / - prop.data_type_num_bytes_); - // Store the number of entries. - prop.list_data_.push_back(num_entries); - // Read and store the actual property data - const int64_t num_bytes_to_read = - prop.data_type_num_bytes() * num_entries; - prop.data_.insert(prop.data_.end(), buffer->data_head(), - buffer->data_head() + num_bytes_to_read); - buffer->Advance(num_bytes_to_read); - } else { - // Non-list property - prop.data_.insert(prop.data_.end(), buffer->data_head(), - buffer->data_head() + prop.data_type_num_bytes()); - buffer->Advance(prop.data_type_num_bytes()); - } - } - } - return true; -} - -bool PlyReader::ParseElementDataAscii(DecoderBuffer *buffer, - int element_index) { - PlyElement &element = elements_[element_index]; - for (int entry = 0; entry < element.num_entries(); ++entry) { - for (int i = 0; i < element.num_properties(); ++i) { - PlyProperty &prop = element.property(i); - PlyPropertyWriter<double> prop_writer(&prop); - int32_t num_entries = 1; - if (prop.is_list()) { - parser::SkipWhitespace(buffer); - // Parse the number of entries for the list element. - if (!parser::ParseSignedInt(buffer, &num_entries)) - return false; - - // Store offset to the main data entry. - prop.list_data_.push_back(prop.data_.size() / - prop.data_type_num_bytes_); - // Store the number of entries. - prop.list_data_.push_back(num_entries); - } - // Read and store the actual property data. - for (int v = 0; v < num_entries; ++v) { - parser::SkipWhitespace(buffer); - if (prop.data_type() == DT_FLOAT32 || prop.data_type() == DT_FLOAT64) { - float val; - if (!parser::ParseFloat(buffer, &val)) - return false; - prop_writer.PushBackValue(val); - } else { - int32_t val; - if (!parser::ParseSignedInt(buffer, &val)) - return false; - prop_writer.PushBackValue(val); - } - } - } - } - return true; -} - -std::vector<std::string> PlyReader::SplitWords(const std::string &line) { - std::vector<std::string> output; - std::string::size_type start = 0; - std::string::size_type end = 0; - - // Check for isspace chars. - 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(), 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(), isspace)) - output.push_back(last_word); - return output; -} - -DataType PlyReader::GetDataTypeFromString(const std::string &name) const { - if (name == "char" || name == "int8") - return DT_INT8; - if (name == "uchar" || name == "uint8") - return DT_UINT8; - if (name == "short" || name == "int16") - return DT_INT16; - if (name == "ushort" || name == "uint16") - return DT_UINT16; - if (name == "int" || name == "int32") - return DT_INT32; - if (name == "uint" || name == "uint32") - return DT_UINT32; - if (name == "float" || name == "float32") - return DT_FLOAT32; - if (name == "double" || name == "float64") { - return DT_FLOAT64; - } - return DT_INVALID; -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/ply_reader.h b/extern/draco/dracoenc/src/draco/io/ply_reader.h deleted file mode 100644 index 845ef2326ae..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_reader.h +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// File contains helper classes used for parsing of PLY files. The classes are -// used by the PlyDecoder (ply_decoder.h) to read a point cloud or mesh from a -// source PLY file. -// TODO(ostava): Currently, we support only binary PLYs encoded in the little -// endian format ("format binary_little_endian 1.0"). - -#ifndef DRACO_IO_PLY_READER_H_ -#define DRACO_IO_PLY_READER_H_ - -#include <map> -#include <vector> - -#include "draco/core/decoder_buffer.h" -#include "draco/core/draco_types.h" -#include "draco/core/status.h" -#include "draco/core/status_or.h" - -namespace draco { - -// A single PLY property of a given PLY element. For "vertex" element this can -// contain data such as "x", "y", or "z" coordinate of the vertex, while for -// "face" element this usually contains corner indices. -class PlyProperty { - public: - friend class PlyReader; - - PlyProperty(const std::string &name, DataType data_type, DataType list_type); - void ReserveData(int num_entries) { - data_.reserve(DataTypeLength(data_type_) * num_entries); - } - - int64_t GetListEntryOffset(int entry_id) const { - return list_data_[entry_id * 2]; - } - int64_t GetListEntryNumValues(int entry_id) const { - return list_data_[entry_id * 2 + 1]; - } - const void *GetDataEntryAddress(int entry_id) const { - return data_.data() + entry_id * data_type_num_bytes_; - } - void push_back_value(const void *data) { - data_.insert(data_.end(), static_cast<const uint8_t *>(data), - static_cast<const uint8_t *>(data) + data_type_num_bytes_); - } - - const std::string &name() const { return name_; } - bool is_list() const { return list_data_type_ != DT_INVALID; } - DataType data_type() const { return data_type_; } - int data_type_num_bytes() const { return data_type_num_bytes_; } - DataType list_data_type() const { return list_data_type_; } - int list_data_type_num_bytes() const { return list_data_type_num_bytes_; } - - private: - std::string name_; - std::vector<uint8_t> data_; - // List data contain pairs of <offset, number_of_values> - std::vector<int64_t> list_data_; - DataType data_type_; - int data_type_num_bytes_; - DataType list_data_type_; - int list_data_type_num_bytes_; -}; - -// A single PLY element such as "vertex" or "face". Each element can store -// arbitrary properties such as vertex coordinates or face indices. -class PlyElement { - public: - PlyElement(const std::string &name, int64_t num_entries); - void AddProperty(const PlyProperty &prop) { - property_index_[prop.name()] = static_cast<int>(properties_.size()); - properties_.emplace_back(prop); - if (!properties_.back().is_list()) - properties_.back().ReserveData(static_cast<int>(num_entries_)); - } - - const PlyProperty *GetPropertyByName(const std::string &name) const { - const auto it = property_index_.find(name); - if (it != property_index_.end()) - return &properties_[it->second]; - return nullptr; - } - - int num_properties() const { return static_cast<int>(properties_.size()); } - int num_entries() const { return static_cast<int>(num_entries_); } - const PlyProperty &property(int prop_index) const { - return properties_[prop_index]; - } - PlyProperty &property(int prop_index) { return properties_[prop_index]; } - - private: - std::string name_; - int64_t num_entries_; - std::vector<PlyProperty> properties_; - std::map<std::string, int> property_index_; -}; - -// Class responsible for parsing PLY data. It produces a list of PLY elements -// and their properties that can be used to construct a mesh or a point cloud. -class PlyReader { - public: - PlyReader(); - Status Read(DecoderBuffer *buffer); - - const PlyElement *GetElementByName(const std::string &name) const { - const auto it = element_index_.find(name); - if (it != element_index_.end()) - return &elements_[it->second]; - return nullptr; - } - - int num_elements() const { return static_cast<int>(elements_.size()); } - const PlyElement &element(int element_index) const { - return elements_[element_index]; - } - - private: - enum Format { kLittleEndian = 0, kAscii }; - - Status ParseHeader(DecoderBuffer *buffer); - StatusOr<bool> ParseEndHeader(DecoderBuffer *buffer); - bool ParseElement(DecoderBuffer *buffer); - StatusOr<bool> ParseProperty(DecoderBuffer *buffer); - bool ParsePropertiesData(DecoderBuffer *buffer); - bool ParseElementData(DecoderBuffer *buffer, int element_index); - bool ParseElementDataAscii(DecoderBuffer *buffer, int element_index); - - // Splits |line| by whitespace characters. - std::vector<std::string> SplitWords(const std::string &line); - DataType GetDataTypeFromString(const std::string &name) const; - - std::vector<PlyElement> elements_; - std::map<std::string, int> element_index_; - Format format_; -}; - -} // namespace draco - -#endif // DRACO_IO_PLY_READER_H_ diff --git a/extern/draco/dracoenc/src/draco/io/ply_reader_test.cc b/extern/draco/dracoenc/src/draco/io/ply_reader_test.cc deleted file mode 100644 index 6804dc33de3..00000000000 --- a/extern/draco/dracoenc/src/draco/io/ply_reader_test.cc +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/ply_reader.h" - -#include <fstream> - -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/ply_property_reader.h" - -namespace draco { - -class PlyReaderTest : public ::testing::Test { - protected: - std::vector<char> ReadPlyFile(const std::string &file_name) const { - const std::string path = GetTestFileFullPath(file_name); - std::ifstream file(path.c_str(), std::ios::binary); - if (!file) - return std::vector<char>(); - auto is_size = file.tellg(); - file.seekg(0, std::ios::end); - is_size = file.tellg() - is_size; - file.seekg(0, std::ios::beg); - std::vector<char> data(is_size); - file.read(&data[0], is_size); - return data; - } -}; - -TEST_F(PlyReaderTest, TestReader) { - const std::string file_name = "test_pos_color.ply"; - const std::vector<char> data = ReadPlyFile(file_name); - DecoderBuffer buf; - buf.Init(data.data(), data.size()); - PlyReader reader; - Status status = reader.Read(&buf); - ASSERT_TRUE(status.ok()) << status; - ASSERT_EQ(reader.num_elements(), 2); - ASSERT_EQ(reader.element(0).num_properties(), 7); - ASSERT_EQ(reader.element(1).num_properties(), 1); - ASSERT_TRUE(reader.element(1).property(0).is_list()); - - ASSERT_TRUE(reader.element(0).GetPropertyByName("red") != nullptr); - const PlyProperty *const prop = reader.element(0).GetPropertyByName("red"); - PlyPropertyReader<uint8_t> reader_uint8(prop); - PlyPropertyReader<uint32_t> reader_uint32(prop); - PlyPropertyReader<float> reader_float(prop); - for (int i = 0; i < reader.element(0).num_entries(); ++i) { - ASSERT_EQ(reader_uint8.ReadValue(i), reader_uint32.ReadValue(i)); - ASSERT_EQ(reader_uint8.ReadValue(i), reader_float.ReadValue(i)); - } -} - -TEST_F(PlyReaderTest, TestReaderAscii) { - const std::string file_name = "test_pos_color.ply"; - const std::vector<char> data = ReadPlyFile(file_name); - DecoderBuffer buf; - buf.Init(data.data(), data.size()); - PlyReader reader; - Status status = reader.Read(&buf); - ASSERT_TRUE(status.ok()) << status; - - const std::string file_name_ascii = "test_pos_color_ascii.ply"; - const std::vector<char> data_ascii = ReadPlyFile(file_name_ascii); - buf.Init(data_ascii.data(), data_ascii.size()); - PlyReader reader_ascii; - status = reader_ascii.Read(&buf); - ASSERT_TRUE(status.ok()) << status; - ASSERT_EQ(reader.num_elements(), reader_ascii.num_elements()); - ASSERT_EQ(reader.element(0).num_properties(), - reader_ascii.element(0).num_properties()); - - ASSERT_TRUE(reader.element(0).GetPropertyByName("x") != nullptr); - const PlyProperty *const prop = reader.element(0).GetPropertyByName("x"); - const PlyProperty *const prop_ascii = - reader_ascii.element(0).GetPropertyByName("x"); - PlyPropertyReader<float> reader_float(prop); - PlyPropertyReader<float> reader_float_ascii(prop_ascii); - for (int i = 0; i < reader.element(0).num_entries(); ++i) { - ASSERT_NEAR(reader_float.ReadValue(i), reader_float_ascii.ReadValue(i), - 1e-4f); - } -} - -TEST_F(PlyReaderTest, TestReaderExtraWhitespace) { - const std::string file_name = "test_extra_whitespace.ply"; - const std::vector<char> data = ReadPlyFile(file_name); - DecoderBuffer buf; - buf.Init(data.data(), data.size()); - PlyReader reader; - Status status = reader.Read(&buf); - ASSERT_TRUE(status.ok()) << status; - - ASSERT_EQ(reader.num_elements(), 2); - ASSERT_EQ(reader.element(0).num_properties(), 7); - ASSERT_EQ(reader.element(1).num_properties(), 1); - ASSERT_TRUE(reader.element(1).property(0).is_list()); - - ASSERT_TRUE(reader.element(0).GetPropertyByName("red") != nullptr); - const PlyProperty *const prop = reader.element(0).GetPropertyByName("red"); - PlyPropertyReader<uint8_t> reader_uint8(prop); - PlyPropertyReader<uint32_t> reader_uint32(prop); - PlyPropertyReader<float> reader_float(prop); - for (int i = 0; i < reader.element(0).num_entries(); ++i) { - ASSERT_EQ(reader_uint8.ReadValue(i), reader_uint32.ReadValue(i)); - ASSERT_EQ(reader_uint8.ReadValue(i), reader_float.ReadValue(i)); - } -} - -TEST_F(PlyReaderTest, TestReaderMoreDataTypes) { - const std::string file_name = "test_more_datatypes.ply"; - const std::vector<char> data = ReadPlyFile(file_name); - DecoderBuffer buf; - buf.Init(data.data(), data.size()); - PlyReader reader; - Status status = reader.Read(&buf); - ASSERT_TRUE(status.ok()) << status; - - ASSERT_EQ(reader.num_elements(), 2); - ASSERT_EQ(reader.element(0).num_properties(), 7); - ASSERT_EQ(reader.element(1).num_properties(), 1); - ASSERT_TRUE(reader.element(1).property(0).is_list()); - - ASSERT_TRUE(reader.element(0).GetPropertyByName("red") != nullptr); - const PlyProperty *const prop = reader.element(0).GetPropertyByName("red"); - PlyPropertyReader<uint8_t> reader_uint8(prop); - PlyPropertyReader<uint32_t> reader_uint32(prop); - PlyPropertyReader<float> reader_float(prop); - for (int i = 0; i < reader.element(0).num_entries(); ++i) { - ASSERT_EQ(reader_uint8.ReadValue(i), reader_uint32.ReadValue(i)); - ASSERT_EQ(reader_uint8.ReadValue(i), reader_float.ReadValue(i)); - } -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/point_cloud_io.cc b/extern/draco/dracoenc/src/draco/io/point_cloud_io.cc deleted file mode 100644 index e91142eaaea..00000000000 --- a/extern/draco/dracoenc/src/draco/io/point_cloud_io.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/point_cloud_io.h" - -#include <fstream> - -#include "draco/io/obj_decoder.h" -#include "draco/io/parser_utils.h" -#include "draco/io/ply_decoder.h" - -namespace draco { - -StatusOr<std::unique_ptr<PointCloud>> ReadPointCloudFromFile( - const std::string &file_name) { - std::unique_ptr<PointCloud> pc(new PointCloud()); - // Analyze file extension. - const std::string extension = parser::ToLower( - file_name.size() >= 4 ? file_name.substr(file_name.size() - 4) - : file_name); - if (extension == ".obj") { - // Wavefront OBJ file format. - ObjDecoder obj_decoder; - const Status obj_status = obj_decoder.DecodeFromFile(file_name, pc.get()); - if (!obj_status.ok()) - return obj_status; - return std::move(pc); - } - if (extension == ".ply") { - // Wavefront PLY file format. - PlyDecoder ply_decoder; - DRACO_RETURN_IF_ERROR(ply_decoder.DecodeFromFile(file_name, pc.get())); - return std::move(pc); - } - - // Otherwise not an obj file. Assume the file was encoded with one of the - // draco encoding methods. - std::ifstream is(file_name.c_str(), std::ios::binary); - if (!is) - return Status(Status::DRACO_ERROR, "Invalid input stream."); - if (!ReadPointCloudFromStream(&pc, is).good()) - return Status(Status::DRACO_ERROR, - "Unknown error."); // Error reading the stream. - return std::move(pc); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/io/point_cloud_io.h b/extern/draco/dracoenc/src/draco/io/point_cloud_io.h deleted file mode 100644 index 4e1eb359644..00000000000 --- a/extern/draco/dracoenc/src/draco/io/point_cloud_io.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef DRACO_IO_POINT_CLOUD_IO_H_ -#define DRACO_IO_POINT_CLOUD_IO_H_ - -#include "draco/compression/config/compression_shared.h" -#include "draco/compression/decode.h" -#include "draco/compression/expert_encode.h" - -namespace draco { - -template <typename OutStreamT> -OutStreamT WritePointCloudIntoStream(const PointCloud *pc, OutStreamT &&os, - PointCloudEncodingMethod method, - const EncoderOptions &options) { - EncoderBuffer buffer; - EncoderOptions local_options = options; - ExpertEncoder encoder(*pc); - encoder.Reset(local_options); - encoder.SetEncodingMethod(method); - if (!encoder.EncodeToBuffer(&buffer).ok()) { - os.setstate(std::ios_base::badbit); - return os; - } - - os.write(static_cast<const char *>(buffer.data()), buffer.size()); - - return os; -} - -template <typename OutStreamT> -OutStreamT WritePointCloudIntoStream(const PointCloud *pc, OutStreamT &&os, - PointCloudEncodingMethod method) { - const EncoderOptions options = EncoderOptions::CreateDefaultOptions(); - return WritePointCloudIntoStream(pc, os, method, options); -} - -template <typename OutStreamT> -OutStreamT &WritePointCloudIntoStream(const PointCloud *pc, OutStreamT &&os) { - return WritePointCloudIntoStream(pc, os, POINT_CLOUD_SEQUENTIAL_ENCODING); -} - -template <typename InStreamT> -InStreamT &ReadPointCloudFromStream(std::unique_ptr<PointCloud> *point_cloud, - InStreamT &&is) { - // Determine size of stream and write into a vector - const auto start_pos = is.tellg(); - is.seekg(0, std::ios::end); - const std::streampos is_size = is.tellg() - start_pos; - is.seekg(start_pos); - std::vector<char> data(is_size); - is.read(&data[0], is_size); - - // Create a point cloud from that data. - DecoderBuffer buffer; - buffer.Init(&data[0], data.size()); - Decoder decoder; - auto statusor = decoder.DecodePointCloudFromBuffer(&buffer); - *point_cloud = std::move(statusor).value(); - if (!statusor.ok() || *point_cloud == nullptr) { - is.setstate(std::ios_base::badbit); - } - - return is; -} - -// Reads a point cloud from a file. The function automatically chooses the -// correct decoder based on the extension of the files. Currently, .obj and .ply -// files are supported. Other file extensions are processed by the default -// draco::PointCloudDecoder. -// Returns nullptr with an error status if the decoding failed. -StatusOr<std::unique_ptr<PointCloud>> ReadPointCloudFromFile( - const std::string &file_name); - -} // namespace draco - -#endif // DRACO_IO_POINT_CLOUD_IO_H_ diff --git a/extern/draco/dracoenc/src/draco/io/point_cloud_io_test.cc b/extern/draco/dracoenc/src/draco/io/point_cloud_io_test.cc deleted file mode 100644 index 73674d06f55..00000000000 --- a/extern/draco/dracoenc/src/draco/io/point_cloud_io_test.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/io/point_cloud_io.h" - -#include <sstream> - -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/obj_decoder.h" - -namespace draco { - -class IoPointCloudIoTest : public ::testing::Test { - protected: - void test_compression_method(PointCloudEncodingMethod method, - int expected_num_attributes, - const std::string &file_name) { - const std::unique_ptr<PointCloud> encoded_pc = - ReadPointCloudFromTestFile(file_name); - ASSERT_NE(encoded_pc, nullptr) << "Failed to load test model " << file_name; - ASSERT_GE(encoded_pc->num_attributes(), expected_num_attributes) - << "Failed to load test model: " << file_name - << " wrong number of attributes" << std::endl; - - // Set quantization. - EncoderOptions options = EncoderOptions::CreateDefaultOptions(); - for (int i = 0; i <= GeometryAttribute::NAMED_ATTRIBUTES_COUNT; i++) { - options.SetAttributeInt(GeometryAttribute::Type(i), "quantization_bits", - 14); - } - - std::stringstream ss; - WritePointCloudIntoStream(encoded_pc.get(), ss, method, options); - ASSERT_TRUE(ss.good()); - - std::unique_ptr<PointCloud> decoded_pc; - ReadPointCloudFromStream(&decoded_pc, ss); - ASSERT_TRUE(ss.good()); - - for (int i = 0; i <= GeometryAttribute::NAMED_ATTRIBUTES_COUNT; i++) { - ASSERT_EQ(encoded_pc->NumNamedAttributes(GeometryAttribute::Type(i)), - decoded_pc->NumNamedAttributes(GeometryAttribute::Type(i))); - } - - ASSERT_EQ(encoded_pc->num_points(), decoded_pc->num_points()); - } -}; - -TEST_F(IoPointCloudIoTest, EncodeSequentialPointCloudTestNmObj) { - test_compression_method(POINT_CLOUD_SEQUENTIAL_ENCODING, 2, "test_nm.obj"); -} -TEST_F(IoPointCloudIoTest, EncodeSequentialPointCloudTestPosObj) { - test_compression_method(POINT_CLOUD_SEQUENTIAL_ENCODING, 1, - "point_cloud_test_pos.obj"); -} -TEST_F(IoPointCloudIoTest, EncodeSequentialPointCloudTestPosPly) { - test_compression_method(POINT_CLOUD_SEQUENTIAL_ENCODING, 1, - "point_cloud_test_pos.ply"); -} -TEST_F(IoPointCloudIoTest, EncodeSequentialPointCloudTestPosNormObj) { - test_compression_method(POINT_CLOUD_SEQUENTIAL_ENCODING, 2, - "point_cloud_test_pos_norm.obj"); -} -TEST_F(IoPointCloudIoTest, EncodeSequentialPointCloudTestPosNormPly) { - test_compression_method(POINT_CLOUD_SEQUENTIAL_ENCODING, 2, - "point_cloud_test_pos_norm.ply"); -} - -TEST_F(IoPointCloudIoTest, EncodeKdTreePointCloudTestPosObj) { - test_compression_method(POINT_CLOUD_KD_TREE_ENCODING, 1, - "point_cloud_test_pos.obj"); -} -TEST_F(IoPointCloudIoTest, EncodeKdTreePointCloudTestPosPly) { - test_compression_method(POINT_CLOUD_KD_TREE_ENCODING, 1, - "point_cloud_test_pos.ply"); -} - -TEST_F(IoPointCloudIoTest, ObjFileInput) { - // Tests whether loading obj point clouds from files works as expected. - const std::unique_ptr<PointCloud> pc = - ReadPointCloudFromTestFile("test_nm.obj"); - ASSERT_NE(pc, nullptr) << "Failed to load the obj point cloud."; - EXPECT_EQ(pc->num_points(), 97) << "Obj point cloud not loaded properly."; -} - -// Test if we handle wrong input for all file extensions. -TEST_F(IoPointCloudIoTest, WrongFileObj) { - const std::unique_ptr<PointCloud> pc = - ReadPointCloudFromTestFile("wrong_file_name.obj"); - ASSERT_EQ(pc, nullptr); -} -TEST_F(IoPointCloudIoTest, WrongFilePly) { - const std::unique_ptr<PointCloud> pc = - ReadPointCloudFromTestFile("wrong_file_name.ply"); - ASSERT_EQ(pc, nullptr); -} -TEST_F(IoPointCloudIoTest, WrongFile) { - const std::unique_ptr<PointCloud> pc = - ReadPointCloudFromTestFile("wrong_file_name"); - ASSERT_EQ(pc, nullptr); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_are_equivalent_test.cc b/extern/draco/dracoenc/src/draco/mesh/mesh_are_equivalent_test.cc deleted file mode 100644 index ff633bc73d1..00000000000 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_are_equivalent_test.cc +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/mesh/mesh_are_equivalent.h" - -#include <sstream> - -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" -#include "draco/io/mesh_io.h" -#include "draco/io/obj_decoder.h" -#include "draco/mesh/mesh.h" - -namespace draco { - -class MeshAreEquivalentTest : public ::testing::Test {}; - -TEST_F(MeshAreEquivalentTest, TestOnIndenticalMesh) { - const std::string file_name = "test_nm.obj"; - const std::unique_ptr<Mesh> mesh(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh, nullptr) << "Failed to load test model." << file_name; - MeshAreEquivalent equiv; - ASSERT_TRUE(equiv(*mesh, *mesh)); -} - -TEST_F(MeshAreEquivalentTest, TestPermutedOneFace) { - const std::string file_name_0 = "one_face_123.obj"; - const std::string file_name_1 = "one_face_312.obj"; - const std::string file_name_2 = "one_face_321.obj"; - const std::unique_ptr<Mesh> mesh_0(ReadMeshFromTestFile(file_name_0)); - const std::unique_ptr<Mesh> mesh_1(ReadMeshFromTestFile(file_name_1)); - const std::unique_ptr<Mesh> mesh_2(ReadMeshFromTestFile(file_name_2)); - ASSERT_NE(mesh_0, nullptr) << "Failed to load test model." << file_name_0; - ASSERT_NE(mesh_1, nullptr) << "Failed to load test model." << file_name_1; - ASSERT_NE(mesh_2, nullptr) << "Failed to load test model." << file_name_2; - MeshAreEquivalent equiv; - ASSERT_TRUE(equiv(*mesh_0, *mesh_0)); - ASSERT_TRUE(equiv(*mesh_0, *mesh_1)); // Face rotated. - ASSERT_FALSE(equiv(*mesh_0, *mesh_2)); // Face inverted. -} - -TEST_F(MeshAreEquivalentTest, TestPermutedTwoFaces) { - const std::string file_name_0 = "two_faces_123.obj"; - const std::string file_name_1 = "two_faces_312.obj"; - const std::unique_ptr<Mesh> mesh_0(ReadMeshFromTestFile(file_name_0)); - const std::unique_ptr<Mesh> mesh_1(ReadMeshFromTestFile(file_name_1)); - ASSERT_NE(mesh_0, nullptr) << "Failed to load test model." << file_name_0; - ASSERT_NE(mesh_1, nullptr) << "Failed to load test model." << file_name_1; - MeshAreEquivalent equiv; - ASSERT_TRUE(equiv(*mesh_0, *mesh_0)); - ASSERT_TRUE(equiv(*mesh_1, *mesh_1)); - ASSERT_TRUE(equiv(*mesh_0, *mesh_1)); -} - -// -TEST_F(MeshAreEquivalentTest, TestPermutedThreeFaces) { - const std::string file_name_0 = "three_faces_123.obj"; - const std::string file_name_1 = "three_faces_312.obj"; - const std::unique_ptr<Mesh> mesh_0(ReadMeshFromTestFile(file_name_0)); - const std::unique_ptr<Mesh> mesh_1(ReadMeshFromTestFile(file_name_1)); - ASSERT_NE(mesh_0, nullptr) << "Failed to load test model." << file_name_0; - ASSERT_NE(mesh_1, nullptr) << "Failed to load test model." << file_name_1; - MeshAreEquivalent equiv; - ASSERT_TRUE(equiv(*mesh_0, *mesh_0)); - ASSERT_TRUE(equiv(*mesh_1, *mesh_1)); - ASSERT_TRUE(equiv(*mesh_0, *mesh_1)); -} - -// This test checks that the edgebreaker algorithm does not change the mesh up -// to the order of faces and vertices. -TEST_F(MeshAreEquivalentTest, TestOnBigMesh) { - const std::string file_name = "test_nm.obj"; - const std::unique_ptr<Mesh> mesh0(ReadMeshFromTestFile(file_name)); - ASSERT_NE(mesh0, nullptr) << "Failed to load test model." << file_name; - - std::unique_ptr<Mesh> mesh1; - std::stringstream ss; - WriteMeshIntoStream(mesh0.get(), ss, MESH_EDGEBREAKER_ENCODING); - ReadMeshFromStream(&mesh1, ss); - ASSERT_TRUE(ss.good()) << "Mesh IO failed."; - - MeshAreEquivalent equiv; - ASSERT_TRUE(equiv(*mesh0, *mesh0)); - ASSERT_TRUE(equiv(*mesh1, *mesh1)); - ASSERT_TRUE(equiv(*mesh0, *mesh1)); -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup_test.cc b/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup_test.cc deleted file mode 100644 index 1051d193d87..00000000000 --- a/extern/draco/dracoenc/src/draco/mesh/mesh_cleanup_test.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/mesh/mesh_cleanup.h" - -#include "draco/core/draco_test_base.h" -#include "draco/core/vector_d.h" -#include "draco/mesh/triangle_soup_mesh_builder.h" - -namespace draco { - -class MeshCleanupTest : public ::testing::Test {}; - -TEST_F(MeshCleanupTest, TestDegneratedFaces) { - // This test verifies that the mesh cleanup tools removes degenerated faces. - TriangleSoupMeshBuilder mb; - mb.Start(2); - const int pos_att_id = - mb.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - // clang-format off - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(0), - Vector3f(0.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 1.f, 0.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(1), - Vector3f(0.f, 1.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data()); - // clang-format on - - std::unique_ptr<Mesh> mesh = mb.Finalize(); - ASSERT_NE(mesh, nullptr) << "Failed to build the test mesh."; - ASSERT_EQ(mesh->num_faces(), 2) << "Wrong number of faces in the input mesh."; - MeshCleanupOptions cleanup_options; - MeshCleanup cleanup; - ASSERT_TRUE(cleanup(mesh.get(), cleanup_options)) - << "Failed to cleanup the mesh."; - ASSERT_EQ(mesh->num_faces(), 1) << "Failed to remove degenerated faces."; -} - -TEST_F(MeshCleanupTest, TestDegneratedFacesAndIsolatedVertices) { - // This test verifies that the mesh cleanup tools removes degenerated faces - // and isolated vertices. - TriangleSoupMeshBuilder mb; - mb.Start(2); - const int pos_att_id = - mb.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - // clang-format off - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(0), - Vector3f(0.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 1.f, 0.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(1), - Vector3f(10.f, 1.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(10.f, 1.f, 0.f).data()); - // clang-format on - - std::unique_ptr<Mesh> mesh = mb.Finalize(); - ASSERT_NE(mesh, nullptr) << "Failed to build the test mesh."; - ASSERT_EQ(mesh->num_faces(), 2) << "Wrong number of faces in the input mesh."; - ASSERT_EQ(mesh->num_points(), 4) - << "Wrong number of point ids in the input mesh."; - const MeshCleanupOptions cleanup_options; - MeshCleanup cleanup; - ASSERT_TRUE(cleanup(mesh.get(), cleanup_options)) - << "Failed to cleanup the mesh."; - ASSERT_EQ(mesh->num_faces(), 1) << "Failed to remove degenerated faces."; - ASSERT_EQ(mesh->num_points(), 3) - << "Failed to remove isolated attribute indices."; -} - -TEST_F(MeshCleanupTest, TestAttributes) { - TriangleSoupMeshBuilder mb; - mb.Start(2); - const int pos_att_id = - mb.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int generic_att_id = - mb.AddAttribute(GeometryAttribute::GENERIC, 2, DT_FLOAT32); - // clang-format off - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(0), - Vector3f(0.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 1.f, 0.f).data()); - mb.SetAttributeValuesForFace(generic_att_id, FaceIndex(0), - Vector2f(0.f, 0.f).data(), - Vector2f(0.f, 0.f).data(), - Vector2f(0.f, 0.f).data()); - - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(1), - Vector3f(10.f, 1.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(10.f, 1.f, 0.f).data()); - mb.SetAttributeValuesForFace(generic_att_id, FaceIndex(1), - Vector2f(1.f, 0.f).data(), - Vector2f(1.f, 0.f).data(), - Vector2f(1.f, 0.f).data()); - // clang-format on - - std::unique_ptr<Mesh> mesh = mb.Finalize(); - ASSERT_NE(mesh, nullptr) << "Failed to build the test mesh."; - ASSERT_EQ(mesh->num_faces(), 2) << "Wrong number of faces in the input mesh."; - ASSERT_EQ(mesh->num_points(), 5) - << "Wrong number of point ids in the input mesh."; - ASSERT_EQ(mesh->attribute(1)->size(), 2u) - << "Wrong number of generic attribute entries."; - const MeshCleanupOptions cleanup_options; - MeshCleanup cleanup; - ASSERT_TRUE(cleanup(mesh.get(), cleanup_options)) - << "Failed to cleanup the mesh."; - ASSERT_EQ(mesh->num_faces(), 1) << "Failed to remove degenerated faces."; - ASSERT_EQ(mesh->num_points(), 3) - << "Failed to remove isolated attribute indices."; - ASSERT_EQ(mesh->attribute(0)->size(), 3u) - << "Wrong number of unique positions after cleanup."; - ASSERT_EQ(mesh->attribute(1)->size(), 1u) - << "Wrong number of generic attribute entries after cleanup."; -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder_test.cc b/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder_test.cc deleted file mode 100644 index 171f8fe24a1..00000000000 --- a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder_test.cc +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/mesh/triangle_soup_mesh_builder.h" - -#include "draco/core/draco_test_base.h" -#include "draco/core/vector_d.h" - -namespace draco { - -class TriangleSoupMeshBuilderTest : public ::testing::Test {}; - -TEST_F(TriangleSoupMeshBuilderTest, CubeTest) { - // This tests, verifies that the mesh builder constructs a valid cube out - // of the provided triangle soup data. - TriangleSoupMeshBuilder mb; - mb.Start(12); - const int pos_att_id = - mb.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - // clang-format off - // Front face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(0), - Vector3f(0.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 1.f, 0.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(1), - Vector3f(0.f, 1.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(1.f, 1.f, 0.f).data()); - - // Back face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(2), - Vector3f(0.f, 1.f, 1.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(0.f, 0.f, 1.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(3), - Vector3f(1.f, 1.f, 1.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(0.f, 1.f, 1.f).data()); - - // Top face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(4), - Vector3f(0.f, 1.f, 0.f).data(), - Vector3f(1.f, 1.f, 0.f).data(), - Vector3f(0.f, 1.f, 1.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(5), - Vector3f(0.f, 1.f, 1.f).data(), - Vector3f(1.f, 1.f, 0.f).data(), - Vector3f(1.f, 1.f, 1.f).data()); - - // Bottom face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(6), - Vector3f(0.f, 0.f, 1.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 0.f, 0.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(7), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 0.f, 1.f).data()); - - // Right face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(8), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(1.f, 1.f, 0.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(9), - Vector3f(1.f, 1.f, 0.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(1.f, 1.f, 1.f).data()); - - // Left face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(10), - Vector3f(0.f, 1.f, 0.f).data(), - Vector3f(0.f, 0.f, 1.f).data(), - Vector3f(0.f, 0.f, 0.f).data()); - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(11), - Vector3f(0.f, 1.f, 1.f).data(), - Vector3f(0.f, 0.f, 1.f).data(), - Vector3f(0.f, 1.f, 0.f).data()); - // clang-format on - - std::unique_ptr<Mesh> mesh = mb.Finalize(); - ASSERT_NE(mesh, nullptr) << "Failed to build the cube mesh."; - EXPECT_EQ(mesh->num_points(), 8) << "Unexpected number of vertices."; - EXPECT_EQ(mesh->num_faces(), 12) << "Unexpected number of faces."; -} - -TEST_F(TriangleSoupMeshBuilderTest, TestPerFaceAttribs) { - // This tests, verifies that the mesh builder constructs a valid cube with - // per face Boolean attributes. - TriangleSoupMeshBuilder mb; - mb.Start(12); - const int pos_att_id = - mb.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int gen_att_id = - mb.AddAttribute(GeometryAttribute::GENERIC, 1, DT_BOOL); - uint8_t bool_true = 1; - uint8_t bool_false = 0; - // clang-format off - // Front face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(0), - Vector3f(0.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 1.f, 0.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(0), &bool_false); - - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(1), - Vector3f(0.f, 1.f, 0.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(1.f, 1.f, 0.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(1), &bool_true); - - // Back face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(2), - Vector3f(0.f, 1.f, 1.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(0.f, 0.f, 1.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(2), &bool_true); - - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(3), - Vector3f(1.f, 1.f, 1.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(0.f, 1.f, 1.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(3), &bool_true); - - // Top face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(4), - Vector3f(0.f, 1.f, 0.f).data(), - Vector3f(1.f, 1.f, 0.f).data(), - Vector3f(0.f, 1.f, 1.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(4), &bool_false);; - - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(5), - Vector3f(0.f, 1.f, 1.f).data(), - Vector3f(1.f, 1.f, 0.f).data(), - Vector3f(1.f, 1.f, 1.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(5), &bool_false); - - // Bottom face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(6), - Vector3f(0.f, 0.f, 1.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 0.f, 0.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(6), &bool_true); - - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(7), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(0.f, 0.f, 1.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(7), &bool_true); - - // Right face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(8), - Vector3f(1.f, 0.f, 0.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(1.f, 1.f, 0.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(8), &bool_false); - - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(9), - Vector3f(1.f, 1.f, 0.f).data(), - Vector3f(1.f, 0.f, 1.f).data(), - Vector3f(1.f, 1.f, 1.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(9), &bool_true); - - // Left face. - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(10), - Vector3f(0.f, 1.f, 0.f).data(), - Vector3f(0.f, 0.f, 1.f).data(), - Vector3f(0.f, 0.f, 0.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(10), &bool_true); - - mb.SetAttributeValuesForFace(pos_att_id, FaceIndex(11), - Vector3f(0.f, 1.f, 1.f).data(), - Vector3f(0.f, 0.f, 1.f).data(), - Vector3f(0.f, 1.f, 0.f).data()); - mb.SetPerFaceAttributeValueForFace(gen_att_id, FaceIndex(11), &bool_false); - // clang-format on - - std::unique_ptr<Mesh> mesh = mb.Finalize(); - ASSERT_NE(mesh, nullptr) << "Failed to build the cube mesh."; - EXPECT_EQ(mesh->num_faces(), 12) << "Unexpected number of faces."; - EXPECT_EQ(mesh->GetAttributeElementType(gen_att_id), MESH_FACE_ATTRIBUTE) - << "Unexpected attribute element type."; -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc b/extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc deleted file mode 100644 index d8f7f2f6649..00000000000 --- a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/metadata/metadata_encoder.h" -#include "draco/core/decoder_buffer.h" -#include "draco/core/draco_test_base.h" -#include "draco/core/encoder_buffer.h" -#include "draco/metadata/metadata.h" -#include "draco/metadata/metadata_decoder.h" - -namespace { - -class MetadataEncoderTest : public ::testing::Test { - protected: - MetadataEncoderTest() {} - - void TestEncodingMetadata() { - ASSERT_TRUE(encoder.EncodeMetadata(&encoder_buffer, &metadata)); - - draco::Metadata decoded_metadata; - decoder_buffer.Init(encoder_buffer.data(), encoder_buffer.size()); - ASSERT_TRUE(decoder.DecodeMetadata(&decoder_buffer, &decoded_metadata)); - CheckMetadatasAreEqual(metadata, decoded_metadata); - } - - void TestEncodingGeometryMetadata() { - ASSERT_TRUE( - encoder.EncodeGeometryMetadata(&encoder_buffer, &geometry_metadata)); - - draco::GeometryMetadata decoded_metadata; - decoder_buffer.Init(encoder_buffer.data(), encoder_buffer.size()); - ASSERT_TRUE( - decoder.DecodeGeometryMetadata(&decoder_buffer, &decoded_metadata)); - CheckGeometryMetadatasAreEqual(geometry_metadata, decoded_metadata); - } - - void CheckBlobOfDataAreEqual(const std::vector<uint8_t> &data0, - const std::vector<uint8_t> &data1) { - ASSERT_EQ(data0.size(), data1.size()); - for (int i = 0; i < data0.size(); ++i) - ASSERT_EQ(data0[i], data1[i]); - } - - void CheckGeometryMetadatasAreEqual( - const draco::GeometryMetadata &metadata0, - const draco::GeometryMetadata &metadata1) { - ASSERT_EQ(metadata0.attribute_metadatas().size(), - metadata1.attribute_metadatas().size()); - const std::vector<std::unique_ptr<draco::AttributeMetadata>> - &att_metadatas0 = metadata0.attribute_metadatas(); - const std::vector<std::unique_ptr<draco::AttributeMetadata>> - &att_metadatas1 = metadata1.attribute_metadatas(); - // Compare each attribute metadata. - for (int i = 0; i < metadata0.attribute_metadatas().size(); ++i) { - CheckMetadatasAreEqual( - static_cast<const draco::Metadata &>(*att_metadatas0[i]), - static_cast<const draco::Metadata &>(*att_metadatas1[i])); - } - // Compare entries and sub metadata. - CheckMetadatasAreEqual(static_cast<const draco::Metadata &>(metadata0), - static_cast<const draco::Metadata &>(metadata1)); - } - - void CheckMetadatasAreEqual(const draco::Metadata &metadata0, - const draco::Metadata &metadata1) { - ASSERT_EQ(metadata0.num_entries(), metadata1.num_entries()); - const std::map<std::string, draco::EntryValue> &entries0 = - metadata0.entries(); - const std::map<std::string, draco::EntryValue> &entries1 = - metadata1.entries(); - for (const auto &entry : entries0) { - const std::string &entry_name = entry.first; - const std::vector<uint8_t> &data0 = entry.second.data(); - const auto entry1_ptr = entries1.find(entry_name); - ASSERT_NE(entry1_ptr, entries1.end()); - const std::vector<uint8_t> &data1 = entry1_ptr->second.data(); - CheckBlobOfDataAreEqual(data0, data1); - } - // Check nested metadata. - ASSERT_EQ(metadata0.sub_metadatas().size(), - metadata1.sub_metadatas().size()); - const std::map<std::string, std::unique_ptr<draco::Metadata>> - &sub_metadatas0 = metadata0.sub_metadatas(); - // Encode each sub-metadata - for (auto &&sub_metadata_entry0 : sub_metadatas0) { - const auto sub_metadata_ptr1 = - metadata1.GetSubMetadata(sub_metadata_entry0.first); - ASSERT_NE(sub_metadata_ptr1, nullptr); - CheckMetadatasAreEqual(*sub_metadata_entry0.second, *sub_metadata_ptr1); - } - } - - draco::MetadataEncoder encoder; - draco::MetadataDecoder decoder; - draco::EncoderBuffer encoder_buffer; - draco::DecoderBuffer decoder_buffer; - draco::Metadata metadata; - draco::GeometryMetadata geometry_metadata; -}; - -TEST_F(MetadataEncoderTest, TestSingleEntry) { - metadata.AddEntryInt("int", 100); - ASSERT_EQ(metadata.num_entries(), 1); - - TestEncodingMetadata(); -} - -TEST_F(MetadataEncoderTest, TestMultipleEntries) { - metadata.AddEntryInt("int", 100); - metadata.AddEntryDouble("double", 1.234); - const std::string entry_value = "test string entry"; - metadata.AddEntryString("string", entry_value); - ASSERT_EQ(metadata.num_entries(), 3); - - TestEncodingMetadata(); -} - -TEST_F(MetadataEncoderTest, TestEncodingArrayEntries) { - std::vector<int32_t> int_array({1, 2, 3}); - metadata.AddEntryIntArray("int_array", int_array); - std::vector<double> double_array({0.1, 0.2, 0.3}); - metadata.AddEntryDoubleArray("double_array", double_array); - ASSERT_EQ(metadata.num_entries(), 2); - - TestEncodingMetadata(); -} - -TEST_F(MetadataEncoderTest, TestEncodingBinaryEntry) { - const std::vector<uint8_t> binarydata({0x1, 0x2, 0x3, 0x4}); - metadata.AddEntryBinary("binary_data", binarydata); - - TestEncodingMetadata(); -} - -TEST_F(MetadataEncoderTest, TestEncodingNestedMetadata) { - metadata.AddEntryDouble("double", 1.234); - std::unique_ptr<draco::Metadata> sub_metadata = - std::unique_ptr<draco::Metadata>(new draco::Metadata()); - sub_metadata->AddEntryInt("int", 100); - metadata.AddSubMetadata("sub0", std::move(sub_metadata)); - - TestEncodingMetadata(); -} - -TEST_F(MetadataEncoderTest, TestEncodingGeometryMetadata) { - std::unique_ptr<draco::AttributeMetadata> att_metadata = - std::unique_ptr<draco::AttributeMetadata>(new draco::AttributeMetadata); - att_metadata->AddEntryInt("int", 100); - att_metadata->AddEntryString("name", "pos"); - ASSERT_TRUE(geometry_metadata.AddAttributeMetadata(std::move(att_metadata))); - - TestEncodingGeometryMetadata(); -} -} // namespace diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_test.cc b/extern/draco/dracoenc/src/draco/metadata/metadata_test.cc deleted file mode 100644 index ba6a764446c..00000000000 --- a/extern/draco/dracoenc/src/draco/metadata/metadata_test.cc +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include <memory> -#include <string> - -#include "draco/core/draco_test_base.h" -#include "draco/metadata/geometry_metadata.h" -#include "draco/metadata/metadata.h" - -namespace { - -class MetadataTest : public ::testing::Test { - protected: - MetadataTest() {} - - draco::Metadata metadata; - draco::GeometryMetadata geometry_metadata; -}; - -TEST_F(MetadataTest, TestRemoveEntry) { - metadata.AddEntryInt("int", 100); - metadata.RemoveEntry("int"); - int32_t int_value = 0; - ASSERT_FALSE(metadata.GetEntryInt("int", &int_value)); -} - -TEST_F(MetadataTest, TestSingleEntry) { - metadata.AddEntryInt("int", 100); - int32_t int_value = 0; - ASSERT_TRUE(metadata.GetEntryInt("int", &int_value)); - ASSERT_EQ(int_value, 100); - - metadata.AddEntryDouble("double", 1.234); - double double_value = 0.0; - ASSERT_TRUE(metadata.GetEntryDouble("double", &double_value)); - ASSERT_EQ(double_value, 1.234); -} - -TEST_F(MetadataTest, TestWriteOverEntry) { - metadata.AddEntryInt("int", 100); - metadata.AddEntryInt("int", 200); - int32_t int_value = 0; - ASSERT_TRUE(metadata.GetEntryInt("int", &int_value)); - ASSERT_EQ(int_value, 200); -} - -TEST_F(MetadataTest, TestArrayEntry) { - std::vector<int32_t> int_array({1, 2, 3}); - metadata.AddEntryIntArray("int_array", int_array); - std::vector<int32_t> return_int_array; - ASSERT_TRUE(metadata.GetEntryIntArray("int_array", &return_int_array)); - ASSERT_EQ(return_int_array.size(), 3); - ASSERT_EQ(return_int_array[0], 1); - ASSERT_EQ(return_int_array[1], 2); - ASSERT_EQ(return_int_array[2], 3); - - std::vector<double> double_array({0.1, 0.2, 0.3}); - metadata.AddEntryDoubleArray("double_array", double_array); - std::vector<double> return_double_array; - ASSERT_TRUE( - metadata.GetEntryDoubleArray("double_array", &return_double_array)); - ASSERT_EQ(return_double_array.size(), 3); - ASSERT_EQ(return_double_array[0], 0.1); - ASSERT_EQ(return_double_array[1], 0.2); - ASSERT_EQ(return_double_array[2], 0.3); -} - -TEST_F(MetadataTest, TestStringEntry) { - const std::string entry_value = "test string entry"; - metadata.AddEntryString("string", entry_value); - std::string return_value; - ASSERT_TRUE(metadata.GetEntryString("string", &return_value)); - ASSERT_EQ(entry_value.size(), return_value.size()); - ASSERT_EQ(entry_value, return_value); -} - -TEST_F(MetadataTest, TestBinaryEntry) { - const std::vector<uint8_t> binarydata({0x1, 0x2, 0x3, 0x4}); - metadata.AddEntryBinary("binary_data", binarydata); - std::vector<uint8_t> return_binarydata; - ASSERT_TRUE(metadata.GetEntryBinary("binary_data", &return_binarydata)); - ASSERT_EQ(binarydata.size(), return_binarydata.size()); - for (int i = 0; i < binarydata.size(); ++i) { - ASSERT_EQ(binarydata[i], return_binarydata[i]); - } -} - -TEST_F(MetadataTest, TestNestedMetadata) { - std::unique_ptr<draco::Metadata> sub_metadata = - std::unique_ptr<draco::Metadata>(new draco::Metadata()); - sub_metadata->AddEntryInt("int", 100); - - metadata.AddSubMetadata("sub0", std::move(sub_metadata)); - const auto sub_metadata_ptr = metadata.GetSubMetadata("sub0"); - ASSERT_NE(sub_metadata_ptr, nullptr); - - int32_t int_value = 0; - ASSERT_TRUE(sub_metadata_ptr->GetEntryInt("int", &int_value)); - ASSERT_EQ(int_value, 100); -} - -TEST_F(MetadataTest, TestHardCopyMetadata) { - metadata.AddEntryInt("int", 100); - std::unique_ptr<draco::Metadata> sub_metadata = - std::unique_ptr<draco::Metadata>(new draco::Metadata()); - sub_metadata->AddEntryInt("int", 200); - metadata.AddSubMetadata("sub0", std::move(sub_metadata)); - - draco::Metadata copied_metadata(metadata); - - int32_t int_value = 0; - ASSERT_TRUE(copied_metadata.GetEntryInt("int", &int_value)); - ASSERT_EQ(int_value, 100); - - const auto sub_metadata_ptr = copied_metadata.GetSubMetadata("sub0"); - ASSERT_NE(sub_metadata_ptr, nullptr); - - int32_t sub_int_value = 0; - ASSERT_TRUE(sub_metadata_ptr->GetEntryInt("int", &sub_int_value)); - ASSERT_EQ(sub_int_value, 200); -} - -TEST_F(MetadataTest, TestGeometryMetadata) { - std::unique_ptr<draco::AttributeMetadata> att_metadata = - std::unique_ptr<draco::AttributeMetadata>(new draco::AttributeMetadata()); - att_metadata->set_att_unique_id(10); - att_metadata->AddEntryInt("int", 100); - att_metadata->AddEntryString("name", "pos"); - - ASSERT_FALSE(geometry_metadata.AddAttributeMetadata(nullptr)); - ASSERT_TRUE(geometry_metadata.AddAttributeMetadata(std::move(att_metadata))); - - ASSERT_NE(geometry_metadata.GetAttributeMetadataByUniqueId(10), nullptr); - ASSERT_EQ(geometry_metadata.GetAttributeMetadataByUniqueId(1), nullptr); - - const draco::AttributeMetadata *requested_att_metadata = - geometry_metadata.GetAttributeMetadataByStringEntry("name", "pos"); - ASSERT_NE(requested_att_metadata, nullptr); - ASSERT_EQ( - geometry_metadata.GetAttributeMetadataByStringEntry("name", "not_exists"), - nullptr); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder_test.cc b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder_test.cc deleted file mode 100644 index 3222a4c8da8..00000000000 --- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder_test.cc +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/point_cloud/point_cloud_builder.h" - -#include "draco/core/draco_test_base.h" - -namespace draco { - -class PointCloudBuilderTest : public ::testing::Test { - protected: - // Test data. - // clang-format off - std::vector<float> pos_data_ = {10.f, 0.f, 1.f, - 11.f, 1.f, 2.f, - 12.f, 2.f, 8.f, - 13.f, 4.f, 7.f, - 14.f, 5.f, 6.f, - 15.f, 6.f, 5.f, - 16.f, 1.f, 3.f, - 17.f, 1.f, 2.f, - 11.f, 1.f, 2.f, - 10.f, 0.f, 1.f}; - std::vector<int16_t> intensity_data_ = {100, - 200, - 500, - 700, - 400, - 400, - 400, - 100, - 100, - 100}; - // clang-format on -}; - -TEST_F(PointCloudBuilderTest, IndividualTest_NoDedup) { - // This test verifies that PointCloudBuilder can construct point cloud using - // SetAttributeValueForPoint API without deduplication. - PointCloudBuilder builder; - builder.Start(10); - const int pos_att_id = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int intensity_att_id = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT16); - for (PointIndex i(0); i < 10; ++i) { - builder.SetAttributeValueForPoint(pos_att_id, i, - pos_data_.data() + 3 * i.value()); - builder.SetAttributeValueForPoint(intensity_att_id, i, - intensity_data_.data() + i.value()); - } - std::unique_ptr<PointCloud> res = builder.Finalize(false); - ASSERT_TRUE(res != nullptr); - ASSERT_EQ(res->num_points(), 10); -} - -TEST_F(PointCloudBuilderTest, IndividualTest_Dedup) { - // This test verifies that PointCloudBuilder can construct point cloud using - // SetAttributeValueForPoint API with deduplication. - PointCloudBuilder builder; - builder.Start(10); - const int pos_att_id = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int intensity_att_id = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT16); - for (PointIndex i(0); i < 10; ++i) { - builder.SetAttributeValueForPoint(pos_att_id, i, - pos_data_.data() + 3 * i.value()); - builder.SetAttributeValueForPoint(intensity_att_id, i, - intensity_data_.data() + i.value()); - } - std::unique_ptr<PointCloud> res = builder.Finalize(true); - ASSERT_TRUE(res != nullptr); - ASSERT_EQ(res->num_points(), 9); -} - -TEST_F(PointCloudBuilderTest, BatchTest) { - // This test verifies that PointCloudBuilder can construct point cloud using - // SetAttributeValuesForAllPoints API. - PointCloudBuilder builder; - builder.Start(10); - const int pos_att_id = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int intensity_att_id = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT16); - builder.SetAttributeValuesForAllPoints(pos_att_id, pos_data_.data(), 0); - builder.SetAttributeValuesForAllPoints(intensity_att_id, - intensity_data_.data(), 0); - std::unique_ptr<PointCloud> res = builder.Finalize(false); - ASSERT_TRUE(res != nullptr); - ASSERT_EQ(res->num_points(), 10); - for (PointIndex i(0); i < 10; ++i) { - float pos_val[3]; - res->attribute(pos_att_id)->GetMappedValue(i, pos_val); - for (int c = 0; c < 3; ++c) { - ASSERT_EQ(pos_val[c], pos_data_[3 * i.value() + c]); - } - int16_t int_val; - res->attribute(intensity_att_id)->GetMappedValue(i, &int_val); - ASSERT_EQ(intensity_data_[i.value()], int_val); - } -} - -TEST_F(PointCloudBuilderTest, MultiUse) { - // This test verifies that PointCloudBuilder can be used multiple times - PointCloudBuilder builder; - { - builder.Start(10); - const int pos_att_id = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int intensity_att_id = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT16); - builder.SetAttributeValuesForAllPoints(pos_att_id, pos_data_.data(), 0); - builder.SetAttributeValuesForAllPoints(intensity_att_id, - intensity_data_.data(), 0); - std::unique_ptr<PointCloud> res = builder.Finalize(false); - ASSERT_TRUE(res != nullptr); - ASSERT_EQ(res->num_points(), 10); - for (PointIndex i(0); i < 10; ++i) { - float pos_val[3]; - res->attribute(pos_att_id)->GetMappedValue(i, pos_val); - for (int c = 0; c < 3; ++c) { - ASSERT_EQ(pos_val[c], pos_data_[3 * i.value() + c]); - } - int16_t int_val; - res->attribute(intensity_att_id)->GetMappedValue(i, &int_val); - ASSERT_EQ(intensity_data_[i.value()], int_val); - } - } - - { - // Use only a sub-set of data (offsetted to avoid possible reuse of old - // data). - builder.Start(4); - const int pos_att_id = - builder.AddAttribute(GeometryAttribute::POSITION, 3, DT_FLOAT32); - const int intensity_att_id = - builder.AddAttribute(GeometryAttribute::GENERIC, 1, DT_INT16); - constexpr int offset = 5; - builder.SetAttributeValuesForAllPoints(pos_att_id, - pos_data_.data() + 3 * offset, 0); - builder.SetAttributeValuesForAllPoints(intensity_att_id, - intensity_data_.data() + offset, 0); - std::unique_ptr<PointCloud> res = builder.Finalize(false); - ASSERT_TRUE(res != nullptr); - ASSERT_EQ(res->num_points(), 4); - for (PointIndex i(0); i < 4; ++i) { - float pos_val[3]; - res->attribute(pos_att_id)->GetMappedValue(i, pos_val); - for (int c = 0; c < 3; ++c) { - ASSERT_EQ(pos_val[c], pos_data_[3 * (i.value() + offset) + c]); - } - int16_t int_val; - res->attribute(intensity_att_id)->GetMappedValue(i, &int_val); - ASSERT_EQ(intensity_data_[i.value() + offset], int_val); - } - } -} - -} // namespace draco diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_test.cc b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_test.cc deleted file mode 100644 index 00491b7309a..00000000000 --- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_test.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2017 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "draco/core/draco_test_base.h" -#include "draco/core/draco_test_utils.h" - -#include "draco/point_cloud/point_cloud.h" - -namespace { - -class PointCloudTest : public ::testing::Test { - protected: - PointCloudTest() {} -}; - -TEST_F(PointCloudTest, TestAttributeDeletion) { - draco::PointCloud pc; - // Test whether we can correctly delete an attribute from a point cloud. - // Create some attributes for the point cloud. - draco::GeometryAttribute pos_att; - pos_att.Init(draco::GeometryAttribute::POSITION, nullptr, 3, - draco::DT_FLOAT32, false, 12, 0); - draco::GeometryAttribute norm_att; - norm_att.Init(draco::GeometryAttribute::NORMAL, nullptr, 3, draco::DT_FLOAT32, - false, 12, 0); - draco::GeometryAttribute gen_att; - gen_att.Init(draco::GeometryAttribute::GENERIC, nullptr, 3, draco::DT_FLOAT32, - false, 12, 0); - - // Add one position, two normal and two generic attributes. - pc.AddAttribute(pos_att, false, 0); - pc.AddAttribute(gen_att, false, 0); - pc.AddAttribute(norm_att, false, 0); - pc.AddAttribute(gen_att, false, 0); - pc.AddAttribute(norm_att, false, 0); - - ASSERT_EQ(pc.num_attributes(), 5); - ASSERT_EQ(pc.attribute(0)->attribute_type(), - draco::GeometryAttribute::POSITION); - ASSERT_EQ(pc.attribute(3)->attribute_type(), - draco::GeometryAttribute::GENERIC); - - // Delete generic attribute. - pc.DeleteAttribute(1); - ASSERT_EQ(pc.num_attributes(), 4); - ASSERT_EQ(pc.attribute(1)->attribute_type(), - draco::GeometryAttribute::NORMAL); - ASSERT_EQ(pc.NumNamedAttributes(draco::GeometryAttribute::NORMAL), 2); - ASSERT_EQ(pc.GetNamedAttributeId(draco::GeometryAttribute::NORMAL, 1), 3); - - // Delete the first normal attribute. - pc.DeleteAttribute(1); - ASSERT_EQ(pc.num_attributes(), 3); - ASSERT_EQ(pc.attribute(1)->attribute_type(), - draco::GeometryAttribute::GENERIC); - ASSERT_EQ(pc.NumNamedAttributes(draco::GeometryAttribute::NORMAL), 1); - ASSERT_EQ(pc.GetNamedAttributeId(draco::GeometryAttribute::NORMAL, 0), 2); -} - -TEST_F(PointCloudTest, TestPointCloudWithMetadata) { - draco::PointCloud pc; - std::unique_ptr<draco::GeometryMetadata> metadata = - std::unique_ptr<draco::GeometryMetadata>(new draco::GeometryMetadata()); - - // Add a position attribute metadata. - draco::GeometryAttribute pos_att; - pos_att.Init(draco::GeometryAttribute::POSITION, nullptr, 3, - draco::DT_FLOAT32, false, 12, 0); - const uint32_t pos_att_id = pc.AddAttribute(pos_att, false, 0); - ASSERT_EQ(pos_att_id, 0); - std::unique_ptr<draco::AttributeMetadata> pos_metadata = - std::unique_ptr<draco::AttributeMetadata>(new draco::AttributeMetadata()); - pos_metadata->AddEntryString("name", "position"); - pc.AddAttributeMetadata(pos_att_id, std::move(pos_metadata)); - const draco::GeometryMetadata *pc_metadata = pc.GetMetadata(); - ASSERT_NE(pc_metadata, nullptr); - // Add a generic material attribute metadata. - draco::GeometryAttribute material_att; - material_att.Init(draco::GeometryAttribute::GENERIC, nullptr, 3, - draco::DT_FLOAT32, false, 12, 0); - const uint32_t material_att_id = pc.AddAttribute(material_att, false, 0); - ASSERT_EQ(material_att_id, 1); - std::unique_ptr<draco::AttributeMetadata> material_metadata = - std::unique_ptr<draco::AttributeMetadata>(new draco::AttributeMetadata()); - material_metadata->AddEntryString("name", "material"); - // The material attribute has id of 1 now. - pc.AddAttributeMetadata(material_att_id, std::move(material_metadata)); - - // Test if the attribute metadata is correctly added. - const draco::AttributeMetadata *requested_pos_metadata = - pc.GetAttributeMetadataByStringEntry("name", "position"); - ASSERT_NE(requested_pos_metadata, nullptr); - const draco::AttributeMetadata *requested_mat_metadata = - pc.GetAttributeMetadataByStringEntry("name", "material"); - ASSERT_NE(requested_mat_metadata, nullptr); - - // Attribute id should be preserved. - ASSERT_EQ( - pc.GetAttributeIdByUniqueId(requested_pos_metadata->att_unique_id()), 0); - ASSERT_EQ( - pc.GetAttributeIdByUniqueId(requested_mat_metadata->att_unique_id()), 1); - - // Test deleting attribute with metadata. - pc.DeleteAttribute(pos_att_id); - ASSERT_EQ(pc.GetAttributeMetadataByStringEntry("name", "position"), nullptr); - - requested_mat_metadata = - pc.GetAttributeMetadataByStringEntry("name", "material"); - // The unique id should not be changed. - ASSERT_EQ(requested_mat_metadata->att_unique_id(), 1); - // Now position attribute is removed, material attribute should have the - // attribute id of 0. - ASSERT_EQ( - pc.GetAttributeIdByUniqueId(requested_mat_metadata->att_unique_id()), 0); - // Should be able to get metadata using the current attribute id. - // Attribute id of material attribute is changed from 1 to 0. - ASSERT_NE(pc.GetAttributeMetadataByAttributeId(0), nullptr); -} - -} // namespace diff --git a/extern/draco/dracoenc/src/draco/tools/draco_decoder.cc b/extern/draco/dracoenc/src/draco/tools/draco_decoder.cc deleted file mode 100644 index 5b06e8caa3b..00000000000 --- a/extern/draco/dracoenc/src/draco/tools/draco_decoder.cc +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include <cinttypes> -#include <fstream> - -#include "draco/compression/decode.h" -#include "draco/core/cycle_timer.h" -#include "draco/io/obj_encoder.h" -#include "draco/io/parser_utils.h" -#include "draco/io/ply_encoder.h" - -namespace { - -struct Options { - Options(); - - std::string input; - std::string output; -}; - -Options::Options() {} - -void Usage() { - printf("Usage: draco_decoder [options] -i input\n"); - printf("\n"); - printf("Main options:\n"); - printf(" -h | -? show help.\n"); - printf(" -o <output> output file name.\n"); -} - -int ReturnError(const draco::Status &status) { - printf("Failed to decode the input file %s\n", status.error_msg()); - return -1; -} - -} // namespace - -int main(int argc, char **argv) { - Options options; - const int argc_check = argc - 1; - - for (int i = 1; i < argc; ++i) { - if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) { - Usage(); - return 0; - } else if (!strcmp("-i", argv[i]) && i < argc_check) { - options.input = argv[++i]; - } else if (!strcmp("-o", argv[i]) && i < argc_check) { - options.output = argv[++i]; - } - } - if (argc < 3 || options.input.empty()) { - Usage(); - return -1; - } - - std::ifstream input_file(options.input, std::ios::binary); - if (!input_file) { - printf("Failed opening the input file.\n"); - return -1; - } - - // Read the file stream into a buffer. - std::streampos file_size = 0; - input_file.seekg(0, std::ios::end); - file_size = input_file.tellg() - file_size; - input_file.seekg(0, std::ios::beg); - std::vector<char> data(file_size); - input_file.read(data.data(), file_size); - - if (data.empty()) { - printf("Empty input file.\n"); - return -1; - } - - // Create a draco decoding buffer. Note that no data is copied in this step. - draco::DecoderBuffer buffer; - buffer.Init(data.data(), data.size()); - - draco::CycleTimer timer; - // Decode the input data into a geometry. - std::unique_ptr<draco::PointCloud> pc; - draco::Mesh *mesh = nullptr; - auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer); - if (!type_statusor.ok()) { - return ReturnError(type_statusor.status()); - } - const draco::EncodedGeometryType geom_type = type_statusor.value(); - if (geom_type == draco::TRIANGULAR_MESH) { - timer.Start(); - draco::Decoder decoder; - auto statusor = decoder.DecodeMeshFromBuffer(&buffer); - if (!statusor.ok()) { - return ReturnError(statusor.status()); - } - std::unique_ptr<draco::Mesh> in_mesh = std::move(statusor).value(); - timer.Stop(); - if (in_mesh) { - mesh = in_mesh.get(); - pc = std::move(in_mesh); - } - } else if (geom_type == draco::POINT_CLOUD) { - // Failed to decode it as mesh, so let's try to decode it as a point cloud. - timer.Start(); - draco::Decoder decoder; - auto statusor = decoder.DecodePointCloudFromBuffer(&buffer); - if (!statusor.ok()) { - return ReturnError(statusor.status()); - } - pc = std::move(statusor).value(); - timer.Stop(); - } - - if (pc == nullptr) { - printf("Failed to decode the input file.\n"); - return -1; - } - - if (options.output.empty()) { - // Save the output model into a ply file. - options.output = options.input + ".ply"; - } - - // Save the decoded geometry into a file. - // TODO(fgalligan): Change extension code to look for '.'. - const std::string extension = draco::parser::ToLower( - options.output.size() >= 4 - ? options.output.substr(options.output.size() - 4) - : options.output); - - if (extension == ".obj") { - draco::ObjEncoder obj_encoder; - if (mesh) { - if (!obj_encoder.EncodeToFile(*mesh, options.output)) { - printf("Failed to store the decoded mesh as OBJ.\n"); - return -1; - } - } else { - if (!obj_encoder.EncodeToFile(*pc.get(), options.output)) { - printf("Failed to store the decoded point cloud as OBJ.\n"); - return -1; - } - } - } else if (extension == ".ply") { - draco::PlyEncoder ply_encoder; - if (mesh) { - if (!ply_encoder.EncodeToFile(*mesh, options.output)) { - printf("Failed to store the decoded mesh as PLY.\n"); - return -1; - } - } else { - if (!ply_encoder.EncodeToFile(*pc.get(), options.output)) { - printf("Failed to store the decoded point cloud as PLY.\n"); - return -1; - } - } - } else { - printf( - "Invalid extension of the output file. Use either .ply, .obj, or " - ".gltf\n"); - return -1; - } - printf("Decoded geometry saved to %s (%" PRId64 " ms to decode)\n", - options.output.c_str(), timer.GetInMs()); - return 0; -} diff --git a/extern/draco/dracoenc/src/draco/tools/draco_encoder.cc b/extern/draco/dracoenc/src/draco/tools/draco_encoder.cc deleted file mode 100644 index e44d0939048..00000000000 --- a/extern/draco/dracoenc/src/draco/tools/draco_encoder.cc +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2016 The Draco Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include <cinttypes> -#include <cstdlib> -#include <fstream> - -#include "draco/compression/encode.h" -#include "draco/core/cycle_timer.h" -#include "draco/io/mesh_io.h" -#include "draco/io/point_cloud_io.h" - -namespace { - -struct Options { - Options(); - - bool is_point_cloud; - int pos_quantization_bits; - int tex_coords_quantization_bits; - bool tex_coords_deleted; - int normals_quantization_bits; - bool normals_deleted; - int generic_quantization_bits; - bool generic_deleted; - int compression_level; - bool use_metadata; - std::string input; - std::string output; -}; - -Options::Options() - : is_point_cloud(false), - pos_quantization_bits(14), - tex_coords_quantization_bits(12), - tex_coords_deleted(false), - normals_quantization_bits(10), - normals_deleted(false), - generic_quantization_bits(8), - generic_deleted(false), - compression_level(7), - use_metadata(false) {} - -void Usage() { - printf("Usage: draco_encoder [options] -i input\n"); - printf("\n"); - printf("Main options:\n"); - printf(" -h | -? show help.\n"); - printf(" -i <input> input file name.\n"); - printf(" -o <output> output file name.\n"); - printf( - " -point_cloud forces the input to be encoded as a point " - "cloud.\n"); - printf( - " -qp <value> quantization bits for the position " - "attribute, default=14.\n"); - printf( - " -qt <value> quantization bits for the texture coordinate " - "attribute, default=12.\n"); - printf( - " -qn <value> quantization bits for the normal vector " - "attribute, default=10.\n"); - printf( - " -qg <value> quantization bits for any generic attribute, " - "default=8.\n"); - printf( - " -cl <value> compression level [0-10], most=10, least=0, " - "default=7.\n"); - printf( - " --skip ATTRIBUTE_NAME skip a given attribute (NORMAL, TEX_COORD, " - "GENERIC)\n"); - printf( - " --metadata use metadata to encode extra information in " - "mesh files.\n"); - printf( - "\nUse negative quantization values to skip the specified attribute\n"); -} - -int StringToInt(const std::string &s) { - char *end; - return strtol(s.c_str(), &end, 10); // NOLINT -} - -void PrintOptions(const draco::PointCloud &pc, const Options &options) { - printf("Encoder options:\n"); - printf(" Compression level = %d\n", options.compression_level); - if (options.pos_quantization_bits == 0) { - printf(" Positions: No quantization\n"); - } else { - printf(" Positions: Quantization = %d bits\n", - options.pos_quantization_bits); - } - - if (pc.GetNamedAttributeId(draco::GeometryAttribute::TEX_COORD) >= 0) { - if (options.tex_coords_quantization_bits == 0) { - printf(" Texture coordinates: No quantization\n"); - } else { - printf(" Texture coordinates: Quantization = %d bits\n", - options.tex_coords_quantization_bits); - } - } else if (options.tex_coords_deleted) { - printf(" Texture coordinates: Skipped\n"); - } - - if (pc.GetNamedAttributeId(draco::GeometryAttribute::NORMAL) >= 0) { - if (options.normals_quantization_bits == 0) { - printf(" Normals: No quantization\n"); - } else { - printf(" Normals: Quantization = %d bits\n", - options.normals_quantization_bits); - } - } else if (options.normals_deleted) { - printf(" Normals: Skipped\n"); - } - - if (pc.GetNamedAttributeId(draco::GeometryAttribute::GENERIC) >= 0) { - if (options.generic_quantization_bits == 0) { - printf(" Generic: No quantization\n"); - } else { - printf(" Generic: Quantization = %d bits\n", - options.generic_quantization_bits); - } - } else if (options.generic_deleted) { - printf(" Generic: Skipped\n"); - } - printf("\n"); -} - -int EncodePointCloudToFile(const draco::PointCloud &pc, const std::string &file, - draco::Encoder *encoder) { - draco::CycleTimer timer; - // Encode the geometry. - draco::EncoderBuffer buffer; - timer.Start(); - const draco::Status status = encoder->EncodePointCloudToBuffer(pc, &buffer); - if (!status.ok()) { - printf("Failed to encode the point cloud.\n"); - printf("%s\n", status.error_msg()); - return -1; - } - timer.Stop(); - // Save the encoded geometry into a file. - std::ofstream out_file(file, std::ios::binary); - if (!out_file) { - printf("Failed to create the output file.\n"); - return -1; - } - out_file.write(buffer.data(), buffer.size()); - printf("Encoded point cloud saved to %s (%" PRId64 " ms to encode).\n", - file.c_str(), timer.GetInMs()); - printf("\nEncoded size = %zu bytes\n\n", buffer.size()); - return 0; -} - -int EncodeMeshToFile(const draco::Mesh &mesh, const std::string &file, - draco::Encoder *encoder) { - draco::CycleTimer timer; - // Encode the geometry. - draco::EncoderBuffer buffer; - timer.Start(); - const draco::Status status = encoder->EncodeMeshToBuffer(mesh, &buffer); - if (!status.ok()) { - printf("Failed to encode the mesh.\n"); - printf("%s\n", status.error_msg()); - return -1; - } - timer.Stop(); - // Save the encoded geometry into a file. - std::ofstream out_file(file, std::ios::binary); - if (!out_file) { - printf("Failed to create the output file.\n"); - return -1; - } - out_file.write(buffer.data(), buffer.size()); - printf("Encoded mesh saved to %s (%" PRId64 " ms to encode).\n", file.c_str(), - timer.GetInMs()); - printf("\nEncoded size = %zu bytes\n\n", buffer.size()); - return 0; -} - -} // anonymous namespace - -int main(int argc, char **argv) { - Options options; - const int argc_check = argc - 1; - - for (int i = 1; i < argc; ++i) { - if (!strcmp("-h", argv[i]) || !strcmp("-?", argv[i])) { - Usage(); - return 0; - } else if (!strcmp("-i", argv[i]) && i < argc_check) { - options.input = argv[++i]; - } else if (!strcmp("-o", argv[i]) && i < argc_check) { - options.output = argv[++i]; - } else if (!strcmp("-point_cloud", argv[i])) { - options.is_point_cloud = true; - } else if (!strcmp("-qp", argv[i]) && i < argc_check) { - options.pos_quantization_bits = StringToInt(argv[++i]); - if (options.pos_quantization_bits > 30) { - printf( - "Error: The maximum number of quantization bits for the position " - "attribute is 30.\n"); - return -1; - } - } else if (!strcmp("-qt", argv[i]) && i < argc_check) { - options.tex_coords_quantization_bits = StringToInt(argv[++i]); - if (options.tex_coords_quantization_bits > 30) { - printf( - "Error: The maximum number of quantization bits for the texture " - "coordinate attribute is 30.\n"); - return -1; - } - } else if (!strcmp("-qn", argv[i]) && i < argc_check) { - options.normals_quantization_bits = StringToInt(argv[++i]); - if (options.normals_quantization_bits > 30) { - printf( - "Error: The maximum number of quantization bits for the normal " - "attribute is 30.\n"); - return -1; - } - } else if (!strcmp("-qg", argv[i]) && i < argc_check) { - options.generic_quantization_bits = StringToInt(argv[++i]); - if (options.generic_quantization_bits > 30) { - printf( - "Error: The maximum number of quantization bits for generic " - "attributes is 30.\n"); - return -1; - } - } else if (!strcmp("-cl", argv[i]) && i < argc_check) { - options.compression_level = StringToInt(argv[++i]); - } else if (!strcmp("--skip", argv[i]) && i < argc_check) { - if (!strcmp("NORMAL", argv[i + 1])) { - options.normals_quantization_bits = -1; - } else if (!strcmp("TEX_COORD", argv[i + 1])) { - options.tex_coords_quantization_bits = -1; - } else if (!strcmp("GENERIC", argv[i + 1])) { - options.generic_quantization_bits = -1; - } else { - printf("Error: Invalid attribute name after --skip\n"); - return -1; - } - ++i; - } else if (!strcmp("--metadata", argv[i])) { - options.use_metadata = true; - } - } - if (argc < 3 || options.input.empty()) { - Usage(); - return -1; - } - - std::unique_ptr<draco::PointCloud> pc; - draco::Mesh *mesh = nullptr; - if (!options.is_point_cloud) { - auto maybe_mesh = - draco::ReadMeshFromFile(options.input, options.use_metadata); - if (!maybe_mesh.ok()) { - printf("Failed loading the input mesh: %s.\n", - maybe_mesh.status().error_msg()); - return -1; - } - mesh = maybe_mesh.value().get(); - pc = std::move(maybe_mesh).value(); - } else { - auto maybe_pc = draco::ReadPointCloudFromFile(options.input); - if (!maybe_pc.ok()) { - printf("Failed loading the input point cloud: %s.\n", - maybe_pc.status().error_msg()); - return -1; - } - pc = std::move(maybe_pc).value(); - } - - if (options.pos_quantization_bits < 0) { - printf("Error: Position attribute cannot be skipped.\n"); - return -1; - } - - // Delete attributes if needed. This needs to happen before we set any - // quantization settings. - if (options.tex_coords_quantization_bits < 0) { - if (pc->NumNamedAttributes(draco::GeometryAttribute::TEX_COORD) > 0) { - options.tex_coords_deleted = true; - } - while (pc->NumNamedAttributes(draco::GeometryAttribute::TEX_COORD) > 0) { - pc->DeleteAttribute( - pc->GetNamedAttributeId(draco::GeometryAttribute::TEX_COORD, 0)); - } - } - if (options.normals_quantization_bits < 0) { - if (pc->NumNamedAttributes(draco::GeometryAttribute::NORMAL) > 0) { - options.normals_deleted = true; - } - while (pc->NumNamedAttributes(draco::GeometryAttribute::NORMAL) > 0) { - pc->DeleteAttribute( - pc->GetNamedAttributeId(draco::GeometryAttribute::NORMAL, 0)); - } - } - if (options.generic_quantization_bits < 0) { - if (pc->NumNamedAttributes(draco::GeometryAttribute::GENERIC) > 0) { - options.generic_deleted = true; - } - while (pc->NumNamedAttributes(draco::GeometryAttribute::GENERIC) > 0) { - pc->DeleteAttribute( - pc->GetNamedAttributeId(draco::GeometryAttribute::GENERIC, 0)); - } - } -#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED - // If any attribute has been deleted, run deduplication of point indices again - // as some points can be possibly combined. - if (options.tex_coords_deleted || options.normals_deleted || - options.generic_deleted) { - pc->DeduplicatePointIds(); - } -#endif - - // Convert compression level to speed (that 0 = slowest, 10 = fastest). - const int speed = 10 - options.compression_level; - - draco::Encoder encoder; - - // Setup encoder options. - if (options.pos_quantization_bits > 0) { - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, - options.pos_quantization_bits); - } - if (options.tex_coords_quantization_bits > 0) { - encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, - options.tex_coords_quantization_bits); - } - if (options.normals_quantization_bits > 0) { - encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, - options.normals_quantization_bits); - } - if (options.generic_quantization_bits > 0) { - encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, - options.generic_quantization_bits); - } - encoder.SetSpeedOptions(speed, speed); - - if (options.output.empty()) { - // Create a default output file by attaching .drc to the input file name. - options.output = options.input + ".drc"; - } - - PrintOptions(*pc.get(), options); - - int ret = -1; - const bool input_is_mesh = mesh && mesh->num_faces() > 0; - if (input_is_mesh) - ret = EncodeMeshToFile(*mesh, options.output, &encoder); - else - ret = EncodePointCloudToFile(*pc.get(), options.output, &encoder); - - if (ret != -1 && options.compression_level < 10) { - printf( - "For better compression, increase the compression level up to '-cl 10' " - ".\n\n"); - } - - return ret; -} diff --git a/extern/draco/src/common.cpp b/extern/draco/src/common.cpp new file mode 100644 index 00000000000..6f98d8db7ef --- /dev/null +++ b/extern/draco/src/common.cpp @@ -0,0 +1,77 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include <cstring> + +size_t getNumberOfComponents(char *dataType) +{ + if (!strcmp(dataType, "SCALAR")) + { + return 1; + } + if (!strcmp(dataType, "VEC2")) + { + return 2; + } + if (!strcmp(dataType, "VEC3")) + { + return 3; + } + if (!strcmp(dataType, "VEC4")) + { + return 4; + } + if (!strcmp(dataType, "MAT2")) + { + return 4; + } + if (!strcmp(dataType, "MAT3")) + { + return 9; + } + if (!strcmp(dataType, "MAT4")) + { + return 16; + } + + return 0; +} + +size_t getComponentByteLength(size_t componentType) +{ + switch (componentType) + { + case ComponentType::Byte: + case ComponentType::UnsignedByte: + return 1; + + case ComponentType::Short: + case ComponentType::UnsignedShort: + return 2; + + case ComponentType::UnsignedInt: + case ComponentType::Float: + return 4; + + default: + return 0; + } +} + +size_t getAttributeStride(size_t componentType, char *dataType) +{ + return getComponentByteLength(componentType) * getNumberOfComponents(dataType); +} diff --git a/extern/draco/src/common.h b/extern/draco/src/common.h new file mode 100644 index 00000000000..beaf7d91adb --- /dev/null +++ b/extern/draco/src/common.h @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Library for the Draco encoding/decoding feature inside the glTF-Blender-IO project. + * + * The python script within glTF-Blender-IO uses the CTypes library to open the DLL, + * load function pointers add pass the raw data to the encoder. + * + * @author Jim Eckerlein <eckerlein@ux3d.io> + * @date 2020-11-18 + */ + +#pragma once + +#include <cstdint> +#include <cstddef> + +#if defined(_MSC_VER) +#define API(returnType) extern "C" __declspec(dllexport) returnType __cdecl +#else +#define API(returnType) extern "C" returnType +#endif + +enum ComponentType: size_t +{ + Byte = 5120, + UnsignedByte = 5121, + Short = 5122, + UnsignedShort = 5123, + UnsignedInt = 5125, + Float = 5126, +}; + +size_t getNumberOfComponents(char *dataType); + +size_t getComponentByteLength(size_t componentType); + +size_t getAttributeStride(size_t componentType, char *dataType); diff --git a/extern/draco/src/decoder.cpp b/extern/draco/src/decoder.cpp new file mode 100644 index 00000000000..3f3e03bd9f2 --- /dev/null +++ b/extern/draco/src/decoder.cpp @@ -0,0 +1,222 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Jim Eckerlein <eckerlein@ux3d.io> + * @date 2020-11-18 + */ + + +#include "decoder.h" + +#include <memory> +#include <vector> +#include <cinttypes> + +#include "draco/mesh/mesh.h" +#include "draco/core/decoder_buffer.h" +#include "draco/compression/decode.h" + +#define LOG_PREFIX "DracoDecoder | " + +struct Decoder { + std::unique_ptr<draco::Mesh> mesh; + std::vector<uint8_t> indexBuffer; + std::map<uint32_t, std::vector<uint8_t>> buffers; + draco::DecoderBuffer decoderBuffer; + uint32_t vertexCount; + uint32_t indexCount; +}; + +Decoder *decoderCreate() +{ + return new Decoder; +} + +void decoderRelease(Decoder *decoder) +{ + delete decoder; +} + +bool decoderDecode(Decoder *decoder, void *data, size_t byteLength) +{ + draco::Decoder dracoDecoder; + draco::DecoderBuffer dracoDecoderBuffer; + dracoDecoderBuffer.Init(reinterpret_cast<char *>(data), byteLength); + + auto decoderStatus = dracoDecoder.DecodeMeshFromBuffer(&dracoDecoderBuffer); + if (!decoderStatus.ok()) + { + printf(LOG_PREFIX "Error during Draco decoding: %s\n", decoderStatus.status().error_msg()); + return false; + } + + decoder->mesh = std::move(decoderStatus).value(); + decoder->vertexCount = decoder->mesh->num_points(); + decoder->indexCount = decoder->mesh->num_faces() * 3; + + printf(LOG_PREFIX "Decoded %" PRIu32 " vertices, %" PRIu32 " indices\n", decoder->vertexCount, decoder->indexCount); + + return true; +} + +uint32_t decoderGetVertexCount(Decoder *decoder) +{ + return decoder->vertexCount; +} + +uint32_t decoderGetIndexCount(Decoder *decoder) +{ + return decoder->indexCount; +} + +bool decoderAttributeIsNormalized(Decoder *decoder, uint32_t id) +{ + const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id); + return attribute != nullptr && attribute->normalized(); +} + +bool decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType) +{ + const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id); + + if (attribute == nullptr) + { + printf(LOG_PREFIX "Attribute with id=%" PRIu32 " does not exist in Draco data\n", id); + return false; + } + + size_t stride = getAttributeStride(componentType, dataType); + + std::vector<uint8_t> decodedData; + decodedData.resize(stride * decoder->vertexCount); + + for (uint32_t i = 0; i < decoder->vertexCount; ++i) + { + auto index = attribute->mapped_index(draco::PointIndex(i)); + uint8_t *value = decodedData.data() + i * stride; + + bool converted = false; + + switch (componentType) + { + case ComponentType::Byte: + converted = attribute->ConvertValue(index, reinterpret_cast<int8_t *>(value)); + break; + case ComponentType::UnsignedByte: + converted = attribute->ConvertValue(index, reinterpret_cast<uint8_t *>(value)); + break; + case ComponentType::Short: + converted = attribute->ConvertValue(index, reinterpret_cast<int16_t *>(value)); + break; + case ComponentType::UnsignedShort: + converted = attribute->ConvertValue(index, reinterpret_cast<uint16_t *>(value)); + break; + case ComponentType::UnsignedInt: + converted = attribute->ConvertValue(index, reinterpret_cast<uint32_t *>(value)); + break; + case ComponentType::Float: + converted = attribute->ConvertValue(index, reinterpret_cast<float *>(value)); + break; + default: + break; + } + + if (!converted) + { + printf(LOG_PREFIX "Failed to convert Draco attribute type to glTF accessor type for attribute with id=%" PRIu32 "\n", id); + return false; + } + } + + decoder->buffers[id] = decodedData; + return true; +} + +size_t decoderGetAttributeByteLength(Decoder *decoder, size_t id) +{ + auto iter = decoder->buffers.find(id); + if (iter != decoder->buffers.end()) + { + return iter->second.size(); + } + else + { + return 0; + } +} + +void decoderCopyAttribute(Decoder *decoder, size_t id, void *output) +{ + auto iter = decoder->buffers.find(id); + if (iter != decoder->buffers.end()) + { + memcpy(output, iter->second.data(), iter->second.size()); + } +} + +template<class T> +void decodeIndices(Decoder *decoder) +{ + std::vector<uint8_t> decodedIndices; + decodedIndices.resize(decoder->indexCount * sizeof(T)); + T *typedView = reinterpret_cast<T *>(decodedIndices.data()); + + for (uint32_t faceIndex = 0; faceIndex < decoder->mesh->num_faces(); ++faceIndex) + { + const draco::Mesh::Face &face = decoder->mesh->face(draco::FaceIndex(faceIndex)); + typedView[faceIndex * 3 + 0] = face[0].value(); + typedView[faceIndex * 3 + 1] = face[1].value(); + typedView[faceIndex * 3 + 2] = face[2].value(); + } + + decoder->indexBuffer = decodedIndices; +} + +bool decoderReadIndices(Decoder *decoder, size_t indexComponentType) +{ + switch (indexComponentType) + { + case ComponentType::Byte: + decodeIndices<int8_t>(decoder); + break; + case ComponentType::UnsignedByte: + decodeIndices<uint8_t>(decoder); + break; + case ComponentType::Short: + decodeIndices<int16_t>(decoder); + break; + case ComponentType::UnsignedShort: + decodeIndices<uint16_t>(decoder); + break; + case ComponentType::UnsignedInt: + decodeIndices<uint32_t>(decoder); + break; + default: + printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType); + return false; + } + + return true; +} + +size_t decoderGetIndicesByteLength(Decoder *decoder) +{ + return decoder->indexBuffer.size(); +} + +void decoderCopyIndices(Decoder *decoder, void *output) +{ + memcpy(output, decoder->indexBuffer.data(), decoder->indexBuffer.size()); +} diff --git a/extern/draco/src/decoder.h b/extern/draco/src/decoder.h new file mode 100644 index 00000000000..914eb776e8f --- /dev/null +++ b/extern/draco/src/decoder.h @@ -0,0 +1,53 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Library for the Draco encoding/decoding feature inside the glTF-Blender-IO project. + * + * The python script within glTF-Blender-IO uses the CTypes library to open the DLL, + * load function pointers add pass the raw data to the encoder. + * + * @author Jim Eckerlein <eckerlein@ux3d.io> + * @date 2020-11-18 + */ + +#pragma once + +#include "common.h" + +struct Decoder; + +API(Decoder *) decoderCreate(); + +API(void) decoderRelease(Decoder *decoder); + +API(bool) decoderDecode(Decoder *decoder, void *data, size_t byteLength); + +API(uint32_t) decoderGetVertexCount(Decoder *decoder); + +API(uint32_t) decoderGetIndexCount(Decoder *decoder); + +API(bool) decoderAttributeIsNormalized(Decoder *decoder, uint32_t id); + +API(bool) decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType); + +API(size_t) decoderGetAttributeByteLength(Decoder *decoder, size_t id); + +API(void) decoderCopyAttribute(Decoder *decoder, size_t id, void *output); + +API(bool) decoderReadIndices(Decoder *decoder, size_t indexComponentType); + +API(size_t) decoderGetIndicesByteLength(Decoder *decoder); + +API(void) decoderCopyIndices(Decoder *decoder, void *output); diff --git a/extern/draco/src/draco-compressor.cpp b/extern/draco/src/draco-compressor.cpp deleted file mode 100644 index 4ae528888fe..00000000000 --- a/extern/draco/src/draco-compressor.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @author Jim Eckerlein <eckerlein@ux3d.io> - * @date 2019-11-29 - */ - -#include "draco-compressor.h" - -#include <memory> -#include <vector> - -#include "draco/mesh/mesh.h" -#include "draco/core/encoder_buffer.h" -#include "draco/compression/encode.h" - -/** - * Prefix used for logging messages. - */ -const char *logTag = "DRACO-COMPRESSOR"; - -struct DracoCompressor { - draco::Mesh mesh; - - // One data buffer per attribute. - std::vector<std::unique_ptr<draco::DataBuffer>> buffers; - - // The buffer the mesh is compressed into. - draco::EncoderBuffer encoderBuffer; - - // Level of compression [0-10]. - // Higher values mean slower encoding. - uint32_t compressionLevel = 7; - - struct { - uint32_t positions = 14; - uint32_t normals = 10; - uint32_t uvs = 12; - uint32_t generic = 12; - } quantization; -}; - -DracoCompressor *create_compressor() { - return new DracoCompressor; -} - -void set_compression_level( - DracoCompressor *const compressor, - uint32_t const compressionLevel -) { - compressor->compressionLevel = compressionLevel; -} - -void set_position_quantization( - DracoCompressor *const compressor, - uint32_t const quantizationBitsPosition -) { - compressor->quantization.positions = quantizationBitsPosition; -} - -void set_normal_quantization( - DracoCompressor *const compressor, - uint32_t const quantizationBitsNormal -) { - compressor->quantization.normals = quantizationBitsNormal; -} - -void set_uv_quantization( - DracoCompressor *const compressor, - uint32_t const quantizationBitsTexCoord -) { - compressor->quantization.uvs = quantizationBitsTexCoord; -} - -void set_generic_quantization( - DracoCompressor *const compressor, - uint32_t const bits -) { - compressor->quantization.generic = bits; -} - -bool compress( - DracoCompressor *const compressor -) { - draco::Encoder encoder; - - encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel); - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions); - encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, compressor->quantization.normals); - encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, compressor->quantization.uvs); - encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, compressor->quantization.generic); - - return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok(); -} - -bool compress_morphed( - DracoCompressor *const compressor -) { - draco::Encoder encoder; - - encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel); - - // For some reason, `EncodeMeshToBuffer` crashes when not disabling prediction or when enabling quantization - // for attributes other position. - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions); - encoder.SetAttributePredictionScheme(draco::GeometryAttribute::POSITION, draco::PREDICTION_NONE); - encoder.SetAttributePredictionScheme(draco::GeometryAttribute::NORMAL, draco::PREDICTION_NONE); - encoder.SetAttributePredictionScheme(draco::GeometryAttribute::TEX_COORD, draco::PREDICTION_NONE); - encoder.SetAttributePredictionScheme(draco::GeometryAttribute::GENERIC, draco::PREDICTION_NONE); - - // Enforce triangle order preservation. - encoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING); - - return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok(); -} - -uint64_t get_compressed_size( - DracoCompressor const *const compressor -) { - return compressor->encoderBuffer.size(); -} - -void copy_to_bytes( - DracoCompressor const *const compressor, - uint8_t *const o_data -) { - memcpy(o_data, compressor->encoderBuffer.data(), compressor->encoderBuffer.size()); -} - -void destroy_compressor( - DracoCompressor *const compressor -) { - delete compressor; -} - -template<class T> -void set_faces_impl( - draco::Mesh &mesh, - int const index_count, - T const *const indices -) { - mesh.SetNumFaces((size_t) index_count / 3); - - for (int i = 0; i < index_count; i += 3) - { - const auto a = draco::PointIndex(indices[i]); - const auto b = draco::PointIndex(indices[i + 1]); - const auto c = draco::PointIndex(indices[i + 2]); - mesh.SetFace(draco::FaceIndex((uint32_t) i), {a, b, c}); - } -} - -void set_faces( - DracoCompressor *const compressor, - uint32_t const index_count, - uint32_t const index_byte_length, - uint8_t const *const indices -) { - switch (index_byte_length) - { - case 1: - { - set_faces_impl(compressor->mesh, index_count, (uint8_t *) indices); - break; - } - case 2: - { - set_faces_impl(compressor->mesh, index_count, (uint16_t *) indices); - break; - } - case 4: - { - set_faces_impl(compressor->mesh, index_count, (uint32_t *) indices); - break; - } - default: - { - printf("%s: Unsupported index size %d\n", logTag, index_byte_length); - break; - } - } -} - -uint32_t add_attribute_to_mesh( - DracoCompressor *const compressor, - draco::GeometryAttribute::Type const semantics, - draco::DataType const data_type, - uint32_t const count, - uint8_t const component_count, - uint8_t const component_size, - uint8_t const *const data -) { - auto buffer = std::make_unique<draco::DataBuffer>(); - - draco::GeometryAttribute attribute; - - attribute.Init( - semantics, - &*buffer, - component_count, - data_type, - false, - component_size * component_count, - 0 - ); - - auto const id = (uint32_t)compressor->mesh.AddAttribute(attribute, true, count); - - for (uint32_t i = 0; i < count; i++) - { - compressor->mesh.attribute(id)->SetAttributeValue( - draco::AttributeValueIndex(i), - data + i * component_count * component_size - ); - } - - compressor->buffers.emplace_back(std::move(buffer)); - - return id; -} - -uint32_t add_positions_f32( - DracoCompressor *const compressor, - uint32_t const count, - uint8_t const *const data -) { - return add_attribute_to_mesh(compressor, draco::GeometryAttribute::POSITION, - draco::DT_FLOAT32, count, 3, sizeof(float), data); -} - -uint32_t add_normals_f32( - DracoCompressor *const compressor, - uint32_t const count, - uint8_t const *const data -) { - return add_attribute_to_mesh(compressor, draco::GeometryAttribute::NORMAL, - draco::DT_FLOAT32, count, 3, sizeof(float), data); -} - -uint32_t add_uvs_f32( - DracoCompressor *const compressor, - uint32_t const count, - uint8_t const *const data -) { - return add_attribute_to_mesh(compressor, draco::GeometryAttribute::TEX_COORD, - draco::DT_FLOAT32, count, 2, sizeof(float), data); -} - -uint32_t add_joints_u16( - DracoCompressor *compressor, - uint32_t const count, - uint8_t const *const data -) { - return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC, - draco::DT_UINT16, count, 4, sizeof(uint16_t), data); -} - -uint32_t add_weights_f32( - DracoCompressor *compressor, - uint32_t const count, - uint8_t const *const data -) { - return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC, - draco::DT_FLOAT32, count, 4, sizeof(float), data); -} diff --git a/extern/draco/src/draco-compressor.h b/extern/draco/src/draco-compressor.h deleted file mode 100644 index fb6168a61af..00000000000 --- a/extern/draco/src/draco-compressor.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * C++ library for the Draco compression feature inside the glTF-Blender-IO project. - * - * The python side uses the CTypes library to open the DLL, load function - * pointers add pass the data to the compressor as raw bytes. - * - * The compressor intercepts the regular glTF exporter after data has been - * gathered and right before the data is converted to a JSON representation, - * which is going to be written out. - * - * The original uncompressed data is removed and replaces an extension, - * pointing to the newly created buffer containing the compressed data. - * - * @author Jim Eckerlein <eckerlein@ux3d.io> - * @date 2019-11-29 - */ - -#include <cstdint> - -#if defined(_MSC_VER) -#define DLL_EXPORT(retType) extern "C" __declspec(dllexport) retType __cdecl -#else -#define DLL_EXPORT(retType) extern "C" retType -#endif - -/** - * This tuple is opaquely exposed to Python through a pointer. - * It encapsulates the complete current compressor state. - * - * A single instance is only intended to compress a single primitive. - */ -struct DracoCompressor; - -DLL_EXPORT(DracoCompressor *) -create_compressor (); - -DLL_EXPORT(void) -set_compression_level ( - DracoCompressor *compressor, - uint32_t compressionLevel -); - -DLL_EXPORT(void) -set_position_quantization ( - DracoCompressor *compressor, - uint32_t quantizationBitsPosition -); - -DLL_EXPORT(void) -set_normal_quantization ( - DracoCompressor *compressor, - uint32_t quantizationBitsNormal -); - -DLL_EXPORT(void) -set_uv_quantization ( - DracoCompressor *compressor, - uint32_t quantizationBitsTexCoord -); - -DLL_EXPORT(void) -set_generic_quantization ( - DracoCompressor *compressor, - uint32_t bits -); - -/// Compresses a mesh. -/// Use `compress_morphed` when compressing primitives which have morph targets. -DLL_EXPORT(bool) -compress ( - DracoCompressor *compressor -); - -/// Compresses the mesh. -/// Use this instead of `compress`, because this procedure takes into account that mesh triangles must not be reordered. -DLL_EXPORT(bool) -compress_morphed ( - DracoCompressor *compressor -); - -/** - * Returns the size of the compressed data in bytes. - */ -DLL_EXPORT(uint64_t) -get_compressed_size ( - DracoCompressor const *compressor -); - -/** - * Copies the compressed mesh into the given byte buffer. - * - * @param[o_data] A Python `bytes` object. - */ -DLL_EXPORT(void) -copy_to_bytes ( - DracoCompressor const *compressor, - uint8_t *o_data -); - -/** - * Releases all memory allocated by the compressor. - */ -DLL_EXPORT(void) -destroy_compressor ( - DracoCompressor *compressor -); - -DLL_EXPORT(void) -set_faces ( - DracoCompressor *compressor, - uint32_t index_count, - uint32_t index_byte_length, - uint8_t const *indices -); - -/// Adds a `float` position attribute to the current mesh. -/// Returns the id Draco has assigned to this attribute. -DLL_EXPORT(uint32_t) -add_positions_f32 ( - DracoCompressor *compressor, - uint32_t count, - uint8_t const *data -); - -/// Adds a `float` normal attribute to the current mesh. -/// Returns the id Draco has assigned to this attribute. -DLL_EXPORT(uint32_t) -add_normals_f32 ( - DracoCompressor *compressor, - uint32_t count, - uint8_t const *data -); - -/// Adds a `float` texture coordinate attribute to the current mesh. -/// Returns the id Draco has assigned to this attribute. -DLL_EXPORT(uint32_t) -add_uvs_f32 ( - DracoCompressor *compressor, - uint32_t count, - uint8_t const *data -); - -/// Adds a `unsigned short` joint attribute to the current mesh. -/// Returns the id Draco has assigned to this attribute. -DLL_EXPORT(uint32_t) -add_joints_u16 ( - DracoCompressor *compressor, - uint32_t count, - uint8_t const *data -); - -/// Adds a `float` weight attribute to the current mesh. -/// Returns the id Draco has assigned to this attribute. -DLL_EXPORT(uint32_t) -add_weights_f32 ( - DracoCompressor *compressor, - uint32_t count, - uint8_t const *data -); diff --git a/extern/draco/src/encoder.cpp b/extern/draco/src/encoder.cpp new file mode 100644 index 00000000000..ff7570ecfcd --- /dev/null +++ b/extern/draco/src/encoder.cpp @@ -0,0 +1,247 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @author Jim Eckerlein <eckerlein@ux3d.io> + * @date 2019-11-18 + */ + +#include "encoder.h" + +#include <memory> +#include <vector> + +#include "draco/mesh/mesh.h" +#include "draco/core/encoder_buffer.h" +#include "draco/compression/encode.h" + +#define LOG_PREFIX "DracoEncoder | " + +struct Encoder +{ + draco::Mesh mesh; + uint32_t encodedVertices; + uint32_t encodedIndices; + std::vector<std::unique_ptr<draco::DataBuffer>> buffers; + draco::EncoderBuffer encoderBuffer; + uint32_t compressionLevel = 7; + size_t rawSize = 0; + struct + { + uint32_t position = 14; + uint32_t normal = 10; + uint32_t uv = 12; + uint32_t color = 10; + uint32_t generic = 12; + } quantization; +}; + +Encoder *encoderCreate(uint32_t vertexCount) +{ + Encoder *encoder = new Encoder; + encoder->mesh.set_num_points(vertexCount); + return encoder; +} + +void encoderRelease(Encoder *encoder) +{ + delete encoder; +} + +void encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel) { + encoder->compressionLevel = compressionLevel; +} + +void encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic) +{ + encoder->quantization.position = position; + encoder->quantization.normal = normal; + encoder->quantization.uv = uv; + encoder->quantization.color = color; + encoder->quantization.generic = generic; +} + +bool encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder) +{ + printf(LOG_PREFIX "Preserve triangle order: %s\n", preserveTriangleOrder ? "yes" : "no"); + + draco::Encoder dracoEncoder; + + int speed = 10 - static_cast<int>(encoder->compressionLevel); + dracoEncoder.SetSpeedOptions(speed, speed); + + dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, encoder->quantization.position); + dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, encoder->quantization.normal); + dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, encoder->quantization.uv); + dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, encoder->quantization.color); + dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, encoder->quantization.generic); + dracoEncoder.SetTrackEncodedProperties(true); + + if (preserveTriangleOrder) + { + dracoEncoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING); + } + + auto encoderStatus = dracoEncoder.EncodeMeshToBuffer(encoder->mesh, &encoder->encoderBuffer); + if (encoderStatus.ok()) + { + encoder->encodedVertices = static_cast<uint32_t>(dracoEncoder.num_encoded_points()); + encoder->encodedIndices = static_cast<uint32_t>(dracoEncoder.num_encoded_faces() * 3); + size_t encodedSize = encoder->encoderBuffer.size(); + float compressionRatio = static_cast<float>(encoder->rawSize) / static_cast<float>(encodedSize); + printf(LOG_PREFIX "Encoded %" PRIu32 " vertices, %" PRIu32 " indices, raw size: %zu, encoded size: %zu, compression ratio: %.2f\n", encoder->encodedVertices, encoder->encodedIndices, encoder->rawSize, encodedSize, compressionRatio); + return true; + } + else + { + printf(LOG_PREFIX "Error during Draco encoding: %s\n", encoderStatus.error_msg()); + return false; + } +} + +uint32_t encoderGetEncodedVertexCount(Encoder *encoder) +{ + return encoder->encodedVertices; +} + +uint32_t encoderGetEncodedIndexCount(Encoder *encoder) +{ + return encoder->encodedIndices; +} + +uint64_t encoderGetByteLength(Encoder *encoder) +{ + return encoder->encoderBuffer.size(); +} + +void encoderCopy(Encoder *encoder, uint8_t *data) +{ + memcpy(data, encoder->encoderBuffer.data(), encoder->encoderBuffer.size()); +} + +template<class T> +void encodeIndices(Encoder *encoder, uint32_t indexCount, T *indices) +{ + int face_count = indexCount / 3; + encoder->mesh.SetNumFaces(static_cast<size_t>(face_count)); + encoder->rawSize += indexCount * sizeof(T); + + for (int i = 0; i < face_count; ++i) + { + draco::Mesh::Face face = { + draco::PointIndex(indices[3 * i + 0]), + draco::PointIndex(indices[3 * i + 1]), + draco::PointIndex(indices[3 * i + 2]) + }; + encoder->mesh.SetFace(draco::FaceIndex(static_cast<uint32_t>(i)), face); + } +} + +void encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices) +{ + switch (indexComponentType) + { + case ComponentType::Byte: + encodeIndices(encoder, indexCount, reinterpret_cast<int8_t *>(indices)); + break; + case ComponentType::UnsignedByte: + encodeIndices(encoder, indexCount, reinterpret_cast<uint8_t *>(indices)); + break; + case ComponentType::Short: + encodeIndices(encoder, indexCount, reinterpret_cast<int16_t *>(indices)); + break; + case ComponentType::UnsignedShort: + encodeIndices(encoder, indexCount, reinterpret_cast<uint16_t *>(indices)); + break; + case ComponentType::UnsignedInt: + encodeIndices(encoder, indexCount, reinterpret_cast<uint32_t *>(indices)); + break; + default: + printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType); + } +} + +draco::GeometryAttribute::Type getAttributeSemantics(char *attribute) +{ + if (!strcmp(attribute, "POSITION")) + { + return draco::GeometryAttribute::POSITION; + } + if (!strcmp(attribute, "NORMAL")) + { + return draco::GeometryAttribute::NORMAL; + } + if (!strncmp(attribute, "TEXCOORD", strlen("TEXCOORD"))) + { + return draco::GeometryAttribute::TEX_COORD; + } + if (!strncmp(attribute, "COLOR", strlen("COLOR"))) + { + return draco::GeometryAttribute::COLOR; + } + + return draco::GeometryAttribute::GENERIC; +} + +draco::DataType getDataType(size_t componentType) +{ + switch (componentType) + { + case ComponentType::Byte: + return draco::DataType::DT_INT8; + + case ComponentType::UnsignedByte: + return draco::DataType::DT_UINT8; + + case ComponentType::Short: + return draco::DataType::DT_INT16; + + case ComponentType::UnsignedShort: + return draco::DataType::DT_UINT16; + + case ComponentType::UnsignedInt: + return draco::DataType::DT_UINT32; + + case ComponentType::Float: + return draco::DataType::DT_FLOAT32; + + default: + return draco::DataType::DT_INVALID; + } +} + +API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data) +{ + auto buffer = std::make_unique<draco::DataBuffer>(); + uint32_t count = encoder->mesh.num_points(); + size_t componentCount = getNumberOfComponents(dataType); + size_t stride = getAttributeStride(componentType, dataType); + draco::DataType dracoDataType = getDataType(componentType); + + draco::GeometryAttribute::Type semantics = getAttributeSemantics(attributeName); + draco::GeometryAttribute attribute; + attribute.Init(semantics, &*buffer, componentCount, getDataType(componentType), false, stride, 0); + + auto id = static_cast<uint32_t>(encoder->mesh.AddAttribute(attribute, true, count)); + auto dataBytes = reinterpret_cast<uint8_t *>(data); + + for (uint32_t i = 0; i < count; i++) + { + encoder->mesh.attribute(id)->SetAttributeValue(draco::AttributeValueIndex(i), dataBytes + i * stride); + } + + encoder->buffers.emplace_back(std::move(buffer)); + encoder->rawSize += count * stride; + return id; +} diff --git a/extern/draco/src/encoder.h b/extern/draco/src/encoder.h new file mode 100644 index 00000000000..2f7f21a469b --- /dev/null +++ b/extern/draco/src/encoder.h @@ -0,0 +1,51 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Library for the Draco encoding/decoding feature inside the glTF-Blender-IO project. + * + * The python script within glTF-Blender-IO uses the CTypes library to open the DLL, + * load function pointers add pass the raw data to the encoder. + * + * @author Jim Eckerlein <eckerlein@ux3d.io> + * @date 2020-11-18 + */ + +#pragma once + +#include "common.h" + +struct Encoder; + +API(Encoder *) encoderCreate(uint32_t vertexCount); + +API(void) encoderRelease(Encoder *encoder); + +API(void) encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel); + +API(void) encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic); + +API(bool) encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder); + +API(uint64_t) encoderGetByteLength(Encoder *encoder); + +API(void) encoderCopy(Encoder *encoder, uint8_t *data); + +API(void) encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices); + +API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data); + +API(uint32_t) encoderGetEncodedVertexCount(Encoder *encoder); + +API(uint32_t) encoderGetEncodedIndexCount(Encoder *encoder); diff --git a/extern/gflags/README.blender b/extern/gflags/README.blender index be68c310997..068c0507d04 100644 --- a/extern/gflags/README.blender +++ b/extern/gflags/README.blender @@ -1,6 +1,6 @@ Project: Google Flags URL: https://github.com/gflags/gflags -License: New BSD +License: BSD 3-Clause Upstream version: 2.2.1 (46f73f88b18) Local modifications: diff --git a/extern/glew-es/LICENSE.txt b/extern/glew-es/LICENSE.txt new file mode 100644 index 00000000000..f7078042e95 --- /dev/null +++ b/extern/glew-es/LICENSE.txt @@ -0,0 +1,73 @@ +The OpenGL Extension Wrangler Library +Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org> +Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org> +Copyright (C) 2002, Lev Povalahev +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* The name of the author may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 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 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + + +Mesa 3-D graphics library +Version: 7.0 + +Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Copyright (c) 2007 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. diff --git a/extern/glew-es/README.blender b/extern/glew-es/README.blender new file mode 100644 index 00000000000..59a932a07f1 --- /dev/null +++ b/extern/glew-es/README.blender @@ -0,0 +1,5 @@ +Project: The OpenGL Extension Wrangler Library +URL: http://glew.sourceforge.net/ +License: Check LICENSE.txt +Upstream version: 2.0.0 +Local modifications: None diff --git a/extern/glew/LICENSE.txt b/extern/glew/LICENSE.txt new file mode 100644 index 00000000000..f7078042e95 --- /dev/null +++ b/extern/glew/LICENSE.txt @@ -0,0 +1,73 @@ +The OpenGL Extension Wrangler Library +Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org> +Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org> +Copyright (C) 2002, Lev Povalahev +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* The name of the author may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 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 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + + +Mesa 3-D graphics library +Version: 7.0 + +Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Copyright (c) 2007 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. diff --git a/extern/glew/README.blender b/extern/glew/README.blender new file mode 100644 index 00000000000..59a932a07f1 --- /dev/null +++ b/extern/glew/README.blender @@ -0,0 +1,5 @@ +Project: The OpenGL Extension Wrangler Library +URL: http://glew.sourceforge.net/ +License: Check LICENSE.txt +Upstream version: 2.0.0 +Local modifications: None diff --git a/extern/glog/README.blender b/extern/glog/README.blender index 62cd065ef0f..5b4dab199bf 100644 --- a/extern/glog/README.blender +++ b/extern/glog/README.blender @@ -1,6 +1,6 @@ Project: Google Logging URL: https://github.com/google/glog -License: New BSD +License: BSD 3-Clause Upstream version: 0.4.0, 96a2f23dca4 Local modifications: * Added per-platform config.h files so no configuration-time diff --git a/extern/gmock/README.blender b/extern/gmock/README.blender index 3f9d80362d8..23e750177b8 100644 --- a/extern/gmock/README.blender +++ b/extern/gmock/README.blender @@ -1,5 +1,5 @@ Project: Google C++ Testing Framework URL: https://github.com/google/googletest -License: New BSD +License: BSD 3-Clause Upstream version: 1.10.0 (703bd9caab5) Local modifications: None diff --git a/extern/gtest/README.blender b/extern/gtest/README.blender index 3f9d80362d8..23e750177b8 100644 --- a/extern/gtest/README.blender +++ b/extern/gtest/README.blender @@ -1,5 +1,5 @@ Project: Google C++ Testing Framework URL: https://github.com/google/googletest -License: New BSD +License: BSD 3-Clause Upstream version: 1.10.0 (703bd9caab5) Local modifications: None diff --git a/extern/lzma/README.blender b/extern/lzma/README.blender new file mode 100644 index 00000000000..0111946e30e --- /dev/null +++ b/extern/lzma/README.blender @@ -0,0 +1,5 @@ +Project: LZMA SDK +URL: https://www.7-zip.org/sdk.html +License: Public Domain +Upstream version: 4.65 +Local modifications: None diff --git a/extern/lzo/README.blender b/extern/lzo/README.blender new file mode 100644 index 00000000000..d91500b7780 --- /dev/null +++ b/extern/lzo/README.blender @@ -0,0 +1,5 @@ +Project: miniLZO - mini subset of the LZO real-time data compression librar +URL: http://www.oberhumer.com/opensource/lzo/ +License: GPLv2+ +Upstream version: 2.08 +Local modifications: None diff --git a/extern/mantaflow/README.blender b/extern/mantaflow/README.blender new file mode 100644 index 00000000000..bc1e2a164dc --- /dev/null +++ b/extern/mantaflow/README.blender @@ -0,0 +1,5 @@ +Project: Mantaflow +URL: http://mantaflow.com/ +License: Apache 2.0 +Upstream version: 0.13 +Local modifications: None diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h index d7a69564a3b..a0590e6a0b0 100644 --- a/extern/mantaflow/preprocessed/gitinfo.h +++ b/extern/mantaflow/preprocessed/gitinfo.h @@ -1,3 +1,3 @@ -#define MANTA_GIT_VERSION "commit bb7cde47b6e04fa62815c70775dc70f02065599f" +#define MANTA_GIT_VERSION "commit 327917cd59b03bef3a953b5f58fc1637b3a83e01" diff --git a/extern/mantaflow/preprocessed/plugin/advection.cpp b/extern/mantaflow/preprocessed/plugin/advection.cpp index 4ccf33cc362..dd891e22088 100644 --- a/extern/mantaflow/preprocessed/plugin/advection.cpp +++ b/extern/mantaflow/preprocessed/plugin/advection.cpp @@ -1090,8 +1090,8 @@ struct extrapolateVelConvectiveBC : public KernelBase { Real timeStep) const { if (flags.isOutflow(i, j, k)) { - Vec3 bulkVel = getBulkVel(flags, vel, i, j, k); - int dim = flags.is3D() ? 3 : 2; + const Vec3 bulkVel = getBulkVel(flags, vel, i, j, k); + const int dim = flags.is3D() ? 3 : 2; const Vec3i cur = Vec3i(i, j, k); Vec3i low, up, flLow, flUp; int cnt = 0; @@ -1099,8 +1099,8 @@ struct extrapolateVelConvectiveBC : public KernelBase { for (int c = 0; c < dim; c++) { low = up = flLow = flUp = cur; Real factor = timeStep * - max((Real)1.0, bulkVel[c]); // prevent the extrapolated velocity from - // exploding when bulk velocity below 1 + max((Real)1.0, abs(bulkVel[c])); // prevent the extrapolated velocity from + // exploding when bulk velocity below 1 low[c] = flLow[c] = cur[c] - 1; up[c] = flUp[c] = cur[c] + 1; // iterate over bWidth to allow for extrapolation into more distant outflow cells; diff --git a/extern/mantaflow/preprocessed/plugin/pressure.cpp b/extern/mantaflow/preprocessed/plugin/pressure.cpp index dfba8e0082b..1100a58db47 100644 --- a/extern/mantaflow/preprocessed/plugin/pressure.cpp +++ b/extern/mantaflow/preprocessed/plugin/pressure.cpp @@ -1147,26 +1147,18 @@ void solvePressureSystem(Grid<Real> &rhs, gcg->setAccuracy(cgAccuracy); gcg->setUseL2Norm(useL2Norm); - int maxIter = 0; + int maxIter = (int)(cgMaxIterFac * flags.getSize().max()) * (flags.is3D() ? 1 : 4); Grid<Real> *pca0 = nullptr, *pca1 = nullptr, *pca2 = nullptr, *pca3 = nullptr; GridMg *pmg = nullptr; // optional preconditioning - if (preconditioner == PcNone || preconditioner == PcMIC) { - maxIter = (int)(cgMaxIterFac * flags.getSize().max()) * (flags.is3D() ? 1 : 4); - + if (preconditioner == PcMIC) { pca0 = new Grid<Real>(parent); pca1 = new Grid<Real>(parent); pca2 = new Grid<Real>(parent); pca3 = new Grid<Real>(parent); - - gcg->setICPreconditioner(preconditioner == PcMIC ? GridCgInterface::PC_mICP : - GridCgInterface::PC_None, - pca0, - pca1, - pca2, - pca3); + gcg->setICPreconditioner(GridCgInterface::PC_mICP, pca0, pca1, pca2, pca3); } else if (preconditioner == PcMGDynamic || preconditioner == PcMGStatic) { maxIter = 100; diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h index e6ca7a105ba..ad404c756ce 100644 --- a/intern/atomic/atomic_ops.h +++ b/intern/atomic/atomic_ops.h @@ -87,6 +87,9 @@ ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x); ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x); ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x); +ATOMIC_INLINE int16_t atomic_fetch_and_or_int16(int16_t *p, int16_t b); +ATOMIC_INLINE int16_t atomic_fetch_and_and_int16(int16_t *p, int16_t b); + ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b); ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b); diff --git a/intern/atomic/intern/atomic_ops_msvc.h b/intern/atomic/intern/atomic_ops_msvc.h index 356140541ba..c9ad1a46ab9 100644 --- a/intern/atomic/intern/atomic_ops_msvc.h +++ b/intern/atomic/intern/atomic_ops_msvc.h @@ -163,6 +163,20 @@ ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x) } /******************************************************************************/ +/* 16-bit operations. */ + +/* Signed */ +ATOMIC_INLINE int16_t atomic_fetch_and_or_int16(int16_t *p, int16_t x) +{ + return InterlockedOr16((short *)p, x); +} + +ATOMIC_INLINE int16_t atomic_fetch_and_and_int16(int16_t *p, int16_t x) +{ + return InterlockedAnd16((short *)p, x); +} + +/******************************************************************************/ /* 8-bit operations. */ /* Unsigned */ diff --git a/intern/atomic/intern/atomic_ops_unix.h b/intern/atomic/intern/atomic_ops_unix.h index 0de9daaaf5f..dc1e71cda76 100644 --- a/intern/atomic/intern/atomic_ops_unix.h +++ b/intern/atomic/intern/atomic_ops_unix.h @@ -55,6 +55,7 @@ * its gcc doesn't have __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n defined. */ # define JE_FORCE_SYNC_COMPARE_AND_SWAP_1 +# define JE_FORCE_SYNC_COMPARE_AND_SWAP_2 # define JE_FORCE_SYNC_COMPARE_AND_SWAP_4 # define JE_FORCE_SYNC_COMPARE_AND_SWAP_8 #endif @@ -326,6 +327,24 @@ ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x) #endif /******************************************************************************/ +/* 16-bit operations. */ +#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_2)) + +/* Signed */ +ATOMIC_INLINE int16_t atomic_fetch_and_and_int16(int16_t *p, int16_t b) +{ + return __sync_fetch_and_and(p, b); +} +ATOMIC_INLINE int16_t atomic_fetch_and_or_int16(int16_t *p, int16_t b) +{ + return __sync_fetch_and_or(p, b); +} + +#else +# error "Missing implementation for 16-bit atomic operations" +#endif + +/******************************************************************************/ /* 8-bit operations. */ #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_1)) /* Unsigned */ diff --git a/intern/atomic/tests/atomic_test.cc b/intern/atomic/tests/atomic_test.cc index 6178b5074a7..661c130c65d 100644 --- a/intern/atomic/tests/atomic_test.cc +++ b/intern/atomic/tests/atomic_test.cc @@ -559,6 +559,39 @@ TEST(atomic, atomic_fetch_and_and_int32) /** \} */ +/** \name 16 bit signed int atomics + * \{ */ + +TEST(atomic, atomic_fetch_and_or_int16) +{ + { + int16_t value = 12; + EXPECT_EQ(atomic_fetch_and_or_int16(&value, 5), 12); + EXPECT_EQ(value, 13); + } + + { + int16_t value = 0x1234; + EXPECT_EQ(atomic_fetch_and_or_int16(&value, -0x5678), 0x1234); + EXPECT_EQ(value, -0x4444); + } +} + +TEST(atomic, atomic_fetch_and_and_int16) +{ + { + int16_t value = 12; + EXPECT_EQ(atomic_fetch_and_and_int16(&value, 5), 12); + EXPECT_EQ(value, 4); + } + + { + int16_t value = 0x1234; + EXPECT_EQ(atomic_fetch_and_and_int16(&value, -0x789A), 0x1234); + EXPECT_EQ(value, 0x224); + } +} + /** \name 8 bit unsigned int atomics * \{ */ diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 807dcaf7f43..69ad1321c1a 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -270,14 +270,14 @@ def list_render_passes(scene, srl): if crl.use_pass_volume_indirect: yield ("VolumeInd", "RGB", 'COLOR') # Cryptomatte passes. - crypto_depth = (crl.pass_crypto_depth + 1) // 2 - if crl.use_pass_crypto_object: + crypto_depth = (srl.pass_cryptomatte_depth + 1) // 2 + if srl.use_pass_cryptomatte_object: for i in range(0, crypto_depth): yield ("CryptoObject" + '{:02d}'.format(i), "RGBA", 'COLOR') - if crl.use_pass_crypto_material: + if srl.use_pass_cryptomatte_material: for i in range(0, crypto_depth): yield ("CryptoMaterial" + '{:02d}'.format(i), "RGBA", 'COLOR') - if srl.cycles.use_pass_crypto_asset: + if srl.use_pass_cryptomatte_asset: for i in range(0, crypto_depth): yield ("CryptoAsset" + '{:02d}'.format(i), "RGBA", 'COLOR') diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 054fd900419..1cb29fc6cb0 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1470,37 +1470,6 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup): default='RGB_ALBEDO_NORMAL', ) - use_pass_crypto_object: BoolProperty( - name="Cryptomatte Object", - description="Render cryptomatte object pass, for isolating objects in compositing", - default=False, - update=update_render_passes, - ) - use_pass_crypto_material: BoolProperty( - name="Cryptomatte Material", - description="Render cryptomatte material pass, for isolating materials in compositing", - default=False, - update=update_render_passes, - ) - use_pass_crypto_asset: BoolProperty( - name="Cryptomatte Asset", - description="Render cryptomatte asset pass, for isolating groups of objects with the same parent", - default=False, - update=update_render_passes, - ) - pass_crypto_depth: IntProperty( - name="Cryptomatte Levels", - description="Sets how many unique objects can be distinguished per pixel", - default=6, min=2, max=16, step=2, - update=update_render_passes, - ) - pass_crypto_accurate: BoolProperty( - name="Cryptomatte Accurate", - description="Generate a more accurate Cryptomatte pass. CPU only, may render slower and use more memory", - default=True, - update=update_render_passes, - ) - aovs: CollectionProperty( type=CyclesAOVPass, description="Custom render passes that can be output by shader nodes", @@ -1651,11 +1620,6 @@ class CyclesPreferences(bpy.types.AddonPreferences): for device in devices: box.prop(device, "use", text=device.name) - if device_type == 'OPTIX': - col = box.column(align=True) - col.label(text="OptiX support is experimental", icon='INFO') - col.label(text="Not all Cycles features are supported yet", icon='BLANK1') - def draw_impl(self, layout, context): row = layout.row() row.prop(self, "compute_device_type", expand=True) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 6b88be3e7aa..f24265d256a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -23,6 +23,7 @@ from bl_ui.utils import PresetPanel from bpy.types import Panel from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel +from bl_ui.properties_view_layer import ViewLayerCryptomattePanel class CYCLES_PT_sampling_presets(PresetPanel, Panel): @@ -885,31 +886,11 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel): col.prop(view_layer, "use_pass_ambient_occlusion", text="Ambient Occlusion") -class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, Panel): +class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, ViewLayerCryptomattePanel): bl_label = "Cryptomatte" bl_context = "view_layer" bl_parent_id = "CYCLES_RENDER_PT_passes" - def draw(self, context): - import _cycles - - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False - - cycles_view_layer = context.view_layer.cycles - - col = layout.column(heading="Include", align=True) - col.prop(cycles_view_layer, "use_pass_crypto_object", text="Object") - col.prop(cycles_view_layer, "use_pass_crypto_material", text="Material") - col.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset") - - layout.prop(cycles_view_layer, "pass_crypto_depth", text="Levels") - - row = layout.row(align=True) - row.active = use_cpu(context) - row.prop(cycles_view_layer, "pass_crypto_accurate", text="Accurate Mode") - class CYCLES_RENDER_PT_passes_debug(CyclesButtonsPanel, Panel): bl_label = "Debug" @@ -1841,10 +1822,6 @@ class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel): bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'CYCLES'} - @classmethod - def poll(cls, context): - return CyclesButtonsPanel.poll(context) and not use_optix(context) - def draw(self, context): layout = self.layout layout.use_property_split = True @@ -1855,6 +1832,9 @@ class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel): cbk = scene.render.bake rd = scene.render + if use_optix(context): + layout.label(text="Baking is performed using CUDA instead of OptiX", icon='INFO') + if rd.use_bake_multires: layout.operator("object.bake_image", icon='RENDER_STILL') layout.prop(rd, "use_bake_multires") diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index f7e3e693858..5dae88d60c7 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -108,7 +108,7 @@ def do_versions(self): library_versions.setdefault(library.version, []).append(library) # Do versioning per library, since they might have different versions. - max_need_versioning = (2, 80, 41) + max_need_versioning = (2, 92, 4) for version, libraries in library_versions.items(): if version > max_need_versioning: continue @@ -194,6 +194,16 @@ def do_versions(self): if not cscene.is_property_set("sample_clamp_indirect"): cscene.sample_clamp_indirect = 0.0 + if version <= (2, 92, 4): + if scene.render.engine == 'CYCLES': + for view_layer in scene.view_layers: + cview_layer = view_layer.cycles + view_layer.use_pass_cryptomatte_object = cview_layer.get("use_pass_crypto_object", False) + view_layer.use_pass_cryptomatte_material = cview_layer.get("use_pass_crypto_material", False) + view_layer.use_pass_cryptomatte_asset = cview_layer.get("use_pass_crypto_asset", False) + view_layer.pass_cryptomatte_depth = cview_layer.get("pass_crypto_depth", 6) + view_layer.use_pass_cryptomatte_accurate = cview_layer.get("pass_crypto_accurate", True) + # Lamps for light in bpy.data.lights: if light.library not in libraries: diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index e85b4ee1fc6..3420025f472 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -1064,6 +1064,8 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me /* update original sockets */ + mesh->clear_non_sockets(); + for (const SocketType &socket : new_mesh.type->inputs) { /* Those sockets are updated in sync_object, so do not modify them. */ if (socket.name == "use_motion_blur" || socket.name == "motion_steps" || diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 94ff0ff1473..b830db7485b 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -667,10 +667,10 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, /* Cryptomatte stores two ID/weight pairs per RGBA layer. * User facing parameter is the number of pairs. */ - int crypto_depth = divide_up(min(16, get_int(crl, "pass_crypto_depth")), 2); + int crypto_depth = divide_up(min(16, b_view_layer.pass_cryptomatte_depth()), 2); scene->film->set_cryptomatte_depth(crypto_depth); CryptomatteType cryptomatte_passes = CRYPT_NONE; - if (get_boolean(crl, "use_pass_crypto_object")) { + if (b_view_layer.use_pass_cryptomatte_object()) { for (int i = 0; i < crypto_depth; i++) { string passname = cryptomatte_prefix + string_printf("Object%02d", i); b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); @@ -678,7 +678,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT); } - if (get_boolean(crl, "use_pass_crypto_material")) { + if (b_view_layer.use_pass_cryptomatte_material()) { for (int i = 0; i < crypto_depth; i++) { string passname = cryptomatte_prefix + string_printf("Material%02d", i); b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); @@ -686,7 +686,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL); } - if (get_boolean(crl, "use_pass_crypto_asset")) { + if (b_view_layer.use_pass_cryptomatte_asset()) { for (int i = 0; i < crypto_depth; i++) { string passname = cryptomatte_prefix + string_printf("Asset%02d", i); b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str()); @@ -694,7 +694,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET); } - if (get_boolean(crl, "pass_crypto_accurate") && cryptomatte_passes != CRYPT_NONE) { + if (b_view_layer.use_pass_cryptomatte_accurate() && cryptomatte_passes != CRYPT_NONE) { cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ACCURATE); } scene->film->set_cryptomatte_passes(cryptomatte_passes); diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp index 95234845f98..c6276c1e955 100644 --- a/intern/cycles/device/device_optix.cpp +++ b/intern/cycles/device/device_optix.cpp @@ -141,7 +141,8 @@ class OptiXDevice : public CUDADevice { PG_BAKE, // kernel_bake_evaluate PG_DISP, // kernel_displace_evaluate PG_BACK, // kernel_background_evaluate - NUM_PROGRAM_GROUPS + PG_CALL, + NUM_PROGRAM_GROUPS = PG_CALL + 3 }; // List of OptiX pipelines @@ -296,6 +297,10 @@ class OptiXDevice : public CUDADevice { BVHLayoutMask get_bvh_layout_mask() const override { + // CUDA kernels are used when doing baking, so need to build a BVH those can understand too! + if (optix_module == NULL) + return CUDADevice::get_bvh_layout_mask(); + // OptiX has its own internal acceleration structure format return BVH_LAYOUT_OPTIX; } @@ -329,15 +334,9 @@ class OptiXDevice : public CUDADevice { return false; } - // Disable baking for now, since its kernel is not well-suited for inlining and is very slow + // Baking is currently performed using CUDA, so no need to load OptiX kernels if (requested_features.use_baking) { - set_error("OptiX backend does not support baking yet"); - return false; - } - // Disable shader raytracing support for now, since continuation callables are slow - if (requested_features.use_shader_raytrace) { - set_error("OptiX backend does not support 'Ambient Occlusion' and 'Bevel' shader nodes yet"); - return false; + return true; } const CUDAContextScope scope(cuContext); @@ -410,7 +409,9 @@ class OptiXDevice : public CUDADevice { } { // Load and compile PTX module with OptiX kernels - string ptx_data, ptx_filename = path_get("lib/kernel_optix.ptx"); + string ptx_data, ptx_filename = path_get(requested_features.use_shader_raytrace ? + "lib/kernel_optix_shader_raytrace.ptx" : + "lib/kernel_optix.ptx"); if (use_adaptive_compilation() || path_file_size(ptx_filename) == -1) { if (!getenv("OPTIX_ROOT_DIR")) { set_error( @@ -525,6 +526,21 @@ class OptiXDevice : public CUDADevice { group_descs[PG_BACK].raygen.entryFunctionName = "__raygen__kernel_optix_background"; } + // Shader raytracing replaces some functions with direct callables + if (requested_features.use_shader_raytrace) { + group_descs[PG_CALL + 0].kind = OPTIX_PROGRAM_GROUP_KIND_CALLABLES; + group_descs[PG_CALL + 0].callables.moduleDC = optix_module; + group_descs[PG_CALL + 0].callables.entryFunctionNameDC = "__direct_callable__svm_eval_nodes"; + group_descs[PG_CALL + 1].kind = OPTIX_PROGRAM_GROUP_KIND_CALLABLES; + group_descs[PG_CALL + 1].callables.moduleDC = optix_module; + group_descs[PG_CALL + 1].callables.entryFunctionNameDC = + "__direct_callable__kernel_volume_shadow"; + group_descs[PG_CALL + 2].kind = OPTIX_PROGRAM_GROUP_KIND_CALLABLES; + group_descs[PG_CALL + 2].callables.moduleDC = optix_module; + group_descs[PG_CALL + 2].callables.entryFunctionNameDC = + "__direct_callable__subsurface_scatter_multi_setup"; + } + check_result_optix_ret(optixProgramGroupCreate( context, group_descs, NUM_PROGRAM_GROUPS, &group_options, nullptr, 0, groups)); @@ -564,33 +580,51 @@ class OptiXDevice : public CUDADevice { # endif { // Create path tracing pipeline - OptixProgramGroup pipeline_groups[] = { - groups[PG_RGEN], - groups[PG_MISS], - groups[PG_HITD], - groups[PG_HITS], - groups[PG_HITL], + vector<OptixProgramGroup> pipeline_groups; + pipeline_groups.reserve(NUM_PROGRAM_GROUPS); + pipeline_groups.push_back(groups[PG_RGEN]); + pipeline_groups.push_back(groups[PG_MISS]); + pipeline_groups.push_back(groups[PG_HITD]); + pipeline_groups.push_back(groups[PG_HITS]); + pipeline_groups.push_back(groups[PG_HITL]); # if OPTIX_ABI_VERSION >= 36 - groups[PG_HITD_MOTION], - groups[PG_HITS_MOTION], + if (motion_blur) { + pipeline_groups.push_back(groups[PG_HITD_MOTION]); + pipeline_groups.push_back(groups[PG_HITS_MOTION]); + } # endif - }; - check_result_optix_ret( - optixPipelineCreate(context, - &pipeline_options, - &link_options, - pipeline_groups, - (sizeof(pipeline_groups) / sizeof(pipeline_groups[0])), - nullptr, - 0, - &pipelines[PIP_PATH_TRACE])); + if (requested_features.use_shader_raytrace) { + pipeline_groups.push_back(groups[PG_CALL + 0]); + pipeline_groups.push_back(groups[PG_CALL + 1]); + pipeline_groups.push_back(groups[PG_CALL + 2]); + } + + check_result_optix_ret(optixPipelineCreate(context, + &pipeline_options, + &link_options, + pipeline_groups.data(), + pipeline_groups.size(), + nullptr, + 0, + &pipelines[PIP_PATH_TRACE])); // Combine ray generation and trace continuation stack size const unsigned int css = stack_size[PG_RGEN].cssRG + link_options.maxTraceDepth * trace_css; + // Max direct callable depth is one of the following, so combine accordingly + // - __raygen__ -> svm_eval_nodes + // - __raygen__ -> kernel_volume_shadow -> svm_eval_nodes + // - __raygen__ -> subsurface_scatter_multi_setup -> svm_eval_nodes + const unsigned int dss = stack_size[PG_CALL + 0].dssDC + + std::max(stack_size[PG_CALL + 1].dssDC, + stack_size[PG_CALL + 2].dssDC); // Set stack size depending on pipeline options check_result_optix_ret( - optixPipelineSetStackSize(pipelines[PIP_PATH_TRACE], 0, 0, css, (motion_blur ? 3 : 2))); + optixPipelineSetStackSize(pipelines[PIP_PATH_TRACE], + 0, + requested_features.use_shader_raytrace ? dss : 0, + css, + motion_blur ? 3 : 2)); } // Only need to create shader evaluation pipeline if one of these features is used: @@ -599,37 +633,51 @@ class OptiXDevice : public CUDADevice { requested_features.use_true_displacement; if (use_shader_eval_pipeline) { // Create shader evaluation pipeline - OptixProgramGroup pipeline_groups[] = { - groups[PG_BAKE], - groups[PG_DISP], - groups[PG_BACK], - groups[PG_MISS], - groups[PG_HITD], - groups[PG_HITS], - groups[PG_HITL], + vector<OptixProgramGroup> pipeline_groups; + pipeline_groups.reserve(NUM_PROGRAM_GROUPS); + pipeline_groups.push_back(groups[PG_BAKE]); + pipeline_groups.push_back(groups[PG_DISP]); + pipeline_groups.push_back(groups[PG_BACK]); + pipeline_groups.push_back(groups[PG_MISS]); + pipeline_groups.push_back(groups[PG_HITD]); + pipeline_groups.push_back(groups[PG_HITS]); + pipeline_groups.push_back(groups[PG_HITL]); # if OPTIX_ABI_VERSION >= 36 - groups[PG_HITD_MOTION], - groups[PG_HITS_MOTION], + if (motion_blur) { + pipeline_groups.push_back(groups[PG_HITD_MOTION]); + pipeline_groups.push_back(groups[PG_HITS_MOTION]); + } # endif - }; - check_result_optix_ret( - optixPipelineCreate(context, - &pipeline_options, - &link_options, - pipeline_groups, - (sizeof(pipeline_groups) / sizeof(pipeline_groups[0])), - nullptr, - 0, - &pipelines[PIP_SHADER_EVAL])); + if (requested_features.use_shader_raytrace) { + pipeline_groups.push_back(groups[PG_CALL + 0]); + pipeline_groups.push_back(groups[PG_CALL + 1]); + pipeline_groups.push_back(groups[PG_CALL + 2]); + } + + check_result_optix_ret(optixPipelineCreate(context, + &pipeline_options, + &link_options, + pipeline_groups.data(), + pipeline_groups.size(), + nullptr, + 0, + &pipelines[PIP_SHADER_EVAL])); // Calculate continuation stack size based on the maximum of all ray generation stack sizes const unsigned int css = std::max(stack_size[PG_BAKE].cssRG, std::max(stack_size[PG_DISP].cssRG, stack_size[PG_BACK].cssRG)) + link_options.maxTraceDepth * trace_css; + const unsigned int dss = stack_size[PG_CALL + 0].dssDC + + std::max(stack_size[PG_CALL + 1].dssDC, + stack_size[PG_CALL + 2].dssDC); - check_result_optix_ret(optixPipelineSetStackSize( - pipelines[PIP_SHADER_EVAL], 0, 0, css, (pipeline_options.usesMotionBlur ? 3 : 2))); + check_result_optix_ret( + optixPipelineSetStackSize(pipelines[PIP_SHADER_EVAL], + 0, + requested_features.use_shader_raytrace ? dss : 0, + css, + motion_blur ? 3 : 2)); } // Clean up program group objects @@ -655,6 +703,11 @@ class OptiXDevice : public CUDADevice { while (task.acquire_tile(this, tile, task.tile_types)) { if (tile.task == RenderTile::PATH_TRACE) launch_render(task, tile, thread_index); + else if (tile.task == RenderTile::BAKE) { + // Perform baking using CUDA, since it is not currently implemented in OptiX + device_vector<WorkTile> work_tiles(this, "work_tiles", MEM_READ_ONLY); + CUDADevice::render(task, tile, work_tiles); + } else if (tile.task == RenderTile::DENOISE) launch_denoise(task, tile); task.release_tile(tile); @@ -734,6 +787,9 @@ class OptiXDevice : public CUDADevice { # else sbt_params.hitgroupRecordCount = 3; // PG_HITD, PG_HITS, PG_HITL # endif + sbt_params.callablesRecordBase = sbt_data.device_pointer + PG_CALL * sizeof(SbtRecord); + sbt_params.callablesRecordCount = 3; + sbt_params.callablesRecordStrideInBytes = sizeof(SbtRecord); // Launch the ray generation program check_result_optix(optixLaunch(pipelines[PIP_PATH_TRACE], @@ -1061,6 +1117,9 @@ class OptiXDevice : public CUDADevice { # else sbt_params.hitgroupRecordCount = 3; // PG_HITD, PG_HITS, PG_HITL # endif + sbt_params.callablesRecordBase = sbt_data.device_pointer + PG_CALL * sizeof(SbtRecord); + sbt_params.callablesRecordCount = 3; + sbt_params.callablesRecordStrideInBytes = sizeof(SbtRecord); check_result_optix(optixLaunch(pipelines[PIP_SHADER_EVAL], cuda_stream[thread_index], diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index c39c67afb5a..f6b4b963a7a 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -423,7 +423,7 @@ if(WITH_CYCLES_CUDA_BINARIES) set(cuda_kernel_src "/kernels/cuda/${name}.cu") - set(cuda_flags + set(cuda_flags ${flags} -D CCL_NAMESPACE_BEGIN= -D CCL_NAMESPACE_END= -D NVCC @@ -545,11 +545,11 @@ endif() # OptiX PTX modules if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES) - foreach(input ${SRC_OPTIX_KERNELS}) - get_filename_component(input_we ${input} NAME_WE) + macro(CYCLES_OPTIX_KERNEL_ADD name flags) + set(input "kernels/optix/kernel_optix.cu") + set(output "${CMAKE_CURRENT_BINARY_DIR}/${name}.ptx") - set(output "${CMAKE_CURRENT_BINARY_DIR}/${input_we}.ptx") - set(cuda_flags + set(cuda_flags ${flags} -I "${OPTIX_INCLUDE_DIR}" -I "${CMAKE_CURRENT_SOURCE_DIR}/.." -I "${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda" @@ -625,7 +625,10 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES) list(APPEND optix_ptx ${output}) delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${output}" ${CYCLES_INSTALL_PATH}/lib) - endforeach() + endmacro() + + CYCLES_OPTIX_KERNEL_ADD(kernel_optix "-D __NO_SHADER_RAYTRACE__") + CYCLES_OPTIX_KERNEL_ADD(kernel_optix_shader_raytrace "--keep-device-functions") add_custom_target(cycles_kernel_optix ALL DEPENDS ${optix_ptx}) cycles_set_solution_folder(cycles_kernel_optix) diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index ed8572467ea..917f35d37dc 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -281,13 +281,28 @@ ccl_device_inline int subsurface_scatter_disk(KernelGlobals *kg, return num_eval_hits; } -ccl_device_noinline void subsurface_scatter_multi_setup(KernelGlobals *kg, - LocalIntersection *ss_isect, - int hit, - ShaderData *sd, - ccl_addr_space PathState *state, - ClosureType type, - float roughness) +#if defined(__KERNEL_OPTIX__) && defined(__SHADER_RAYTRACE__) +ccl_device_inline void subsurface_scatter_multi_setup(KernelGlobals *kg, + LocalIntersection *ss_isect, + int hit, + ShaderData *sd, + ccl_addr_space PathState *state, + ClosureType type, + float roughness) +{ + optixDirectCall<void>(2, kg, ss_isect, hit, sd, state, type, roughness); +} +extern "C" __device__ void __direct_callable__subsurface_scatter_multi_setup( +#else +ccl_device_noinline void subsurface_scatter_multi_setup( +#endif + KernelGlobals *kg, + LocalIntersection *ss_isect, + int hit, + ShaderData *sd, + ccl_addr_space PathState *state, + ClosureType type, + float roughness) { #ifdef __SPLIT_KERNEL__ Ray ray_object = ss_isect->ray; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 8e2b0e46a66..6beabebb92f 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -139,8 +139,6 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_OPTIX__ # undef __BAKING__ # undef __BRANCHED_PATH__ -/* TODO(pmours): Cannot use optixTrace in non-inlined functions */ -# undef __SHADER_RAYTRACE__ #endif /* __KERNEL_OPTIX__ */ #ifdef __KERNEL_OPENCL__ diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index f5d10c0ca8a..fdf712293e7 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -274,11 +274,24 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, /* get the volume attenuation over line segment defined by ray, with the * assumption that there are no surfaces blocking light between the endpoints */ -ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg, - ShaderData *shadow_sd, - ccl_addr_space PathState *state, - Ray *ray, - float3 *throughput) +# if defined(__KERNEL_OPTIX__) && defined(__SHADER_RAYTRACE__) +ccl_device_inline void kernel_volume_shadow(KernelGlobals *kg, + ShaderData *shadow_sd, + ccl_addr_space PathState *state, + Ray *ray, + float3 *throughput) +{ + optixDirectCall<void>(1, kg, shadow_sd, state, ray, throughput); +} +extern "C" __device__ void __direct_callable__kernel_volume_shadow( +# else +ccl_device_noinline void kernel_volume_shadow( +# endif + KernelGlobals *kg, + ShaderData *shadow_sd, + ccl_addr_space PathState *state, + Ray *ray, + float3 *throughput) { shader_setup_from_volume(kg, shadow_sd, ray); diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h index 44c658d4cab..59b96c86c50 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h @@ -18,6 +18,7 @@ #define __KERNEL_CPU_IMAGE_H__ #ifdef WITH_NANOVDB +# define NANOVDB_USE_INTRINSICS # include <nanovdb/NanoVDB.h> # include <nanovdb/util/SampleFromVoxels.h> #endif diff --git a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h index 001bc652810..82ad9225fc3 100644 --- a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h +++ b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h @@ -15,6 +15,8 @@ */ #ifdef WITH_NANOVDB +# define NDEBUG /* Disable "assert" in device code */ +# define NANOVDB_USE_INTRINSICS # include "nanovdb/NanoVDB.h" # include "nanovdb/util/SampleFromVoxels.h" #endif diff --git a/intern/cycles/kernel/kernels/optix/kernel_optix.cu b/intern/cycles/kernel/kernels/optix/kernel_optix.cu index fd9065098dd..8ccd2555091 100644 --- a/intern/cycles/kernel/kernels/optix/kernel_optix.cu +++ b/intern/cycles/kernel/kernels/optix/kernel_optix.cu @@ -118,12 +118,18 @@ extern "C" __global__ void __anyhit__kernel_optix_local_hit() return optixIgnoreIntersection(); } + const uint max_hits = optixGetPayload_5(); + if (max_hits == 0) { + // Special case for when no hit information is requested, just report that something was hit + optixSetPayload_5(true); + return optixTerminateRay(); + } + int hit = 0; uint *const lcg_state = get_payload_ptr_0<uint>(); LocalIntersection *const local_isect = get_payload_ptr_2<LocalIntersection>(); if (lcg_state) { - const uint max_hits = optixGetPayload_5(); for (int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) { if (optixGetRayTmax() == local_isect->hits[i].t) { return optixIgnoreIntersection(); diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 6c849f5b2fc..000da1fa615 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -217,12 +217,26 @@ CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN /* Main Interpreter Loop */ -ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, - ShaderData *sd, - ccl_addr_space PathState *state, - ccl_global float *buffer, - ShaderType type, - int path_flag) +#if defined(__KERNEL_OPTIX__) && defined(__SHADER_RAYTRACE__) +ccl_device_inline void svm_eval_nodes(KernelGlobals *kg, + ShaderData *sd, + ccl_addr_space PathState *state, + ccl_global float *buffer, + ShaderType type, + int path_flag) +{ + optixDirectCall<void>(0, kg, sd, state, buffer, type, path_flag); +} +extern "C" __device__ void __direct_callable__svm_eval_nodes( +#else +ccl_device_noinline void svm_eval_nodes( +#endif + KernelGlobals *kg, + ShaderData *sd, + ccl_addr_space PathState *state, + ccl_global float *buffer, + ShaderType type, + int path_flag) { float stack[SVM_STACK_SIZE]; int offset = sd->shader & SHADER_MASK; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 11c8e240afd..43e664a686f 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -277,6 +277,20 @@ void Mesh::reserve_subd_creases(size_t num_creases) subd_creases_weight.reserve(num_creases); } +void Mesh::clear_non_sockets() +{ + Geometry::clear(true); + + num_subd_verts = 0; + num_subd_faces = 0; + + vert_to_stitching_key_map.clear(); + vert_stitching_map.clear(); + + delete patch_table; + patch_table = NULL; +} + void Mesh::clear(bool preserve_shaders, bool preserve_voxel_data) { Geometry::clear(preserve_shaders); @@ -297,22 +311,15 @@ void Mesh::clear(bool preserve_shaders, bool preserve_voxel_data) subd_ptex_offset.clear(); subd_face_corners.clear(); - num_subd_verts = 0; - num_subd_faces = 0; - subd_creases_edge.clear(); subd_creases_weight.clear(); subd_attributes.clear(); attributes.clear(preserve_voxel_data); - vert_to_stitching_key_map.clear(); - vert_stitching_map.clear(); - subdivision_type = SubdivisionType::SUBDIVISION_NONE; - delete patch_table; - patch_table = NULL; + clear_non_sockets(); } void Mesh::clear(bool preserve_shaders) @@ -662,7 +669,7 @@ void Mesh::add_undisplaced() float3 *data = attr->data_float3(); /* copy verts */ - size_t size = attr->buffer_size(this, attrs.prim); + size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY); /* Center points for ngons aren't stored in Mesh::verts but are included in size since they will * be calculated later, we subtract them from size here so we don't have an overflow while diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 6630dcd8a35..e2746e560da 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -205,6 +205,7 @@ class Mesh : public Geometry { void resize_subd_faces(int numfaces, int num_ngons, int numcorners); void reserve_subd_faces(int numfaces, int num_ngons, int numcorners); void reserve_subd_creases(size_t num_creases); + void clear_non_sockets(); void clear(bool preserve_shaders = false) override; void add_vertex(float3 P); void add_vertex_slow(float3 P); diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 4a2a12932fe..e8611839aea 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -142,7 +142,11 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL) list(APPEND INC_SYS ${SDL_INCLUDE_DIR} ) - if(NOT WITH_SDL_DYNLOAD) + if(WITH_SDL_DYNLOAD) + list(APPEND LIB + extern_sdlew + ) + else() list(APPEND LIB ${SDL_LIBRARY} ) diff --git a/release/datafiles/blender_logo.png b/release/datafiles/blender_logo.png Binary files differnew file mode 100644 index 00000000000..17ffef7df5d --- /dev/null +++ b/release/datafiles/blender_logo.png diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject ae7e6c215c9fc715cdedbc1c1e33e946fc90b49 +Subproject 9e40c01dffd3f720b23b906d20df8e999d34a4a diff --git a/release/license/ISC.txt b/release/license/ISC.txt deleted file mode 100644 index 5923726e458..00000000000 --- a/release/license/ISC.txt +++ /dev/null @@ -1,14 +0,0 @@ -ISC License (ISC) ------------------ - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/release/lts/README.md b/release/lts/README.md new file mode 100644 index 00000000000..8f7b6f0b87a --- /dev/null +++ b/release/lts/README.md @@ -0,0 +1,41 @@ +This folder contains several scripts to smoothen the Blender LTS releases. + +create_download_urls.py +======================= + +This python script is used to generate the download urls which we can +copy-paste directly into the CMS of www.blender.org. + +Usage: create_download_urls.py --version 2.83.7 + +Arguments: + --version VERSION Version string in the form of {major}.{minor}.{build} + (eg 2.83.7) + +The resulting html will be printed to the console. + +create_release_notes.py +======================= + +This python script is used to generate the release notes which we can +copy-paste directly into the CMS of www.blender.org and stores. + +Usage: ./create_release_notes.py --task=T77348 --version=2.83.7 + +Arguments: + --version VERSION Version string in the form of {major}.{minor}.{build} + (e.g. 2.83.7) + --task TASK Phabricator ticket that is contains the release notes + information (e.g. T77348) + --format FORMAT Format the result in `text`, `steam`, `wiki` or `html` + +Requirements +============ + +* Python 3.8 or later +* Python phabricator client version 0.7.0 + https://pypi.org/project/phabricator/ + +For convenience the python modules can be installed using pip + + pip3 install -r ./requirements.txt
\ No newline at end of file diff --git a/release/lts/create_download_urls.py b/release/lts/create_download_urls.py new file mode 100755 index 00000000000..0d0b2554d2a --- /dev/null +++ b/release/lts/create_download_urls.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 + +import argparse +import datetime + + +DESCRIPTION = ("This python script is used to generate the download urls " + "which we can copy-paste directly into the CMS of " + "www.blender.org") +USAGE = "create_download_urls --version=2.83.7" +# Used date format: "September 30, 2020" +DATE_FORMAT = "%B %d, %Y" + + +class Version: + """ + Version class that extracts the major, minor and build from + a version string + """ + def __init__(self, version: str): + self.version = version + v = version.split(".") + self.major = v[0] + self.minor = v[1] + self.build = v[2] + + def __str__(self) -> str: + return self.version + + +def get_download_file_names(version: Version): + yield f"blender-{version}-linux64.tar.xz" + yield f"blender-{version}-macOS.dmg" + yield f"blender-{version}-windows64.msi" + yield f"blender-{version}-windows64.zip" + + +def get_download_url(version: Version, file_name: str) -> str: + """ + Get the download url for the given version and file_name + """ + return (f"https://www.blender.org/download/Blender{version.major}" + f".{version.minor}/{file_name}") + + +def generate_html(version: Version) -> str: + """ + Generate download urls and format them into an HTML string + """ + today = datetime.date.today() + lines = [] + lines.append(f"Released on {today.strftime(DATE_FORMAT)}.") + lines.append("") + lines.append("<ul>") + for file_name in get_download_file_names(version): + download_url = get_download_url(version, file_name) + lines.append(f" <li><a href=\"{download_url}\">{file_name}</a></li>") + lines.append("</ul>") + + return "\n".join(lines) + + +def print_download_urls(version: Version): + """ + Generate the download urls and print them to the console. + """ + print(generate_html(version)) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=DESCRIPTION, usage=USAGE) + parser.add_argument("--version", + required=True, + help=("Version string in the form of {major}.{minor}." + "{build} (eg 2.83.7)")) + args = parser.parse_args() + + print_download_urls(version=Version(args.version)) diff --git a/release/lts/create_release_notes.py b/release/lts/create_release_notes.py new file mode 100755 index 00000000000..2a396dca6b0 --- /dev/null +++ b/release/lts/create_release_notes.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 + +import argparse +import phabricator + + +DESCRIPTION = ("This python script is used to generate the release notes " + "which we can copy-paste directly into the CMS of " + "www.blender.org and stores.") +USAGE = "./create_release_notes.py --task=T77348 --version=2.83.7" + + +class ReleaseLogLine: + """ + Class containing the information of a single line of the release log + + Instance attributes: + + * line: (str) the original line used to create this log line + * task_id: (int or None) the extracted task id associated with this log + line. Can be None if the log line isn't associated with a task. + * commit_id: (str or None) the extracted commit id associated with this log + line. Only filled when no `task_id` could be found. + * ref: (str) `task_id` or `commit_id` of this line, including `T` for tasks + or `D` for diffs. + * title: (str) title of this log line. When constructed this attribute is + an empty string. The called needs to retrieve the title from the + backend. + * url: (str) url of the ticket task or commit. + """ + def __init__(self, line: str): + self.line=line + items = line.split("|") + self.task_id = None + self.commit_id = None + try: + task_id = int(items[1].strip()[1:]) + self.task_id = task_id + self.ref = f"T{self.task_id}" + except ValueError: + # no task + commit_string = items[3].strip() + commits = commit_string.split(",") + commit_id = commits[0] + commit_id = commit_id.replace("{", "").replace("}", "") + if not commit_id.startswith("rB"): + commit_id = f"rB{commit_id}" + self.commit_id = commit_id + + self.ref = f"{self.commit_id}" + + self.title = "" + self.url = f"https://developer.blender.org/{self.ref}" + + def __format_as_html(self)-> str: + return f" <li>{self.title} [<a href=\"{self.url}\">{self.ref}</a>]</li>" + + def __format_as_text(self) ->str: + return f"* {self.title} [{self.ref}]" + + def __format_as_steam(self) -> str: + return f"* {self.title} ([url={self.url}]{self.ref}[/url])" + + def __format_as_wiki(self) -> str: + if self.task_id: + return f"* {self.title} [{{{{BugReport|{self.task_id}}}}}]" + else: + return f"* {self.title} [{{{{GitCommit|{self.commit_id[2:]}}}}}]" + + def format(self, format: str) -> str: + """ + Format this line + + :attr format: the desired format. Possible values are 'text', 'steam' or 'html' + :type string: + """ + if format == 'html': + return self.__format_as_html() + elif format == 'steam': + return self.__format_as_steam() + elif format == 'wiki': + return self.__format_as_wiki() + else: + return self.__format_as_text() + + +def format_title(title: str) -> str: + title = title.strip() + if not title.endswith("."): + title = title + "." + return title + + +def extract_release_notes(version: str, task_id: int): + """ + Extract all release notes logs + + # Process + + 1. Retrieval of description of the gived `task_id`. + 2. Find rows for the given `version` and convert to `ReleaseLogLine`. + 3. based on the associated task or commit retrieves the title of the log + line. + """ + phab = phabricator.Phabricator() + phab.update_interfaces() + task = phab.maniphest.info(task_id=task_id) + description = task["description"] + lines = description.split("\n") + start_index = lines.index(f"## Blender {version} ##") + lines = lines[start_index+1:] + for line in lines: + if not line.strip(): + continue + if line.startswith("| **Report**"): + continue + if line.startswith("## Blender"): + break + + log_line = ReleaseLogLine(line) + if log_line.task_id: + issue_task = phab.maniphest.info(task_id=log_line.task_id) + log_line.title = format_title(issue_task.title) + yield log_line + elif log_line.commit_id: + commits = phab.diffusion.commit.search(constraints={"identifiers":[log_line.commit_id]}) + commit = commits.data[0] + commit_message = commit['fields']['message'] + commit_title = commit_message.split("\n")[0] + log_line.title = format_title(commit_title) + yield log_line + + +def print_release_notes(version: str, format: str, task_id: int): + """ + Generate and print the release notes to the console. + """ + if format == 'html': + print("<ul>") + if format == 'steam': + print("[ul]") + for log_item in extract_release_notes(version=version, task_id=task_id): + print(log_item.format(format=format)) + if format == 'html': + print("</ul>") + if format == 'steam': + print("[/ul]") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=DESCRIPTION, usage=USAGE) + parser.add_argument( + "--version", + required=True, + help="Version string in the form of {major}.{minor}.{build} (e.g. 2.83.7)") + parser.add_argument( + "--task", + required=True, + help="Phabricator ticket that is contains the release notes information (e.g. T77348)") + parser.add_argument( + "--format", + help="Format the result in `text`, `steam`, `wiki` or `html`", + default="text") + args = parser.parse_args() + + print_release_notes(version=args.version, format=args.format, task_id=int(args.task[1:])) diff --git a/release/lts/requirements.txt b/release/lts/requirements.txt new file mode 100644 index 00000000000..dc91ba85b01 --- /dev/null +++ b/release/lts/requirements.txt @@ -0,0 +1 @@ +phabricator==0.7.0
\ No newline at end of file diff --git a/release/scripts/addons b/release/scripts/addons -Subproject ca74197440127e56c9f6f2a277c30957f34fd07 +Subproject 1191a172ac389e3d068a8ef7d16f36457e67e3b diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index e304ef5ea17..cfa4fcac17f 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -30,7 +30,11 @@ import os import sys import types -import bpy +try: + import bpy +except ModuleNotFoundError: + print("Could not import bpy, some features are not available when not run from Blender.") + bpy = None ############################################################################### # MISC @@ -98,8 +102,10 @@ LANGUAGES = ( (47, "Slovak (Slovenčina)", "sk_SK"), ) -# Default context, in py! -DEFAULT_CONTEXT = bpy.app.translations.contexts.default +# Default context, in py (keep in sync with `BLT_translation.h`)! +if bpy is not None: + assert(bpy.app.translations.contexts.default == "*") +DEFAULT_CONTEXT = "*" # Name of language file used by Blender to generate translations' menu. LANGUAGES_FILE = "languages" diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py index 4cb25816a34..40b76b617b3 100644 --- a/release/scripts/modules/bl_i18n_utils/utils.py +++ b/release/scripts/modules/bl_i18n_utils/utils.py @@ -35,13 +35,8 @@ from bl_i18n_utils import ( utils_rtl, ) -import bpy - ##### Misc Utils ##### -from bpy.app.translations import locale_explode - - _valid_po_path_re = re.compile(r"^\S+:[0-9]+$") @@ -79,6 +74,28 @@ def get_best_similar(data): return key, tmp +_locale_explode_re = re.compile(r"^([a-z]{2,})(?:_([A-Z]{2,}))?(?:@([a-z]{2,}))?$") + + +def locale_explode(locale): + """Copies behavior of `BLT_lang_locale_explode`, keep them in sync.""" + ret = (None, None, None, None, None) + m = _locale_explode_re.match(locale) + if m: + lang, country, variant = m.groups() + return (lang, country, variant, + "%s_%s" % (lang, country) if country else None, + "%s@%s" % (lang, variant) if variant else None) + + try: + import bpy.app.translations as bpy_translations + assert(ret == bpy_translations.locale_explode(locale)) + except ModuleNotFoundError: + pass + + return ret + + def locale_match(loc1, loc2): """ Return: @@ -164,6 +181,36 @@ def get_po_files_from_dir(root_dir, langs=set()): yield uid, po_file +def list_po_dir(root_path, settings): + """ + Generator. List given directory (expecting one sub-directory per languages) + and return all files matching languages listed in settings. + + Yield tuples (can_use, uid, num_id, name, isocode, po_path) + + Note that po_path may not actually exists. + """ + isocodes = ((e, os.path.join(root_path, e, e + ".po")) for e in os.listdir(root_path)) + isocodes = dict(e for e in isocodes if os.path.isfile(e[1])) + for num_id, name, uid in settings.LANGUAGES[2:]: # Skip "default" and "en" languages! + best_po = find_best_isocode_matches(uid, isocodes) + #print(uid, "->", best_po) + if best_po: + isocode = best_po[0] + yield (True, uid, num_id, name, isocode, isocodes[isocode]) + else: + yielded = False + language, _1, _2, language_country, language_variant = locale_explode(uid) + for isocode in (language, language_variant, language_country, uid): + p = os.path.join(root_path, isocode, isocode + ".po") + if not os.path.exists(p): + yield (True, uid, num_id, name, isocode, p) + yielded = True + break + if not yielded: + yield (False, uid, num_id, name, None, None) + + def enable_addons(addons=None, support=None, disable=False, check_only=False): """ Enable (or disable) addons based either on a set of names, or a set of 'support' types. @@ -172,6 +219,12 @@ def enable_addons(addons=None, support=None, disable=False, check_only=False): """ import addon_utils + try: + import bpy + except ModuleNotFoundError: + print("Could not import bpy, enable_addons must be run from whithin Blender.") + return + if addons is None: addons = {} if support is None: @@ -725,6 +778,13 @@ class I18nMessages: rna_ctxt: the labels' i18n context. rna_struct_name, rna_prop_name, rna_enum_name: should be self-explanatory! """ + try: + import bpy + except ModuleNotFoundError: + print("Could not import bpy, find_best_messages_matches must be run from whithin Blender.") + return + + # Build helper mappings. # Note it's user responsibility to know when to invalidate (and hence force rebuild) this cache! if self._reverse_cache is None: @@ -1275,7 +1335,7 @@ class I18n: msgs.print_stats(prefix=msgs_prefix) print(prefix) - nbr_contexts = len(self.contexts - {bpy.app.translations.contexts.default}) + nbr_contexts = len(self.contexts - {self.settings.DEFAULT_CONTEXT}) if nbr_contexts != 1: if nbr_contexts == 0: nbr_contexts = "No" @@ -1293,7 +1353,7 @@ class I18n: " The org msgids are currently made of {} signs.\n".format(self.nbr_signs), " All processed translations are currently made of {} signs.\n".format(self.nbr_trans_signs), " {} specific context{} present:\n".format(self.nbr_contexts, _ctx_txt)) + - tuple(" " + c + "\n" for c in self.contexts - {bpy.app.translations.contexts.default}) + + tuple(" " + c + "\n" for c in self.contexts - {self.settings.DEFAULT_CONTEXT}) + ("\n",) ) print(prefix.join(lines)) diff --git a/release/scripts/modules/bl_i18n_utils/utils_cli.py b/release/scripts/modules/bl_i18n_utils/utils_cli.py new file mode 100644 index 00000000000..d38911c122d --- /dev/null +++ b/release/scripts/modules/bl_i18n_utils/utils_cli.py @@ -0,0 +1,145 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ***** END GPL LICENSE BLOCK ***** + +# <pep8 compliant> + +# Some useful operations from utils' I18nMessages class exposed as a CLI. + +import os + +if __package__ is None: + import settings as settings_i18n + import utils as utils_i18n + import utils_languages_menu +else: + from . import settings as settings_i18n + from . import utils as utils_i18n + from . import utils_languages_menu + + +def update_po(args, settings): + pot = utils_i18n.I18nMessages(uid=None, kind='PO', src=args.template, settings=settings) + if os.path.isfile(args.dst): + uid = os.path.splitext(os.path.basename(args.dst))[0] + po = utils_i18n.I18nMessages(uid=uid, kind='PO', src=args.dst, settings=settings) + po.update(pot) + else: + po = pot + po.write(kind="PO", dest=args.dst) + + +def cleanup_po(args, settings): + uid = os.path.splitext(os.path.basename(args.src))[0] + if not args.dst: + args.dst = args.src + po = utils_i18n.I18nMessages(uid=uid, kind='PO', src=args.src, settings=settings) + po.check(fix=True) + po.clean_commented() + po.write(kind="PO", dest=args.dst) + + +def strip_po(args, settings): + uid = os.path.splitext(os.path.basename(args.src))[0] + if not args.dst: + args.dst = args.src + po = utils_i18n.I18nMessages(uid=uid, kind='PO', src=args.src, settings=settings) + po.clean_commented() + po.write(kind="PO_COMPACT", dest=args.dst) + + +def rtl_process_po(args, settings): + uid = os.path.splitext(os.path.basename(args.src))[0] + if not args.dst: + args.dst = args.src + po = utils_i18n.I18nMessages(uid=uid, kind='PO', src=args.src, settings=settings) + po.rtl_process() + po.write(kind="PO", dest=args.dst) + + +def language_menu(args, settings): + # 'DEFAULT' and en_US are always valid, fully-translated "languages"! + stats = {"DEFAULT": 1.0, "en_US": 1.0} + + po_to_uid = {os.path.basename(po_path_branch): uid + for can_use, uid, _num_id, _name, _isocode, po_path_branch + in utils_i18n.list_po_dir(settings.BRANCHES_DIR, settings) + if can_use} + for po_dir in os.listdir(settings.BRANCHES_DIR): + po_dir = os.path.join(settings.BRANCHES_DIR, po_dir) + if not os.path.isdir(po_dir): + continue + for po_path in os.listdir(po_dir): + uid = po_to_uid.get(po_path, None) + #print("Checking %s, found uid %s" % (po_path, uid)) + po_path = os.path.join(settings.TRUNK_PO_DIR, po_path) + if uid is not None: + po = utils_i18n.I18nMessages(uid=uid, kind='PO', src=po_path, settings=settings) + stats[uid] = po.nbr_trans_msgs / po.nbr_msgs if po.nbr_msgs > 0 else 0 + utils_languages_menu.gen_menu_file(stats, settings) + + +def main(): + import sys + import argparse + + parser = argparse.ArgumentParser(description="Tool to perform common actions over PO/MO files.") + parser.add_argument('-s', '--settings', default=None, + help="Override (some) default settings. Either a JSon file name, or a JSon string.") + sub_parsers = parser.add_subparsers() + + sub_parser = sub_parsers.add_parser('update_po', help="Update a PO file from a given POT template file") + sub_parser.add_argument('--template', metavar='template.pot', required=True, + help="The source pot file to use as template for the update.") + sub_parser.add_argument('--dst', metavar='dst.po', required=True, help="The destination po to update.") + sub_parser.set_defaults(func=update_po) + + sub_parser = sub_parsers.add_parser('cleanup_po', + help="Cleanup a PO file (check for and fix some common errors, remove commented messages).") + sub_parser.add_argument('--src', metavar='src.po', required=True, help="The source po file to clean up.") + sub_parser.add_argument('--dst', metavar='dst.po', help="The destination po to write to.") + sub_parser.set_defaults(func=cleanup_po) + + sub_parser = sub_parsers.add_parser('strip_po', + help="Reduce all non-essential data from given PO file (reduce its size).") + sub_parser.add_argument('--src', metavar='src.po', required=True, help="The source po file to strip.") + sub_parser.add_argument('--dst', metavar='dst.po', help="The destination po to write to.") + sub_parser.set_defaults(func=strip_po) + + sub_parser = sub_parsers.add_parser('rtl_process_po', + help="Pre-process PO files for RTL languages.") + sub_parser.add_argument('--src', metavar='src.po', required=True, help="The source po file to process.") + sub_parser.add_argument('--dst', metavar='dst.po', help="The destination po to write to.") + sub_parser.set_defaults(func=rtl_process_po) + + sub_parser = sub_parsers.add_parser('language_menu', + help="Generate the text file used by Blender to create its language menu.") + sub_parser.set_defaults(func=language_menu) + + args = parser.parse_args(sys.argv[1:]) + + settings = settings_i18n.I18nSettings() + settings.load(args.settings) + + if getattr(args, 'template', None) is not None: + settings.FILE_NAME_POT = args.template + + args.func(args=args, settings=settings) + +if __name__ == "__main__": + print("\n\n *** Running {} *** \n".format(__file__)) + main() diff --git a/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py index 7c98faebe9d..63981310839 100755 --- a/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py +++ b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py @@ -40,7 +40,7 @@ def gen_menu_file(stats, settings): # Generate languages file used by Blender's i18n system. # First, match all entries in LANGUAGES to a lang in stats, if possible! tmp = [] - for uid_num, label, uid, in settings.LANGUAGES: + for uid_num, label, uid in settings.LANGUAGES: if uid in stats: if uid in settings.IMPORT_LANGUAGES_SKIP: tmp.append((stats[uid], uid_num, label, uid, FORBIDDEN)) diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index 05985cac868..b1f72408a45 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -80,7 +80,8 @@ class SpellChecker: "autoexecution", "autogenerated", "autolock", - "automasking", + "automask", "automasking", + "automerge", "autoname", "autopack", "autosave", @@ -143,6 +144,7 @@ class SpellChecker: "midlevel", "midground", "mixdown", + "monospaced", "multi", "multifractal", "multiframe", @@ -464,6 +466,7 @@ class SpellChecker: "eigenvectors", "emissive", "equirectangular", + "filmlike", "fisheye", "framerate", "gimbal", @@ -642,6 +645,7 @@ class SpellChecker: "aa", "msaa", "ao", "api", + "apic", # Affine Particle-In-Cell "asc", "cdl", "ascii", "atrac", diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index 3ff259e0e3e..897010e80cf 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -26,6 +26,7 @@ not associated with blenders internal data. __all__ = ( "blend_paths", "escape_identifier", + "unescape_identifier", "keyconfig_init", "keyconfig_set", "load_scripts", @@ -60,6 +61,7 @@ from _bpy import ( _utils_units as units, blend_paths, escape_identifier, + unescape_identifier, register_class, resource_path, script_paths as _bpy_script_paths, diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py index 8fdd66dff9f..e3158118146 100644 --- a/release/scripts/modules/rna_prop_ui.py +++ b/release/scripts/modules/rna_prop_ui.py @@ -49,7 +49,7 @@ def rna_idprop_ui_del(item): def rna_idprop_quote_path(prop): - return "[\"%s\"]" % prop.replace("\"", "\\\"") + return "[\"%s\"]" % bpy.utils.escape_identifier(prop) def rna_idprop_ui_prop_update(item, prop): diff --git a/release/scripts/presets/keyconfig/blender.py b/release/scripts/presets/keyconfig/blender.py index d24735ba8b7..113e99fed42 100644 --- a/release/scripts/presets/keyconfig/blender.py +++ b/release/scripts/presets/keyconfig/blender.py @@ -168,6 +168,7 @@ class Prefs(bpy.types.KeyConfigPreferences): def draw(self, layout): layout.use_property_split = True + layout.use_property_decorate = False is_select_left = (self.select_mouse == 'LEFT') diff --git a/release/scripts/presets/keyconfig/blender_27x.py b/release/scripts/presets/keyconfig/blender_27x.py index a02ac895efb..efb013b9216 100644 --- a/release/scripts/presets/keyconfig/blender_27x.py +++ b/release/scripts/presets/keyconfig/blender_27x.py @@ -33,11 +33,11 @@ class Prefs(bpy.types.KeyConfigPreferences): ) def draw(self, layout): - split = layout.split() - col = split.column() - col.label(text="Select With:") - col.row().prop(self, "select_mouse", expand=True) - split.column() + layout.use_property_split = True + layout.use_property_decorate = False + + col = layout.column() + col.row().prop(self, "select_mouse", text="Select with Mouse Button", expand=True) blender_default = bpy.utils.execfile(os.path.join(DIRNAME, "keymap_data", "blender_default.py")) diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index d1a595f04c8..54731c7139f 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -447,6 +447,13 @@ def km_property_editor(params): {"properties": [("direction", 'PREV'), ], },), ("screen.space_context_cycle", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True}, {"properties": [("direction", 'NEXT'), ], },), + ("buttons.start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None), + ("buttons.clear_filter", {"type": 'ESC', "value": 'PRESS'}, None), + # Modifier panels + ("object.modifier_set_active", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), + ("object.modifier_remove", {"type": 'BACK_SPACE', "value": 'PRESS'}, {"properties": [("report", True)]}), + ("object.modifier_remove", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}), + ("object.modifier_copy", {"type": 'D', "value": 'PRESS', "ctrl": True}, None), ]) return keymap diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py index ab79ebe3957..bb414b5ff89 100644 --- a/release/scripts/startup/bl_operators/anim.py +++ b/release/scripts/startup/bl_operators/anim.py @@ -429,9 +429,22 @@ class UpdateAnimatedTransformConstraint(Operator): return {'FINISHED'} +class ANIM_OT_show_group_colors_deprecated(Operator): + """This option moved to Preferences > Animation""" + + bl_idname = "anim.show_group_colors_deprecated" + bl_label = "Show Group Colors" + bl_options = {'REGISTER'} + + @classmethod + def poll(cls, context) -> bool: + return False + + classes = ( ANIM_OT_keying_set_export, NLA_OT_bake, ClearUselessActions, UpdateAnimatedTransformConstraint, + ANIM_OT_show_group_colors_deprecated, ) diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index a3c54a7b069..51a9695e44a 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -414,8 +414,8 @@ class CLIP_OT_delete_proxy(Operator): class CLIP_OT_set_viewport_background(Operator): - """Set current movie clip as a camera background in 3D view-port """ \ - """(works only when a 3D view-port is visible)""" + """Set current movie clip as a camera background in 3D Viewport """ \ + """(works only when a 3D Viewport is visible)""" bl_idname = "clip.set_viewport_background" bl_label = "Set as Background" diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py index 8d543daeac7..f2cd0ad7478 100644 --- a/release/scripts/startup/bl_operators/image.py +++ b/release/scripts/startup/bl_operators/image.py @@ -116,7 +116,7 @@ class EditExternally(Operator): class ProjectEdit(Operator): - """Edit a snapshot of the view-port in an external image editor""" + """Edit a snapshot of the 3D Viewport in an external image editor""" bl_idname = "image.project_edit" bl_label = "Project Edit" bl_options = {'REGISTER'} diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index bd1ae2ca8e1..bd1c99fdeb3 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -31,6 +31,7 @@ from bpy.props import ( IntProperty, StringProperty, ) +from bpy.app.translations import pgettext_iface as iface_ # FIXME, we need a way to detect key repeat events. # unfortunately checking event previous values isn't reliable. @@ -1146,10 +1147,11 @@ rna_default = StringProperty( maxlen=1024, ) -rna_property = StringProperty( +rna_custom_property = StringProperty( name="Property Name", description="Property name edit", - maxlen=1024, + # Match `MAX_IDPROP_NAME - 1` in Blender's source. + maxlen=63, ) rna_min = FloatProperty( @@ -1195,7 +1197,7 @@ class WM_OT_properties_edit(Operator): bl_options = {'REGISTER', 'INTERNAL'} data_path: rna_path - property: rna_property + property: rna_custom_property value: rna_value default: rna_default min: rna_min @@ -1264,6 +1266,7 @@ class WM_OT_properties_edit(Operator): data_path = self.data_path prop = self.property + prop_escape = bpy.utils.escape_identifier(prop) prop_old = getattr(self, "_last_prop", [None])[0] @@ -1288,7 +1291,7 @@ class WM_OT_properties_edit(Operator): # Reassign item[prop] = value_eval - item.property_overridable_library_set('["%s"]' % prop, self.is_overridable_library) + item.property_overridable_library_set('["%s"]' % prop_escape, self.is_overridable_library) rna_idprop_ui_prop_update(item, prop) self._last_prop[:] = [prop] @@ -1321,7 +1324,7 @@ class WM_OT_properties_edit(Operator): # If we have changed the type of the property, update its potential anim curves! if prop_type_old != prop_type_new: - data_path = '["%s"]' % bpy.utils.escape_identifier(prop) + data_path = '["%s"]' % prop_escape done = set() def _update(fcurves): @@ -1363,13 +1366,16 @@ class WM_OT_properties_edit(Operator): rna_idprop_value_item_type ) + prop = self.property + prop_escape = bpy.utils.escape_identifier(prop) + data_path = self.data_path if not data_path: self.report({'ERROR'}, "Data path not set") return {'CANCELLED'} - self._last_prop = [self.property] + self._last_prop = [prop] item = eval("context.%s" % data_path) @@ -1378,7 +1384,7 @@ class WM_OT_properties_edit(Operator): return {'CANCELLED'} # retrieve overridable static - is_overridable = item.is_property_overridable_library('["%s"]' % self.property) + is_overridable = item.is_property_overridable_library('["%s"]' % prop_escape) self.is_overridable_library = bool(is_overridable) # default default value @@ -1389,7 +1395,7 @@ class WM_OT_properties_edit(Operator): self.default = "" # setup defaults - prop_ui = rna_idprop_ui_prop_get(item, self.property, False) # don't create + prop_ui = rna_idprop_ui_prop_get(item, prop, False) # don't create if prop_ui: self.min = prop_ui.get("min", -1000000000) self.max = prop_ui.get("max", 1000000000) @@ -1547,7 +1553,7 @@ class WM_OT_properties_remove(Operator): bl_options = {'UNDO', 'INTERNAL'} data_path: rna_path - property: rna_property + property: rna_custom_property def execute(self, context): from rna_prop_ui import ( @@ -2642,26 +2648,28 @@ class WM_MT_splash_about(Menu): layout = self.layout layout.operator_context = 'EXEC_DEFAULT' - layout.label(text="Blender is free software") - layout.label(text="Licensed under the GNU General Public License") - layout.separator() - layout.separator() - - split = layout.split() - split.emboss = 'PULLDOWN_MENU' - split.scale_y = 1.3 - - col1 = split.column() - - col1.operator("wm.url_open_preset", text="Release Notes", icon='URL').type = 'RELEASE_NOTES' - col1.operator("wm.url_open_preset", text="Credits", icon='URL').type = 'CREDITS' - col1.operator("wm.url_open", text="License", icon='URL').url = "https://www.blender.org/about/license/" - - col2 = split.column() - - col2.operator("wm.url_open_preset", text="Blender Website", icon='URL').type = 'BLENDER' - col2.operator("wm.url_open", text="Blender Store", icon='URL').url = "https://store.blender.org" - col2.operator("wm.url_open_preset", text="Development Fund", icon='FUND').type = 'FUND' + split = layout.split(factor=0.65) + + col = split.column(align=True) + col.scale_y = 0.8 + col.label(text=bpy.app.version_string, translate=False) + col.separator(factor=2.5) + col.label(text=iface_("Date: %s %s") % (bpy.app.build_commit_date.decode('utf-8', 'replace'), + bpy.app.build_commit_time.decode('utf-8', 'replace')), translate=False) + col.label(text=iface_("Hash: %s") % bpy.app.build_hash.decode('ascii'), translate=False) + col.label(text=iface_("Branch: %s") % bpy.app.build_branch.decode('utf-8', 'replace'), translate=False) + col.separator(factor=2.0) + col.label(text="Blender is free software") + col.label(text="Licensed under the GNU General Public License") + + col = split.column(align=True) + col.emboss = 'PULLDOWN_MENU' + col.operator("wm.url_open_preset", text="Release Notes", icon='URL').type = 'RELEASE_NOTES' + col.operator("wm.url_open_preset", text="Credits", icon='URL').type = 'CREDITS' + col.operator("wm.url_open", text="License", icon='URL').url = "https://www.blender.org/about/license/" + col.operator("wm.url_open_preset", text="Blender Website", icon='URL').type = 'BLENDER' + col.operator("wm.url_open", text="Blender Store", icon='URL').url = "https://store.blender.org" + col.operator("wm.url_open_preset", text="Development Fund", icon='FUND').type = 'FUND' class WM_OT_drop_blend_file(Operator): diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index f46e9f9727f..71a7b056d07 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -85,14 +85,23 @@ class ConstraintButtonsPanel(Panel): row.operator("constraint.disable_keep_transform", text="", icon='CANCEL') @staticmethod - def space_template(layout, con, target=True, owner=True): + def space_template(layout, con, target=True, owner=True, separator=True): if target or owner: - layout.separator() + if separator: + layout.separator() if target: layout.prop(con, "target_space", text="Target") if owner: layout.prop(con, "owner_space", text="Owner") + if con.target_space == 'CUSTOM' or con.owner_space == 'CUSTOM': + col = layout.column() + col.prop(con, "space_object") + if con.space_object and con.space_object.type == 'ARMATURE': + col.prop_search(con, "space_subtarget", con.space_object.data, "bones", text="Bone") + elif con.space_object and con.space_object.type in {'MESH', 'LATTICE'}: + col.prop_search(con, "space_subtarget", con.space_object, "vertex_groups", text="Vertex Group") + @staticmethod def target_template(layout, con, subtargets=True): col = layout.column() @@ -237,7 +246,7 @@ class ConstraintButtonsPanel(Panel): row.label(icon="BLANK1") layout.prop(con, "use_transform_limit") - layout.prop(con, "owner_space") + self.space_template(layout, con, target=False, owner=True) self.draw_influence(layout, con) @@ -306,7 +315,7 @@ class ConstraintButtonsPanel(Panel): row.prop_decorator(con, "max_z") layout.prop(con, "use_transform_limit") - layout.prop(con, "owner_space") + self.space_template(layout, con, target=False, owner=True) self.draw_influence(layout, con) @@ -375,7 +384,7 @@ class ConstraintButtonsPanel(Panel): row.prop_decorator(con, "max_z") layout.prop(con, "use_transform_limit") - layout.prop(con, "owner_space") + self.space_template(layout, con, target=False, owner=True) self.draw_influence(layout, con) @@ -483,7 +492,7 @@ class ConstraintButtonsPanel(Panel): layout.prop(con, "volume") - layout.prop(con, "owner_space") + self.space_template(layout, con, target=False, owner=True) self.draw_influence(layout, con) @@ -1117,7 +1126,7 @@ class ConstraintButtonsSubPanel(Panel): col = layout.column() col.active = not con.use_eval_time col.prop(con, "transform_channel", text="Channel") - col.prop(con, "target_space") + ConstraintButtonsPanel.space_template(col, con, target=True, owner=False, separator=False) sub = col.column(align=True) sub.prop(con, "min", text="Range Min") diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index 9ae7f8f8e6c..394e2270227 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -126,7 +126,7 @@ class DATA_PT_shape_curve(CurveButtonsPanel, Panel): col = layout.column() col.separator() - sub = col.column() + sub = col.column(heading="Curve Deform", align=True) sub.prop(curve, "use_radius") sub.prop(curve, "use_stretch") sub.prop(curve, "use_deform_bounds") diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 63ccbd2ae05..1ae1826b609 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -643,6 +643,11 @@ def brush_settings(layout, context, brush, popover=False): layout.prop(brush, "elastic_deform_volume_preservation", slider=True) layout.separator() + elif sculpt_tool == 'SNAKE_HOOK': + layout.separator() + layout.prop(brush, "snake_hook_deform_type") + layout.separator() + elif sculpt_tool == 'POSE': layout.separator() layout.prop(brush, "deform_target") @@ -717,6 +722,9 @@ def brush_settings(layout, context, brush, popover=False): row.prop(brush, "use_wet_persistence_pressure", text="") row = layout.row(align=True) + row.prop(brush, "wet_paint_radius_factor") + + row = layout.row(align=True) row.prop(brush, "density") row.prop(brush, "invert_density_pressure", text="") row.prop(brush, "use_density_pressure", text="") diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py index afa00bb50c2..27df3b10853 100644 --- a/release/scripts/startup/bl_ui/properties_view_layer.py +++ b/release/scripts/startup/bl_ui/properties_view_layer.py @@ -17,7 +17,16 @@ # ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> -from bpy.types import Panel +from bpy.types import Panel, UIList + + +class VIEWLAYER_UL_aov(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + row = layout.row() + split = row.split(factor=0.65) + icon = 'NONE' if item.is_valid else 'ERROR' + split.row().prop(item, "name", text="", icon=icon, emboss=False) + split.row().prop(item, "type", text="", emboss=False) class ViewLayerButtonsPanel: @@ -49,7 +58,7 @@ class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel): col.prop(rd, "use_single_layer", text="Render Single Layer") -class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel): +class VIEWLAYER_PT_layer_passes(ViewLayerButtonsPanel, Panel): bl_label = "Passes" COMPAT_ENGINES = {'BLENDER_EEVEE'} @@ -59,7 +68,7 @@ class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel): class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel): bl_label = "Data" - bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes" + bl_parent_id = "VIEWLAYER_PT_layer_passes" COMPAT_ENGINES = {'BLENDER_EEVEE'} @@ -81,7 +90,7 @@ class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel): class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel): bl_label = "Light" - bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes" + bl_parent_id = "VIEWLAYER_PT_layer_passes" COMPAT_ENGINES = {'BLENDER_EEVEE'} def draw(self, context): @@ -116,7 +125,7 @@ class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel): class VIEWLAYER_PT_eevee_layer_passes_effects(ViewLayerButtonsPanel, Panel): bl_label = "Effects" - bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes" + bl_parent_id = "VIEWLAYER_PT_layer_passes" COMPAT_ENGINES = {'BLENDER_EEVEE'} def draw(self, context): @@ -135,12 +144,70 @@ class VIEWLAYER_PT_eevee_layer_passes_effects(ViewLayerButtonsPanel, Panel): col.active = scene_eevee.use_bloom +class VIEWLAYER_PT_layer_passes_aov(ViewLayerButtonsPanel, Panel): + bl_label = "Shader AOV" + bl_parent_id = "VIEWLAYER_PT_layer_passes" + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + layout.use_property_decorate = False + + view_layer = context.view_layer + + row = layout.row() + col = row.column() + col.template_list("VIEWLAYER_UL_aov", "aovs", view_layer, "aovs", view_layer, "active_aov_index", rows=2) + + col = row.column() + sub = col.column(align=True) + sub.operator("scene.view_layer_add_aov", icon='ADD', text="") + sub.operator("scene.view_layer_remove_aov", icon='REMOVE', text="") + + aov = view_layer.active_aov + if aov and not aov.is_valid: + layout.label(text="Conflicts with another render pass with the same name", icon='ERROR') + + +class ViewLayerCryptomattePanel(ViewLayerButtonsPanel, Panel): + bl_label = "Cryptomatte" + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + layout.use_property_decorate = False + + view_layer = context.view_layer + + col = layout.column() + col.prop(view_layer, "use_pass_cryptomatte_object", text="Object") + col.prop(view_layer, "use_pass_cryptomatte_material", text="Material") + col.prop(view_layer, "use_pass_cryptomatte_asset", text="Asset") + col = layout.column() + col.active = any((view_layer.use_pass_cryptomatte_object, + view_layer.use_pass_cryptomatte_material, + view_layer.use_pass_cryptomatte_asset)) + col.prop(view_layer, "pass_cryptomatte_depth", text="Levels") + col.prop(view_layer, "use_pass_cryptomatte_accurate", text="Accurate Mode") + + +class VIEWLAYER_PT_layer_passes_cryptomatte(ViewLayerCryptomattePanel): + bl_parent_id = "VIEWLAYER_PT_layer_passes" + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + classes = ( VIEWLAYER_PT_layer, - VIEWLAYER_PT_eevee_layer_passes, + VIEWLAYER_PT_layer_passes, VIEWLAYER_PT_eevee_layer_passes_data, VIEWLAYER_PT_eevee_layer_passes_light, VIEWLAYER_PT_eevee_layer_passes_effects, + VIEWLAYER_PT_layer_passes_cryptomatte, + VIEWLAYER_PT_layer_passes_aov, + VIEWLAYER_UL_aov, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 676e93f4ce9..0c222e8c023 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -347,6 +347,8 @@ class DOPESHEET_MT_view(Menu): col.active = context.space_data.mode != 'SHAPEKEY' col.prop(st, "show_sliders") + if bpy.app.version < (2, 93): + layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT') layout.prop(st, "show_interpolation") layout.prop(st, "show_extremes") layout.prop(st, "use_auto_merge_keyframes") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 3fee0ae9d47..6ece6a4c841 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -18,6 +18,7 @@ # <pep8 compliant> +import bpy from bpy.types import Header, Menu, Panel from bl_ui.space_dopesheet import ( DopesheetFilterPopoverBase, @@ -119,7 +120,10 @@ class GRAPH_MT_view(Menu): layout.prop(st, "use_realtime_update") layout.prop(st, "show_cursor") layout.prop(st, "show_sliders") - layout.prop(st, "show_group_colors") + + if bpy.app.version < (2, 93): + layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT') + layout.prop(st, "use_auto_merge_keyframes") if st.mode != 'DRIVERS': diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 53c1a136dec..761e60aef30 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -207,10 +207,14 @@ class USERPREF_PT_interface_display(InterfacePanel, CenterAlignMixIn, Panel): col.prop(view, "ui_line_width", text="Line Width") col.prop(view, "show_splash", text="Splash Screen") col.prop(view, "show_developer_ui") + + col.separator() - col = layout.column(heading="Tooltips") - col.prop(view, "show_tooltips") - col.prop(view, "show_tooltips_python") + col = layout.column(heading="Tooltips", align=True) + col.prop(view, "show_tooltips", text = "User Tooltips") + sub = col.column() + sub.active = view.show_tooltips + sub.prop(view, "show_tooltips_python") class USERPREF_PT_interface_text(InterfacePanel, CenterAlignMixIn, Panel): @@ -2187,7 +2191,7 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel): context, ( ({"property": "use_sculpt_vertex_colors"}, "T71947"), ({"property": "use_switch_object_operator"}, "T80402"), - ({"property": "use_sculpt_tools_tilt"}, "T00000"), + ({"property": "use_sculpt_tools_tilt"}, "T82877"), ({"property": "use_object_add_tool"}, "T57210"), ), ) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 5af88e15111..10c9f25b92a 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1828,7 +1828,13 @@ class VIEW3D_MT_paint_gpencil(Menu): def draw(self, context): layout = self.layout + layout.operator("gpencil.vertex_color_set", text="Set Vertex Colors") layout.operator("gpencil.stroke_reset_vertex_color") + layout.separator() + layout.operator("gpencil.vertex_color_invert", text="Invert") + layout.operator("gpencil.vertex_color_levels", text="Levels") + layout.operator("gpencil.vertex_color_hsv", text="Hue Saturation Value") + layout.operator("gpencil.vertex_color_brightness_contrast", text="Bright/Contrast") class VIEW3D_MT_select_gpencil(Menu): @@ -5044,22 +5050,6 @@ class VIEW3D_MT_weight_gpencil(Menu): layout.menu("VIEW3D_MT_gpencil_autoweights") -class VIEW3D_MT_vertex_gpencil(Menu): - bl_label = "Paint" - - def draw(self, _context): - layout = self.layout - layout.operator("gpencil.vertex_color_set", text="Set Vertex Colors") - layout.separator() - layout.operator("gpencil.vertex_color_invert", text="Invert") - layout.operator("gpencil.vertex_color_levels", text="Levels") - layout.operator("gpencil.vertex_color_hsv", text="Hue Saturation Value") - layout.operator("gpencil.vertex_color_brightness_contrast", text="Bright/Contrast") - - layout.separator() - layout.menu("VIEW3D_MT_join_palette") - - class VIEW3D_MT_gpencil_animation(Menu): bl_label = "Animation" @@ -7606,7 +7596,6 @@ classes = ( VIEW3D_MT_edit_gpencil_delete, VIEW3D_MT_edit_gpencil_showhide, VIEW3D_MT_weight_gpencil, - VIEW3D_MT_vertex_gpencil, VIEW3D_MT_gpencil_animation, VIEW3D_MT_gpencil_simplify, VIEW3D_MT_gpencil_copy_layer, diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py index 6dffeac35ce..012febc7cc7 100644 --- a/release/scripts/startup/keyingsets_builtins.py +++ b/release/scripts/startup/keyingsets_builtins.py @@ -520,7 +520,7 @@ class BUILTIN_KSI_WholeCharacter(KeyingSetInfo): # for now, just add all of 'em prop_rna = type(bone).bl_rna.properties.get(prop, None) if prop_rna is None: - prop_path = '["%s"]' % prop + prop_path = '["%s"]' % bpy.utils.escape_identifier(prop) try: rna_property = bone.path_resolve(prop_path, False) except ValueError as ex: diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index b1789776728..abab50b95a2 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -165,11 +165,6 @@ def object_cycles_shader_nodes_poll(context): cycles_shader_nodes_poll(context)) -def cycles_aov_node_poll(context): - return (object_cycles_shader_nodes_poll(context) or - world_shader_nodes_poll(context)) - - def object_eevee_shader_nodes_poll(context): return (object_shader_nodes_poll(context) and eevee_shader_nodes_poll(context)) @@ -210,7 +205,7 @@ shader_node_categories = [ ShaderNodeCategory("SH_NEW_OUTPUT", "Output", items=[ NodeItem("ShaderNodeOutputMaterial", poll=object_eevee_cycles_shader_nodes_poll), NodeItem("ShaderNodeOutputLight", poll=object_cycles_shader_nodes_poll), - NodeItem("ShaderNodeOutputAOV", poll=cycles_aov_node_poll), + NodeItem("ShaderNodeOutputAOV"), NodeItem("ShaderNodeOutputWorld", poll=world_shader_nodes_poll), NodeItem("ShaderNodeOutputLineStyle", poll=line_style_shader_nodes_poll), NodeItem("NodeGroupOutput", poll=group_input_output_item_poll), diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 88c19355960..0ce2341fc2e 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -22,7 +22,7 @@ if(WITH_LEGACY_OPENGL) add_definitions(-DWITH_LEGACY_OPENGL) endif() -if(WITH_CLANG_TIDY) +if(WITH_CLANG_TIDY AND NOT MSVC) if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang") message(WARNING "Currently Clang-Tidy might fail with GCC toolchain, switch to Clang toolchain if that happens") endif() diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index 3e52d7f3301..6da6079ea2a 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -26,6 +26,7 @@ extern "C" { struct ListBase; void BKE_appdir_init(void); +void BKE_appdir_exit(void); /* note on naming: typical _get() suffix is omitted here, * since its the main purpose of the API. */ diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index e58fba36342..c4a704ef385 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -23,6 +23,7 @@ #include "BKE_attribute.h" +#include "BLI_color.hh" #include "BLI_float3.hh" struct Mesh; @@ -31,6 +32,9 @@ namespace blender::bke { using fn::CPPType; +const CPPType *custom_data_type_to_cpp_type(const CustomDataType type); +CustomDataType cpp_type_to_custom_data_type(const CPPType &type); + /** * This class offers an indirection for reading an attribute. * This is useful for the following reasons: @@ -47,6 +51,7 @@ class ReadAttribute { protected: const AttributeDomain domain_; const CPPType &cpp_type_; + const CustomDataType custom_data_type_; const int64_t size_; /* Protects the span below, so that no two threads initialize it at the same time. */ @@ -59,7 +64,10 @@ class ReadAttribute { public: ReadAttribute(AttributeDomain domain, const CPPType &cpp_type, const int64_t size) - : domain_(domain), cpp_type_(cpp_type), size_(size) + : domain_(domain), + cpp_type_(cpp_type), + custom_data_type_(cpp_type_to_custom_data_type(cpp_type)), + size_(size) { } @@ -75,6 +83,11 @@ class ReadAttribute { return cpp_type_; } + CustomDataType custom_data_type() const + { + return custom_data_type_; + } + int64_t size() const { return size_; @@ -104,6 +117,7 @@ class WriteAttribute { protected: const AttributeDomain domain_; const CPPType &cpp_type_; + const CustomDataType custom_data_type_; const int64_t size_; /* When not null, this points either to the attribute array or to a temporary array. */ @@ -115,7 +129,10 @@ class WriteAttribute { public: WriteAttribute(AttributeDomain domain, const CPPType &cpp_type, const int64_t size) - : domain_(domain), cpp_type_(cpp_type), size_(size) + : domain_(domain), + cpp_type_(cpp_type), + custom_data_type_(cpp_type_to_custom_data_type(cpp_type)), + size_(size) { } @@ -131,6 +148,11 @@ class WriteAttribute { return cpp_type_; } + CustomDataType custom_data_type() const + { + return custom_data_type_; + } + int64_t size() const { return size_; @@ -246,10 +268,9 @@ template<typename T> class TypedWriteAttribute { using FloatReadAttribute = TypedReadAttribute<float>; using Float3ReadAttribute = TypedReadAttribute<float3>; +using Color4fReadAttribute = TypedReadAttribute<Color4f>; using FloatWriteAttribute = TypedWriteAttribute<float>; using Float3WriteAttribute = TypedWriteAttribute<float3>; - -const CPPType *custom_data_type_to_cpp_type(const CustomDataType type); -CustomDataType cpp_type_to_custom_data_type(const CPPType &type); +using Color4fWriteAttribute = TypedWriteAttribute<Color4f>; } // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 9fa32013ba6..afb6112b954 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 4 +#define BLENDER_FILE_SUBVERSION 6 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index e5c4535560d..7a14787c191 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -56,6 +56,8 @@ typedef struct bConstraintOb { float matrix[4][4]; /** original matrix (before constraint solving) */ float startmat[4][4]; + /** space matrix for custom object space */ + float space_obj_world_matrix[4][4]; /** type of owner */ short type; @@ -175,6 +177,9 @@ struct bConstraint *BKE_constraint_find_from_target(struct Object *ob, struct bConstraintTarget *tgt, struct bPoseChannel **r_pchan); +bool BKE_constraint_is_nonlocal_in_liboverride(const struct Object *ob, + const struct bConstraint *con); + struct bConstraint *BKE_constraint_add_for_object(struct Object *ob, const char *name, short type); struct bConstraint *BKE_constraint_add_for_pose(struct Object *ob, struct bPoseChannel *pchan, @@ -203,6 +208,7 @@ void BKE_constraints_clear_evalob(struct bConstraintOb *cob); void BKE_constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, + struct bConstraintOb *cob, float mat[4][4], short from, short to, @@ -221,6 +227,7 @@ void BKE_constraint_targets_for_solving_get(struct Depsgraph *depsgraph, struct bConstraintOb *ob, struct ListBase *targets, float ctime); +void BKE_constraint_custom_object_space_get(float r_mat[4][4], struct bConstraint *con); void BKE_constraints_solve(struct Depsgraph *depsgraph, struct ListBase *conlist, struct bConstraintOb *cob, diff --git a/source/blender/blenkernel/BKE_cryptomatte.h b/source/blender/blenkernel/BKE_cryptomatte.h new file mode 100644 index 00000000000..9ad4770c754 --- /dev/null +++ b/source/blender/blenkernel/BKE_cryptomatte.h @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#pragma once + +#include "BLI_sys_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Object; +struct Material; + +uint32_t BKE_cryptomatte_object_hash(const struct Object *object); +uint32_t BKE_cryptomatte_material_hash(const struct Material *material); +uint32_t BKE_cryptomatte_asset_hash(const struct Object *object); +float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash); + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index ef3ae3c381c..3398da9896b 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -157,6 +157,14 @@ class GeometryComponent { const CustomDataType data_type, const void *value) const; + /* Create a read-only dummy attribute that always returns the same value. + * The given value is converted to the correct type if necessary. */ + blender::bke::ReadAttributePtr attribute_get_constant_for_read_converted( + const AttributeDomain domain, + const CustomDataType in_data_type, + const CustomDataType out_data_type, + const void *value) const; + /* Get a read-only dummy attribute that always returns the same value. */ template<typename T> blender::bke::TypedReadAttribute<T> attribute_get_constant_for_read(const AttributeDomain domain, diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index 7729d2c53ab..ccf65a585ef 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -278,6 +278,9 @@ void BKE_gpencil_modifiers_foreach_tex_link(struct Object *ob, GreasePencilTexWalkFunc walk, void *userData); +bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const struct Object *ob, + const struct GpencilModifierData *gmd); + typedef struct GpencilVirtualModifierData { ArmatureGpencilModifierData amd; LatticeGpencilModifierData lmd; diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 7091a060243..e5fab35891c 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -42,6 +42,7 @@ struct Depsgraph; struct LayerCollection; struct Main; struct Object; +struct RenderEngine; struct Scene; struct View3D; struct ViewLayer; @@ -444,6 +445,15 @@ bool BKE_view_layer_filter_edit_mesh_has_edges(struct Object *ob, void *user_dat BKE_view_layer_array_from_objects_in_mode( \ view_layer, v3d, r_len, {.object_mode = mode, .no_dup_data = true}) +struct ViewLayerAOV *BKE_view_layer_add_aov(struct ViewLayer *view_layer); +void BKE_view_layer_remove_aov(struct ViewLayer *view_layer, struct ViewLayerAOV *aov); +void BKE_view_layer_set_active_aov(struct ViewLayer *view_layer, struct ViewLayerAOV *aov); +void BKE_view_layer_verify_aov(struct RenderEngine *engine, + struct Scene *scene, + struct ViewLayer *view_layer); +bool BKE_view_layer_has_valid_aov(struct ViewLayer *view_layer); +ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene, struct ViewLayerAOV *view_layer_aov); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index b0a7d89e3d8..73e33124b43 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -431,6 +431,8 @@ bool BKE_modifier_is_non_geometrical(ModifierData *md); bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode); +bool BKE_modifier_is_nonlocal_in_liboverride(const struct Object *ob, + const struct ModifierData *md); void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format, diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 8671324fab1..16d48024d07 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -60,9 +60,13 @@ struct NlaTrack *BKE_nlatrack_copy(struct Main *bmain, const int flag); void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, ListBase *src, const int flag); -struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev); +struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, + struct NlaTrack *prev, + bool is_liboverride); struct NlaStrip *BKE_nlastrip_new(struct bAction *act); -struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt, struct bAction *act); +struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt, + struct bAction *act, + const bool is_liboverride); struct NlaStrip *BKE_nla_add_soundstrip(struct Main *bmain, struct Scene *scene, struct Speaker *speaker); @@ -95,10 +99,14 @@ void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); -bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip); +bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, + struct NlaStrip *strip, + const bool is_liboverride); bool BKE_nlatrack_get_bounds(struct NlaTrack *nlt, float bounds[2]); +bool BKE_nlatrack_is_nonlocal_in_liboverride(const struct ID *id, const struct NlaTrack *nlt); + /* ............ */ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); @@ -124,11 +132,11 @@ void BKE_nla_validate_state(struct AnimData *adt); /* ............ */ bool BKE_nla_action_is_stashed(struct AnimData *adt, struct bAction *act); -bool BKE_nla_action_stash(struct AnimData *adt); +bool BKE_nla_action_stash(struct AnimData *adt, const bool is_liboverride); /* ............ */ -void BKE_nla_action_pushdown(struct AnimData *adt); +void BKE_nla_action_pushdown(struct AnimData *adt, const bool is_liboverride); bool BKE_nla_tweakmode_enter(struct AnimData *adt); void BKE_nla_tweakmode_exit(struct AnimData *adt); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 1a90d6fadd3..c962f0a6a8c 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -101,6 +101,7 @@ set(SRC intern/constraint.c intern/context.c intern/crazyspace.c + intern/cryptomatte.c intern/curve.c intern/curve_bevel.c intern/curve_decimate.c @@ -726,6 +727,7 @@ if(WITH_GTESTS) intern/fcurve_test.cc intern/lattice_deform_test.cc intern/tracking_test.cc + intern/layer_test.cc ) set(TEST_INC ../editors/include diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index a85509b11db..13abfa92032 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -989,8 +989,8 @@ char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *name_old_esc = BLI_array_alloca(name_old_esc, (name_old_len * 2) + 1); char *name_new_esc = BLI_array_alloca(name_new_esc, (name_new_len * 2) + 1); - BLI_strescape(name_old_esc, oldName, (name_old_len * 2) + 1); - BLI_strescape(name_new_esc, newName, (name_new_len * 2) + 1); + BLI_str_escape(name_old_esc, oldName, (name_old_len * 2) + 1); + BLI_str_escape(name_new_esc, newName, (name_new_len * 2) + 1); oldN = BLI_sprintfN("[\"%s\"]", name_old_esc); newN = BLI_sprintfN("[\"%s\"]", name_new_esc); } @@ -1048,8 +1048,8 @@ void BKE_action_fix_paths_rename(ID *owner_id, char *name_old_esc = BLI_array_alloca(name_old_esc, (name_old_len * 2) + 1); char *name_new_esc = BLI_array_alloca(name_new_esc, (name_new_len * 2) + 1); - BLI_strescape(name_old_esc, oldName, (name_old_len * 2) + 1); - BLI_strescape(name_new_esc, newName, (name_new_len * 2) + 1); + BLI_str_escape(name_old_esc, oldName, (name_old_len * 2) + 1); + BLI_str_escape(name_new_esc, newName, (name_new_len * 2) + 1); oldN = BLI_sprintfN("[\"%s\"]", name_old_esc); newN = BLI_sprintfN("[\"%s\"]", name_new_esc); } @@ -1096,8 +1096,8 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, char *name_old_esc = BLI_array_alloca(name_old_esc, (name_old_len * 2) + 1); char *name_new_esc = BLI_array_alloca(name_new_esc, (name_new_len * 2) + 1); - BLI_strescape(name_old_esc, oldName, (name_old_len * 2) + 1); - BLI_strescape(name_new_esc, newName, (name_new_len * 2) + 1); + BLI_str_escape(name_old_esc, oldName, (name_old_len * 2) + 1); + BLI_str_escape(name_new_esc, newName, (name_new_len * 2) + 1); oldN = BLI_sprintfN("[\"%s\"]", name_old_esc); newN = BLI_sprintfN("[\"%s\"]", name_new_esc); } diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 2038079744d..b1462167edd 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -114,6 +114,14 @@ void BKE_appdir_init(void) #endif } +void BKE_appdir_exit(void) +{ +#ifndef NDEBUG + BLI_assert(is_appdir_init == true); + is_appdir_init = false; +#endif +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 2345c834be4..d79168d5443 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -325,7 +325,7 @@ class ConstantReadAttribute final : public ReadAttribute { type.copy_to_uninitialized(value, value_); } - ~ConstantReadAttribute() + ~ConstantReadAttribute() override { this->cpp_type_.destruct(value_); MEM_freeN(value_); @@ -668,6 +668,39 @@ blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_rea domain, domain_size, *cpp_type, value); } +blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_read_converted( + const AttributeDomain domain, + const CustomDataType in_data_type, + const CustomDataType out_data_type, + const void *value) const +{ + BLI_assert(this->attribute_domain_supported(domain)); + if (value == nullptr || in_data_type == out_data_type) { + return this->attribute_get_constant_for_read(domain, out_data_type, value); + } + + const blender::fn::CPPType *in_cpp_type = blender::bke::custom_data_type_to_cpp_type( + in_data_type); + const blender::fn::CPPType *out_cpp_type = blender::bke::custom_data_type_to_cpp_type( + out_data_type); + BLI_assert(in_cpp_type != nullptr); + BLI_assert(out_cpp_type != nullptr); + + const blender::nodes::DataTypeConversions &conversions = + blender::nodes::get_implicit_type_conversions(); + BLI_assert(conversions.is_convertible(*in_cpp_type, *out_cpp_type)); + + void *out_value = alloca(out_cpp_type->size()); + conversions.convert(*in_cpp_type, *out_cpp_type, value, out_value); + + const int domain_size = this->attribute_domain_size(domain); + blender::bke::ReadAttributePtr attribute = std::make_unique<blender::bke::ConstantReadAttribute>( + domain, domain_size, *out_cpp_type, out_value); + + out_cpp_type->destruct(out_value); + return attribute; +} + WriteAttributePtr GeometryComponent::attribute_try_ensure_for_write(const StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type) diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 1b77989c2b8..96791aed2c3 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -446,6 +446,7 @@ static void brush_defaults(Brush *brush) FROM_DEFAULT(topology_rake_factor); FROM_DEFAULT(crease_pinch_factor); FROM_DEFAULT(normal_radius_factor); + FROM_DEFAULT(wet_paint_radius_factor); FROM_DEFAULT(area_radius_factor); FROM_DEFAULT(disconnected_distance_max); FROM_DEFAULT(sculpt_plane); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 5497065bb34..1c17692ac36 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -261,8 +261,13 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) * of a matrix from one space to another for constraint evaluation. * For now, this is only implemented for Objects and PoseChannels. */ -void BKE_constraint_mat_convertspace( - Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale) +void BKE_constraint_mat_convertspace(Object *ob, + bPoseChannel *pchan, + bConstraintOb *cob, + float mat[4][4], + short from, + short to, + const bool keep_scale) { float diff_mat[4][4]; float imat[4][4]; @@ -282,25 +287,30 @@ void BKE_constraint_mat_convertspace( switch (from) { case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */ { - /* world to pose */ - invert_m4_m4(imat, ob->obmat); - mul_m4_m4m4(mat, imat, mat); - - /* use pose-space as stepping stone for other spaces... */ - if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { - /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + if (to == CONSTRAINT_SPACE_CUSTOM) { + /* World to custom. */ + BLI_assert(cob); + invert_m4_m4(imat, cob->space_obj_world_matrix); + mul_m4_m4m4(mat, imat, mat); + } + else { + /* World to pose. */ + invert_m4_m4(imat, ob->obmat); + mul_m4_m4m4(mat, imat, mat); + + /* Use pose-space as stepping stone for other spaces. */ + if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { + /* Call self with slightly different values. */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + } } break; } case CONSTRAINT_SPACE_POSE: /* ---------- FROM POSESPACE ---------- */ { - /* pose to world */ - if (to == CONSTRAINT_SPACE_WORLD) { - mul_m4_m4m4(mat, ob->obmat, mat); - } /* pose to local */ - else if (to == CONSTRAINT_SPACE_LOCAL) { + if (to == CONSTRAINT_SPACE_LOCAL) { if (pchan->bone) { BKE_armature_mat_pose_to_bone(pchan, mat, mat); } @@ -312,6 +322,16 @@ void BKE_constraint_mat_convertspace( mul_m4_m4m4(mat, imat, mat); } } + else { + /* Pose to world. */ + mul_m4_m4m4(mat, ob->obmat, mat); + /* Use world-space as stepping stone for other spaces. */ + if (to != CONSTRAINT_SPACE_WORLD) { + /* Call self with slightly different values. */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_WORLD, to, keep_scale); + } + } break; } case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */ @@ -323,9 +343,10 @@ void BKE_constraint_mat_convertspace( } /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { + if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL, CONSTRAINT_SPACE_CUSTOM)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); } break; } @@ -337,9 +358,24 @@ void BKE_constraint_mat_convertspace( } /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { + if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_CUSTOM)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); + } + break; + } + case CONSTRAINT_SPACE_CUSTOM: /* -------------- FROM CUSTOM SPACE ---------- */ + { + /* Custom to world. */ + BLI_assert(cob); + mul_m4_m4m4(mat, cob->space_obj_world_matrix, mat); + + /* Use world-space as stepping stone for other spaces. */ + if (to != CONSTRAINT_SPACE_WORLD) { + /* Call self with slightly different values. */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_WORLD, to, keep_scale); } break; } @@ -347,37 +383,44 @@ void BKE_constraint_mat_convertspace( } else { /* objects */ - if (from == CONSTRAINT_SPACE_WORLD && to == CONSTRAINT_SPACE_LOCAL) { - /* check if object has a parent */ - if (ob->parent) { - /* 'subtract' parent's effects from owner */ - mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv); - invert_m4_m4_safe(imat, diff_mat); - mul_m4_m4m4(mat, imat, mat); - } - else { - /* Local space in this case will have to be defined as local to the owner's - * transform-property-rotated axes. So subtract this rotation component. - */ - /* XXX This is actually an ugly hack, local space of a parent-less object *is* the same as - * global space! - * Think what we want actually here is some kind of 'Final Space', i.e - * . once transformations are applied - users are often confused about this too, - * this is not consistent with bones - * local space either... Meh :| - * --mont29 - */ - BKE_object_to_mat4(ob, diff_mat); - if (!keep_scale) { - normalize_m4(diff_mat); + if (from == CONSTRAINT_SPACE_WORLD) { + if (to == CONSTRAINT_SPACE_LOCAL) { + /* Check if object has a parent. */ + if (ob->parent) { + /* 'subtract' parent's effects from owner. */ + mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv); + invert_m4_m4_safe(imat, diff_mat); + mul_m4_m4m4(mat, imat, mat); } - zero_v3(diff_mat[3]); + else { + /* Local space in this case will have to be defined as local to the owner's + * transform-property-rotated axes. So subtract this rotation component. + */ + /* XXX This is actually an ugly hack, local space of a parent-less object *is* the same + * as global space! Think what we want actually here is some kind of 'Final Space', i.e + * . once transformations are applied - users are often confused about this too, + * this is not consistent with bones + * local space either... Meh :| + * --mont29 + */ + BKE_object_to_mat4(ob, diff_mat); + if (!keep_scale) { + normalize_m4(diff_mat); + } + zero_v3(diff_mat[3]); - invert_m4_m4_safe(imat, diff_mat); + invert_m4_m4_safe(imat, diff_mat); + mul_m4_m4m4(mat, imat, mat); + } + } + else if (to == CONSTRAINT_SPACE_CUSTOM) { + /* 'subtract' custom objects's effects from owner. */ + BLI_assert(cob); + invert_m4_m4_safe(imat, cob->space_obj_world_matrix); mul_m4_m4m4(mat, imat, mat); } } - else if (from == CONSTRAINT_SPACE_LOCAL && to == CONSTRAINT_SPACE_WORLD) { + else if (from == CONSTRAINT_SPACE_LOCAL) { /* check that object has a parent - otherwise this won't work */ if (ob->parent) { /* 'add' parent's effect back to owner */ @@ -397,6 +440,24 @@ void BKE_constraint_mat_convertspace( mul_m4_m4m4(mat, diff_mat, mat); } + if (to == CONSTRAINT_SPACE_CUSTOM) { + /* 'subtract' objects's effects from owner. */ + BLI_assert(cob); + invert_m4_m4_safe(imat, cob->space_obj_world_matrix); + mul_m4_m4m4(mat, imat, mat); + } + } + else if (from == CONSTRAINT_SPACE_CUSTOM) { + /* Custom to world. */ + BLI_assert(cob); + mul_m4_m4m4(mat, cob->space_obj_world_matrix, mat); + + /* Use world-space as stepping stone for other spaces. */ + if (to != CONSTRAINT_SPACE_WORLD) { + /* Call self with slightly different values. */ + BKE_constraint_mat_convertspace( + ob, pchan, cob, mat, CONSTRAINT_SPACE_WORLD, to, keep_scale); + } } } } @@ -573,6 +634,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m /* The cases where the target can be object data have not been implemented */ static void constraint_target_to_mat4(Object *ob, const char *substring, + bConstraintOb *cob, float mat[4][4], short from, short to, @@ -582,7 +644,7 @@ static void constraint_target_to_mat4(Object *ob, /* Case OBJECT */ if (substring[0] == '\0') { copy_m4_m4(mat, ob->obmat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); + BKE_constraint_mat_convertspace(ob, NULL, cob, mat, from, to, false); } /* Case VERTEXGROUP */ /* Current method just takes the average location of all the points in the @@ -595,11 +657,11 @@ static void constraint_target_to_mat4(Object *ob, */ else if (ob->type == OB_MESH) { contarget_get_mesh_mat(ob, substring, mat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); + BKE_constraint_mat_convertspace(ob, NULL, cob, mat, from, to, false); } else if (ob->type == OB_LATTICE) { contarget_get_lattice_mat(ob, substring, mat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); + BKE_constraint_mat_convertspace(ob, NULL, cob, mat, from, to, false); } /* Case BONE */ else { @@ -662,7 +724,7 @@ static void constraint_target_to_mat4(Object *ob, } /* convert matrix space as required */ - BKE_constraint_mat_convertspace(ob, pchan, mat, from, to, false); + BKE_constraint_mat_convertspace(ob, pchan, cob, mat, from, to, false); } } @@ -705,13 +767,14 @@ static bConstraintTypeInfo CTI_CONSTRNAME = { */ static void default_get_tarmat(struct Depsgraph *UNUSED(depsgraph), bConstraint *con, - bConstraintOb *UNUSED(cob), + bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) { constraint_target_to_mat4(ct->tar, ct->subtarget, + cob, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, @@ -727,13 +790,14 @@ static void default_get_tarmat(struct Depsgraph *UNUSED(depsgraph), */ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph), bConstraint *con, - bConstraintOb *UNUSED(cob), + bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) { constraint_target_to_mat4(ct->tar, ct->subtarget, + cob, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, @@ -844,6 +908,32 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph), } \ (void)0 +static void custom_space_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) +{ + func(con, (ID **)&con->space_object, false, userdata); +} + +static int get_space_tar(bConstraint *con, ListBase *list) +{ + if (!con || !list || + (con->ownspace != CONSTRAINT_SPACE_CUSTOM && con->tarspace != CONSTRAINT_SPACE_CUSTOM)) { + return 0; + } + bConstraintTarget *ct; + SINGLETARGET_GET_TARS(con, con->space_object, con->space_subtarget, ct, list); + return 1; +} + +static void flush_space_tar(bConstraint *con, ListBase *list, bool no_copy) +{ + if (!con || !list || + (con->ownspace != CONSTRAINT_SPACE_CUSTOM && con->tarspace != CONSTRAINT_SPACE_CUSTOM)) { + return; + } + bConstraintTarget *ct = (bConstraintTarget *)list->last; + SINGLETARGET_FLUSH_TARS(con, con->space_object, con->space_subtarget, ct, list, no_copy); +} + /* --------- ChildOf Constraint ------------ */ static void childof_new_data(void *cdata) @@ -1030,6 +1120,8 @@ static void trackto_id_looper(bConstraint *con, ConstraintIDFunc func, void *use /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int trackto_get_tars(bConstraint *con, ListBase *list) @@ -1041,7 +1133,7 @@ static int trackto_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -1055,6 +1147,7 @@ static void trackto_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -1262,6 +1355,7 @@ static void kinematic_get_tarmat(struct Depsgraph *UNUSED(depsgraph), if (VALID_CONS_TARGET(ct)) { constraint_target_to_mat4(ct->tar, ct->subtarget, + cob, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, @@ -1533,11 +1627,11 @@ static bConstraintTypeInfo CTI_LOCLIMIT = { "Limit Location", /* name */ "bLocLimitConstraint", /* struct name */ NULL, /* free data */ - NULL, /* id looper */ + custom_space_id_looper, /* id looper */ NULL, /* copy data */ NULL, /* new data */ - NULL, /* get constraint targets */ - NULL, /* flush constraint targets */ + get_space_tar, /* get constraint targets */ + flush_space_tar, /* flush constraint targets */ NULL, /* get target matrix */ loclimit_evaluate, /* evaluate */ }; @@ -1596,11 +1690,11 @@ static bConstraintTypeInfo CTI_ROTLIMIT = { "Limit Rotation", /* name */ "bRotLimitConstraint", /* struct name */ NULL, /* free data */ - NULL, /* id looper */ + custom_space_id_looper, /* id looper */ NULL, /* copy data */ NULL, /* new data */ - NULL, /* get constraint targets */ - NULL, /* flush constraint targets */ + get_space_tar, /* get constraint targets */ + flush_space_tar, /* flush constraint targets */ NULL, /* get target matrix */ rotlimit_evaluate, /* evaluate */ }; @@ -1663,11 +1757,11 @@ static bConstraintTypeInfo CTI_SIZELIMIT = { "Limit Scale", /* name */ "bSizeLimitConstraint", /* struct name */ NULL, /* free data */ - NULL, /* id looper */ + custom_space_id_looper, /* id looper */ NULL, /* copy data */ NULL, /* new data */ - NULL, /* get constraint targets */ - NULL, /* flush constraint targets */ + get_space_tar, /* get constraint targets */ + flush_space_tar, /* flush constraint targets */ NULL, /* get target matrix */ sizelimit_evaluate, /* evaluate */ }; @@ -1687,6 +1781,8 @@ static void loclike_id_looper(bConstraint *con, ConstraintIDFunc func, void *use /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int loclike_get_tars(bConstraint *con, ListBase *list) @@ -1698,7 +1794,7 @@ static int loclike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -1712,6 +1808,7 @@ static void loclike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -1784,6 +1881,8 @@ static void rotlike_id_looper(bConstraint *con, ConstraintIDFunc func, void *use /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int rotlike_get_tars(bConstraint *con, ListBase *list) @@ -1795,7 +1894,7 @@ static int rotlike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -1809,6 +1908,7 @@ static void rotlike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -1962,6 +2062,8 @@ static void sizelike_id_looper(bConstraint *con, ConstraintIDFunc func, void *us /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int sizelike_get_tars(bConstraint *con, ListBase *list) @@ -1973,7 +2075,7 @@ static int sizelike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -1987,6 +2089,7 @@ static void sizelike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -2084,6 +2187,8 @@ static void translike_id_looper(bConstraint *con, ConstraintIDFunc func, void *u /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int translike_get_tars(bConstraint *con, ListBase *list) @@ -2095,7 +2200,7 @@ static int translike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -2109,6 +2214,7 @@ static void translike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -2212,11 +2318,11 @@ static bConstraintTypeInfo CTI_SAMEVOL = { "Maintain Volume", /* name */ "bSameVolumeConstraint", /* struct name */ NULL, /* free data */ - NULL, /* id looper */ + custom_space_id_looper, /* id looper */ NULL, /* copy data */ samevolume_new_data, /* new data */ - NULL, /* get constraint targets */ - NULL, /* flush constraint targets */ + get_space_tar, /* get constraint targets */ + flush_space_tar, /* flush constraint targets */ NULL, /* get target matrix */ samevolume_evaluate, /* evaluate */ }; @@ -2282,7 +2388,7 @@ static void pycon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userd /* Whether this approach is maintained remains to be seen (aligorith) */ static void pycon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), bConstraint *con, - bConstraintOb *UNUSED(cob), + bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { @@ -2301,6 +2407,7 @@ static void pycon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), */ constraint_target_to_mat4(ct->tar, ct->subtarget, + cob, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, @@ -2608,6 +2715,8 @@ static void actcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *user /* action */ func(con, (ID **)&data->act, true, userdata); + + custom_space_id_looper(con, func, userdata); } static int actcon_get_tars(bConstraint *con, ListBase *list) @@ -2619,7 +2728,7 @@ static int actcon_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -2633,6 +2742,7 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -2660,6 +2770,7 @@ static void actcon_get_tarmat(struct Depsgraph *depsgraph, /* get the transform matrix of the target */ constraint_target_to_mat4(ct->tar, ct->subtarget, + cob, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, @@ -3117,6 +3228,8 @@ static void distlimit_id_looper(bConstraint *con, ConstraintIDFunc func, void *u /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int distlimit_get_tars(bConstraint *con, ListBase *list) @@ -3128,7 +3241,7 @@ static int distlimit_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -3142,6 +3255,7 @@ static void distlimit_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -3470,6 +3584,8 @@ static void minmax_id_looper(bConstraint *con, ConstraintIDFunc func, void *user /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int minmax_get_tars(bConstraint *con, ListBase *list) @@ -3481,7 +3597,7 @@ static int minmax_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -3495,6 +3611,7 @@ static void minmax_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -3789,6 +3906,8 @@ static void transform_id_looper(bConstraint *con, ConstraintIDFunc func, void *u /* target only */ func(con, (ID **)&data->tar, false, userdata); + + custom_space_id_looper(con, func, userdata); } static int transform_get_tars(bConstraint *con, ListBase *list) @@ -3800,7 +3919,7 @@ static int transform_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1; + return 1 + get_space_tar(con, list); } return 0; @@ -3814,6 +3933,7 @@ static void transform_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); + flush_space_tar(con, list, no_copy); } } @@ -4122,7 +4242,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph), * See T42447. */ unit_m4(mat); BKE_constraint_mat_convertspace( - cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true); + cob->ob, cob->pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true); invert_m4(mat); mul_mat3_m4_v3(mat, no); @@ -5634,6 +5754,7 @@ bConstraint *BKE_constraint_duplicate_ex(bConstraint *src, const int flag, const bConstraint *dst = MEM_dupallocN(src); constraint_copy_data_ex(dst, src, flag, do_extern); dst->next = dst->prev = NULL; + dst->flag |= CONSTRAINT_OVERRIDE_LIBRARY_LOCAL; return dst; } @@ -5668,6 +5789,7 @@ void BKE_constraints_copy_ex(ListBase *dst, const ListBase *src, const int flag, for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) { constraint_copy_data_ex(con, srccon, flag, do_extern); + con->flag |= CONSTRAINT_OVERRIDE_LIBRARY_LOCAL; } } @@ -5834,6 +5956,18 @@ static bConstraint *constraint_find_original_for_update(bConstraintOb *cob, bCon return orig_con; } +/** + * Check whether given constraint is not local (i.e. from linked data) when the object is a library + * override. + * + * \param con May be NULL, in which case we consider it as a non-local constraint case. + */ +bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstraint *con) +{ + return (ID_IS_OVERRIDE_LIBRARY(ob) && + (con == NULL || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) == 0)); +} + /* -------- Constraints and Proxies ------- */ /* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL @@ -6000,6 +6134,35 @@ void BKE_constraint_targets_for_solving_get(struct Depsgraph *depsgraph, } } +void BKE_constraint_custom_object_space_get(float r_mat[4][4], bConstraint *con) +{ + if (!con || + (con->ownspace != CONSTRAINT_SPACE_CUSTOM && con->tarspace != CONSTRAINT_SPACE_CUSTOM)) { + return; + } + bConstraintTarget *ct; + ListBase target = {NULL, NULL}; + SINGLETARGET_GET_TARS(con, con->space_object, con->space_subtarget, ct, &target); + + /* Basically default_get_tarmat but without the unused parameters. */ + if (VALID_CONS_TARGET(ct)) { + constraint_target_to_mat4(ct->tar, + ct->subtarget, + NULL, + ct->matrix, + CONSTRAINT_SPACE_WORLD, + CONSTRAINT_SPACE_WORLD, + 0, + 0); + copy_m4_m4(r_mat, ct->matrix); + } + else { + unit_m4(r_mat); + } + + SINGLETARGET_FLUSH_TARS(con, con->space_object, con->space_subtarget, ct, &target, true); +} + /* ---------- Evaluation ----------- */ /* This function is called whenever constraints need to be evaluated. Currently, all @@ -6048,12 +6211,15 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, */ enf = con->enforce; + /* Get custom space matrix. */ + BKE_constraint_custom_object_space_get(cob->space_obj_world_matrix, con); + /* make copy of world-space matrix pre-constraint for use with blending later */ copy_m4_m4(oldmat, cob->matrix); /* move owner matrix into right space */ BKE_constraint_mat_convertspace( - cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false); + cob->ob, cob->pchan, cob, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false); /* prepare targets for constraint solving */ BKE_constraint_targets_for_solving_get(depsgraph, con, cob, &targets, ctime); @@ -6072,7 +6238,7 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, /* move owner back into world-space for next constraint/other business */ if ((con->flag & CONSTRAINT_SPACEONCE) == 0) { BKE_constraint_mat_convertspace( - cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD, false); + cob->ob, cob->pchan, cob, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD, false); } /* Interpolate the enforcement, to blend result of constraint into final owner transform diff --git a/source/blender/blenkernel/intern/cryptomatte.c b/source/blender/blenkernel/intern/cryptomatte.c new file mode 100644 index 00000000000..6570ffce920 --- /dev/null +++ b/source/blender/blenkernel/intern/cryptomatte.c @@ -0,0 +1,87 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "BKE_cryptomatte.h" + +#include "DNA_material_types.h" +#include "DNA_object_types.h" + +#include "BLI_compiler_attrs.h" +#include "BLI_hash_mm3.h" +#include "BLI_string.h" +#include <string.h> + +static uint32_t cryptomatte_hash(const ID *id) +{ + const char *name = &id->name[2]; + const int len = BLI_strnlen(name, MAX_NAME - 2); + uint32_t cryptohash_int = BLI_hash_mm3((const unsigned char *)name, len, 0); + return cryptohash_int; +} + +uint32_t BKE_cryptomatte_object_hash(const Object *object) +{ + return cryptomatte_hash(&object->id); +} + +uint32_t BKE_cryptomatte_material_hash(const Material *material) +{ + if (material == NULL) { + return 0.0f; + } + return cryptomatte_hash(&material->id); +} + +uint32_t BKE_cryptomatte_asset_hash(const Object *object) +{ + const Object *asset_object = object; + while (asset_object->parent != NULL) { + asset_object = asset_object->parent; + } + return cryptomatte_hash(&asset_object->id); +} + +/* Convert a cryptomatte hash to a float. + * + * Cryptomatte hashes are stored in float textures and images. The conversion is taken from the + * cryptomatte specification. See Floating point conversion section in + * https://github.com/Psyop/Cryptomatte/blob/master/specification/cryptomatte_specification.pdf. + * + * The conversion uses as many 32 bit floating point values as possible to minimize hash + * collisions. Unfortunately not all 32 bits can be as NaN and Inf can be problematic. + * + * Note that this conversion assumes to be running on a L-endian system. */ +float BKE_cryptomatte_hash_to_float(uint32_t cryptomatte_hash) +{ + uint32_t mantissa = cryptomatte_hash & ((1 << 23) - 1); + uint32_t exponent = (cryptomatte_hash >> 23) & ((1 << 8) - 1); + exponent = MAX2(exponent, (uint32_t)1); + exponent = MIN2(exponent, (uint32_t)254); + exponent = exponent << 23; + uint32_t sign = (cryptomatte_hash >> 31); + sign = sign << 31; + uint32_t float_bits = sign | exponent | mantissa; + float f; + memcpy(&f, &float_bits, sizeof(uint32_t)); + return f; +} diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 2df9f362b9c..ebce28c4e23 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -2185,19 +2185,28 @@ static void bevel_list_calc_bisect(BevList *bl) bevp2++; } + /* In the unlikely situation that handles define a zeroed direction, + * calculate it from the adjacent points, see T80742. + * + * Only do this as a fallback since we typically want the end-point directions + * to be exactly aligned with the handles at the end-point, see T83117. */ if (is_cyclic == false) { bevp0 = &bl->bevpoints[0]; bevp1 = &bl->bevpoints[1]; - sub_v3_v3v3(bevp0->dir, bevp1->vec, bevp0->vec); - if (normalize_v3(bevp0->dir) == 0.0f) { - copy_v3_v3(bevp0->dir, bevp1->dir); + if (UNLIKELY(is_zero_v3(bevp0->dir))) { + sub_v3_v3v3(bevp0->dir, bevp1->vec, bevp0->vec); + if (normalize_v3(bevp0->dir) == 0.0f) { + copy_v3_v3(bevp0->dir, bevp1->dir); + } } bevp0 = &bl->bevpoints[bl->nr - 2]; bevp1 = &bl->bevpoints[bl->nr - 1]; - sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp0->vec); - if (normalize_v3(bevp1->dir) == 0.0f) { - copy_v3_v3(bevp1->dir, bevp0->dir); + if (UNLIKELY(is_zero_v3(bevp1->dir))) { + sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp0->vec); + if (normalize_v3(bevp1->dir) == 0.0f) { + copy_v3_v3(bevp1->dir, bevp0->dir); + } } } } diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c index b11a3cb9457..1bce9ad8e35 100644 --- a/source/blender/blenkernel/intern/fcurve_driver.c +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -411,7 +411,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) /* Extract transform just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); + ob, pchan, NULL, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); /* ... and from that, we get our transform. */ copy_v3_v3(tmp_loc, mat[3]); @@ -437,7 +437,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) /* Extract transform just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); + ob, NULL, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); /* ... and from that, we get our transform. */ copy_v3_v3(tmp_loc, mat[3]); @@ -514,7 +514,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) /* Just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); + ob, pchan, NULL, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); } else { /* Specially calculate local matrix, since chan_mat is not valid @@ -541,7 +541,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) /* Just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); + ob, NULL, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); } else { /* Transforms to matrix. */ diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 98e83bfb789..f68a390db64 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -671,6 +671,8 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f); /* Default vertex mix. */ gpl->vertex_paint_opacity = 1.0f; + /* Enable onion skin. */ + gpl->onion_flag |= GP_LAYER_ONIONSKIN; } /* auto-name */ diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 09f9e9e891c..ac81e4a5470 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -531,6 +531,19 @@ void BKE_gpencil_modifier_set_error(GpencilModifierData *md, const char *_format } /** + * Check whether given modifier is not local (i.e. from linked data) when the object is a library + * override. + * + * \param gmd May be NULL, in which case we consider it as a non-local modifier case. + */ +bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const Object *ob, + const GpencilModifierData *gmd) +{ + return (ID_IS_OVERRIDE_LIBRARY(ob) && + (gmd == NULL || (gmd->flag & eGpencilModifierFlag_OverrideLibrary_Local) == 0)); +} + +/** * Link grease pencil modifier related IDs. * \param ob: Grease pencil object * \param walk: Walk option diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 9696d920640..6a852df95c6 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1999,12 +1999,12 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips) } /* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, false) == 0) { /* trying to add to the current failed (no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, false); + BKE_nlatrack_add_strip(nlt, strip, false); } /* ensure that strip has a name */ diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 0757cf791b7..8a699e31f37 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -57,6 +57,8 @@ #include "DRW_engine.h" +#include "RE_engine.h" + #include "MEM_guardedalloc.h" #include "BLO_read_write.h" @@ -175,6 +177,8 @@ static ViewLayer *view_layer_add(const char *name) view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */ view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z; view_layer->pass_alpha_threshold = 0.5f; + view_layer->cryptomatte_levels = 6; + view_layer->cryptomatte_flag = VIEW_LAYER_CRYPTOMATTE_ACCURATE; BKE_freestyle_config_init(&view_layer->freestyle_config); return view_layer; @@ -279,6 +283,8 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user) } } BLI_freelistN(&view_layer->drawdata); + BLI_freelistN(&view_layer->aovs); + view_layer->active_aov = NULL; MEM_SAFE_FREE(view_layer->stats); @@ -412,6 +418,28 @@ void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, Bas } /**************************** Copy View Layer and Layer Collections ***********************/ +static void layer_aov_copy_data(ViewLayer *view_layer_dst, + const ViewLayer *view_layer_src, + ListBase *aovs_dst, + const ListBase *aovs_src) +{ + if (aovs_src != NULL) { + BLI_duplicatelist(aovs_dst, aovs_src); + } + + ViewLayerAOV *aov_dst = aovs_dst->first; + const ViewLayerAOV *aov_src = aovs_src->first; + + while (aov_dst != NULL) { + BLI_assert(aov_src); + if (aov_src == view_layer_src->active_aov) { + view_layer_dst->active_aov = aov_dst; + } + + aov_dst = aov_dst->next; + aov_src = aov_src->next; + } +} static void layer_collections_copy_data(ViewLayer *view_layer_dst, const ViewLayer *view_layer_src, @@ -482,6 +510,10 @@ void BKE_view_layer_copy_data(Scene *scene_dst, LayerCollection *lc_scene_dst = view_layer_dst->layer_collections.first; lc_scene_dst->collection = scene_dst->master_collection; + BLI_listbase_clear(&view_layer_dst->aovs); + layer_aov_copy_data( + view_layer_dst, view_layer_src, &view_layer_dst->aovs, &view_layer_src->aovs); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus((ID *)view_layer_dst->mat_override); } @@ -1261,7 +1293,7 @@ void BKE_layer_collection_local_sync(ViewLayer *view_layer, const View3D *v3d) } /** - * Sync the local collection for all the view-ports. + * Sync the local collection for all the 3D Viewports. */ void BKE_layer_collection_local_sync_all(const Main *bmain) { @@ -1864,6 +1896,9 @@ void BKE_view_layer_blend_write(BlendWriter *writer, ViewLayer *view_layer) LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { BLO_write_struct(writer, FreestyleLineSet, fls); } + LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { + BLO_write_struct(writer, ViewLayerAOV, aov); + } write_layer_collections(writer, &view_layer->layer_collections); } @@ -1899,6 +1934,9 @@ void BKE_view_layer_blend_read_data(BlendDataReader *reader, ViewLayer *view_lay BLO_read_list(reader, &(view_layer->freestyle_config.modules)); BLO_read_list(reader, &(view_layer->freestyle_config.linesets)); + BLO_read_list(reader, &view_layer->aovs); + BLO_read_data_address(reader, &view_layer->active_aov); + BLI_listbase_clear(&view_layer->drawdata); view_layer->object_bases_array = NULL; view_layer->object_bases_hash = NULL; @@ -1952,3 +1990,129 @@ void BKE_view_layer_blend_read_lib(BlendLibReader *reader, Library *lib, ViewLay IDP_BlendReadLib(reader, view_layer->id_properties); } + +/* -------------------------------------------------------------------- */ +/** \name Shader AOV + * \{ */ + +static void viewlayer_aov_make_name_unique(ViewLayer *view_layer) +{ + ViewLayerAOV *aov = view_layer->active_aov; + if (aov == NULL) { + return; + } + BLI_uniquename( + &view_layer->aovs, aov, DATA_("AOV"), '.', offsetof(ViewLayerAOV, name), sizeof(aov->name)); +} + +static void viewlayer_aov_active_set(ViewLayer *view_layer, ViewLayerAOV *aov) +{ + if (aov != NULL) { + BLI_assert(BLI_findindex(&view_layer->aovs, aov) != -1); + view_layer->active_aov = aov; + } + else { + view_layer->active_aov = NULL; + } +} + +struct ViewLayerAOV *BKE_view_layer_add_aov(struct ViewLayer *view_layer) +{ + ViewLayerAOV *aov; + aov = MEM_callocN(sizeof(ViewLayerAOV), __func__); + aov->type = AOV_TYPE_COLOR; + BLI_strncpy(aov->name, DATA_("AOV"), sizeof(aov->name)); + BLI_addtail(&view_layer->aovs, aov); + viewlayer_aov_active_set(view_layer, aov); + viewlayer_aov_make_name_unique(view_layer); + return aov; +} + +void BKE_view_layer_remove_aov(ViewLayer *view_layer, ViewLayerAOV *aov) +{ + BLI_assert(BLI_findindex(&view_layer->aovs, aov) != -1); + BLI_assert(aov != NULL); + if (view_layer->active_aov == aov) { + if (aov->next) { + viewlayer_aov_active_set(view_layer, aov->next); + } + else { + viewlayer_aov_active_set(view_layer, aov->prev); + } + } + BLI_freelinkN(&view_layer->aovs, aov); +} + +void BKE_view_layer_set_active_aov(ViewLayer *view_layer, ViewLayerAOV *aov) +{ + viewlayer_aov_active_set(view_layer, aov); +} + +static void bke_view_layer_verify_aov_cb(void *userdata, + Scene *UNUSED(scene), + ViewLayer *UNUSED(view_layer), + const char *name, + int UNUSED(channels), + const char *UNUSED(chanid), + int UNUSED(type)) +{ + GHash *name_count = userdata; + void **value_p; + void *key = BLI_strdup(name); + + if (!BLI_ghash_ensure_p(name_count, key, &value_p)) { + *value_p = POINTER_FROM_INT(1); + } + else { + int value = POINTER_AS_INT(*value_p); + value++; + *value_p = POINTER_FROM_INT(value); + MEM_freeN(key); + } +} + +/* Update the naming and conflicts of the AOVs. + * + * Name must be unique between all AOVs. + * Conflicts with render passes will show a conflict icon. Reason is that switching a render + * engine or activating a render pass could lead to other conflicts that wouldn't be that clear + * for the user. */ +void BKE_view_layer_verify_aov(struct RenderEngine *engine, + struct Scene *scene, + struct ViewLayer *view_layer) +{ + viewlayer_aov_make_name_unique(view_layer); + + GHash *name_count = BLI_ghash_str_new(__func__); + RE_engine_update_render_passes( + engine, scene, view_layer, bke_view_layer_verify_aov_cb, name_count); + LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { + void **value_p = BLI_ghash_lookup(name_count, aov->name); + int count = POINTER_AS_INT(value_p); + SET_FLAG_FROM_TEST(aov->flag, count > 1, AOV_CONFLICT); + } + BLI_ghash_free(name_count, MEM_freeN, NULL); +} + +/* Check if the given view layer has at least one valid AOV. */ +bool BKE_view_layer_has_valid_aov(ViewLayer *view_layer) +{ + LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { + if ((aov->flag & AOV_CONFLICT) == 0) { + return true; + } + } + return false; +} + +ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene, struct ViewLayerAOV *aov) +{ + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + if (BLI_findindex(&view_layer->aovs, aov) != -1) { + return view_layer; + } + } + return NULL; +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/layer_test.cc b/source/blender/blenkernel/intern/layer_test.cc new file mode 100644 index 00000000000..e241c12d714 --- /dev/null +++ b/source/blender/blenkernel/intern/layer_test.cc @@ -0,0 +1,177 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 by Blender Foundation. + */ +#include "testing/testing.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_appdir.h" +#include "BKE_idtype.h" +#include "BKE_layer.h" + +#include "BLI_string.h" + +#include "RE_engine.h" + +#include "IMB_imbuf.h" + +#include "CLG_log.h" + +#include "RNA_access.h" + +namespace blender::bke::tests { + +TEST(view_layer, aov_unique_names) +{ + /* Set Up */ + CLG_init(); + BKE_appdir_init(); + IMB_init(); + RE_engines_init(); + + Scene scene = {{nullptr}}; + IDType_ID_SCE.init_data(&scene.id); + ViewLayer *view_layer = static_cast<ViewLayer *>(scene.view_layers.first); + + RenderEngineType *engine_type = RE_engines_find(scene.r.engine); + RenderEngine *engine = RE_engine_create(engine_type); + + EXPECT_FALSE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_EQ(view_layer->active_aov, nullptr); + + /* Add an AOV */ + ViewLayerAOV *aov1 = BKE_view_layer_add_aov(view_layer); + BKE_view_layer_verify_aov(engine, &scene, view_layer); + EXPECT_EQ(view_layer->active_aov, aov1); + EXPECT_TRUE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_FALSE((aov1->flag & AOV_CONFLICT) != 0); + + /* Add a second AOV */ + ViewLayerAOV *aov2 = BKE_view_layer_add_aov(view_layer); + BKE_view_layer_verify_aov(engine, &scene, view_layer); + EXPECT_EQ(view_layer->active_aov, aov2); + EXPECT_TRUE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_FALSE((aov1->flag & AOV_CONFLICT) != 0); + EXPECT_FALSE((aov2->flag & AOV_CONFLICT) != 0); + EXPECT_TRUE(STREQ(aov1->name, "AOV")); + EXPECT_TRUE(STREQ(aov2->name, "AOV.001")); + + /* Revert previous resolution */ + BLI_strncpy(aov2->name, "AOV", MAX_NAME); + BKE_view_layer_verify_aov(engine, &scene, view_layer); + EXPECT_TRUE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_FALSE((aov1->flag & AOV_CONFLICT) != 0); + EXPECT_FALSE((aov2->flag & AOV_CONFLICT) != 0); + EXPECT_TRUE(STREQ(aov1->name, "AOV")); + EXPECT_TRUE(STREQ(aov2->name, "AOV.001")); + + /* Resolve by removing AOV resolution */ + BKE_view_layer_remove_aov(view_layer, aov2); + aov2 = nullptr; + BKE_view_layer_verify_aov(engine, &scene, view_layer); + EXPECT_TRUE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_FALSE((aov1->flag & AOV_CONFLICT) != 0); + + /* Tear down */ + RE_engine_free(engine); + RE_engines_exit(); + IDType_ID_SCE.free_data(&scene.id); + IMB_exit(); + BKE_appdir_exit(); + CLG_exit(); +} + +static void test_render_pass_conflict(Scene *scene, + RenderEngine *engine, + ViewLayer *view_layer, + ViewLayerAOV *aov, + const char *render_pass_name, + const char *rna_prop_name) +{ + PointerRNA ptr; + RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &ptr); + RNA_boolean_set(&ptr, rna_prop_name, false); + + /* Rename to Conflicting name */ + BLI_strncpy(aov->name, render_pass_name, MAX_NAME); + BKE_view_layer_verify_aov(engine, scene, view_layer); + EXPECT_TRUE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_FALSE((aov->flag & AOV_CONFLICT) != 0); + EXPECT_TRUE(STREQ(aov->name, render_pass_name)); + + /* Activate render pass */ + RNA_boolean_set(&ptr, rna_prop_name, true); + BKE_view_layer_verify_aov(engine, scene, view_layer); + EXPECT_FALSE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_TRUE((aov->flag & AOV_CONFLICT) != 0); + EXPECT_TRUE(STREQ(aov->name, render_pass_name)); + + /* Deactivate render pass */ + RNA_boolean_set(&ptr, rna_prop_name, false); + BKE_view_layer_verify_aov(engine, scene, view_layer); + EXPECT_TRUE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_FALSE((aov->flag & AOV_CONFLICT) != 0); + EXPECT_TRUE(STREQ(aov->name, render_pass_name)); +} + +TEST(view_layer, aov_conflict) +{ + /* Set Up */ + CLG_init(); + BKE_appdir_init(); + IMB_init(); + RE_engines_init(); + + Scene scene = {{nullptr}}; + IDType_ID_SCE.init_data(&scene.id); + ViewLayer *view_layer = static_cast<ViewLayer *>(scene.view_layers.first); + + RenderEngineType *engine_type = RE_engines_find(scene.r.engine); + RenderEngine *engine = RE_engine_create(engine_type); + + EXPECT_FALSE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_EQ(view_layer->active_aov, nullptr); + + /* Add an AOV */ + ViewLayerAOV *aov = BKE_view_layer_add_aov(view_layer); + BKE_view_layer_verify_aov(engine, &scene, view_layer); + EXPECT_EQ(view_layer->active_aov, aov); + EXPECT_TRUE(BKE_view_layer_has_valid_aov(view_layer)); + EXPECT_FALSE((aov->flag & AOV_CONFLICT) != 0); + + test_render_pass_conflict(&scene, engine, view_layer, aov, "Depth", "use_pass_z"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "Normal", "use_pass_normal"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "Mist", "use_pass_mist"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "Shadow", "use_pass_shadow"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "AO", "use_pass_ambient_occlusion"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "Emit", "use_pass_emit"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "Env", "use_pass_environment"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "DiffDir", "use_pass_diffuse_direct"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "DiffCol", "use_pass_diffuse_color"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "GlossDir", "use_pass_glossy_direct"); + test_render_pass_conflict(&scene, engine, view_layer, aov, "GlossCol", "use_pass_glossy_color"); + + /* Tear down */ + RE_engine_free(engine); + RE_engines_exit(); + IDType_ID_SCE.free_data(&scene.id); + IMB_exit(); + BKE_appdir_exit(); + CLG_exit(); +} + +} // namespace blender::bke::tests diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 69e6535a59f..8542959d4b0 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -2017,7 +2017,7 @@ char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand if (found) { char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", name_esc); } } diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index 16733729be0..0aaca33124a 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -76,10 +76,10 @@ struct OrderedEdge { }; /* The map first contains an edge pointer and later an index. */ -typedef union OrigEdgeOrIndex { +union OrigEdgeOrIndex { const MEdge *original_edge; int index; -} OrigEdgeOrIndex; +}; using EdgeMap = Map<OrderedEdge, OrigEdgeOrIndex>; static void reserve_hash_maps(const Mesh *mesh, diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index c9bdaecfa2a..3496e05c6e5 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -574,6 +574,18 @@ bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int re return true; } +/** + * Check whether given modifier is not local (i.e. from linked data) when the object is a library + * override. + * + * \param md May be NULL, in which case we consider it as a non-local modifier case. + */ +bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md) +{ + return (ID_IS_OVERRIDE_LIBRARY(ob) && + (md == NULL || (md->flag & eModifierFlag_OverrideLibrary_Local) == 0)); +} + CDMaskLink *BKE_modifier_calc_data_masks(struct Scene *scene, Object *ob, ModifierData *md, diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 56bd83140bf..ebd9317fcf1 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -280,7 +280,7 @@ void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, ListBase *src, const int fl /* Add a NLA Track to the given AnimData * - prev: NLA-Track to add the new one after */ -NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev) +NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev, const bool is_liboverride) { NlaTrack *nlt; @@ -293,11 +293,15 @@ NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev) nlt = MEM_callocN(sizeof(NlaTrack), "NlaTrack"); /* set settings requiring the track to not be part of the stack yet */ - nlt->flag = NLATRACK_SELECTED; + nlt->flag = NLATRACK_SELECTED | NLATRACK_OVERRIDELIBRARY_LOCAL; nlt->index = BLI_listbase_count(&adt->nla_tracks); /* add track to stack, and make it the active one */ - if (prev) { + if (is_liboverride) { + for (; prev != NULL && (prev->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0; prev = prev->next) { + } + } + if (prev != NULL) { BLI_insertlinkafter(&adt->nla_tracks, prev, nlt); } else { @@ -359,7 +363,7 @@ NlaStrip *BKE_nlastrip_new(bAction *act) /* Add new NLA-strip to the top of the NLA stack - i.e. * into the last track if space, or a new one otherwise. */ -NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act) +NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act, const bool is_liboverride) { NlaStrip *strip; NlaTrack *nlt; @@ -376,12 +380,12 @@ NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act) } /* firstly try adding strip to last track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) { + if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip, is_liboverride) == 0) { /* trying to add to the last track failed (no track or no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); } /* automatically name it too */ @@ -1138,15 +1142,16 @@ void BKE_nlatrack_sort_strips(NlaTrack *nlt) /* Add the given NLA-Strip to the given NLA-Track, assuming that it * isn't currently attached to another one */ -bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip) +bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_liboverride) { /* sanity checks */ if (ELEM(NULL, nlt, strip)) { return false; } - /* do not allow adding strips if this track is locked */ - if (nlt->flag & NLATRACK_PROTECTED) { + /* Do not allow adding strips if this track is locked, or not a local one in liboverride case. */ + if (nlt->flag & NLATRACK_PROTECTED || + (is_liboverride && (nlt->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0)) { return false; } @@ -1186,6 +1191,18 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2]) return true; } +/** + * Check whether given NLA track is not local (i.e. from linked data) when the object is a library + * override. + * + * \param nlt May be NULL, in which case we consider it as a non-local track case. + */ +bool BKE_nlatrack_is_nonlocal_in_liboverride(const ID *id, const NlaTrack *nlt) +{ + return (ID_IS_OVERRIDE_LIBRARY(id) && + (nlt == NULL || (nlt->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0)); +} + /* NLA Strips -------------------------------------- */ /* Find the active NLA-strip within the given track */ @@ -1857,7 +1874,7 @@ bool BKE_nla_action_is_stashed(AnimData *adt, bAction *act) /* "Stash" an action (i.e. store it as a track/layer in the NLA, but non-contributing) * to retain it in the file for future uses */ -bool BKE_nla_action_stash(AnimData *adt) +bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride) { NlaTrack *prev_track = NULL; NlaTrack *nlt; @@ -1881,7 +1898,7 @@ bool BKE_nla_action_stash(AnimData *adt) } } - nlt = BKE_nlatrack_add(adt, prev_track); + nlt = BKE_nlatrack_add(adt, prev_track, is_liboverride); BLI_assert(nlt != NULL); /* We need to ensure that if there wasn't any previous instance, @@ -1901,7 +1918,7 @@ bool BKE_nla_action_stash(AnimData *adt) strip = BKE_nlastrip_new(adt->action); BLI_assert(strip != NULL); - BKE_nlatrack_add_strip(nlt, strip); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); BKE_nlastrip_validate_name(adt, strip); /* mark the stash track and strip so that they doesn't disturb the stack animation, @@ -1931,7 +1948,7 @@ bool BKE_nla_action_stash(AnimData *adt) * so no checks for this are performed. */ /* TODO: maybe we should have checks for this too... */ -void BKE_nla_action_pushdown(AnimData *adt) +void BKE_nla_action_pushdown(AnimData *adt, const bool is_liboverride) { NlaStrip *strip; const bool is_first = (adt) && (adt->nla_tracks.first == NULL); @@ -1952,7 +1969,7 @@ void BKE_nla_action_pushdown(AnimData *adt) } /* add a new NLA strip to the track, which references the active action */ - strip = BKE_nlastack_add_strip(adt, adt->action); + strip = BKE_nlastack_add_strip(adt, adt->action, is_liboverride); if (strip == NULL) { return; } @@ -2273,6 +2290,11 @@ void BKE_nla_blend_read_lib(BlendLibReader *reader, ID *id, ListBase *tracks) { /* we only care about the NLA strips inside the tracks */ LISTBASE_FOREACH (NlaTrack *, nlt, tracks) { + /* If linking from a library, clear 'local' library override flag. */ + if (id->lib != NULL) { + nlt->flag &= ~NLATRACK_OVERRIDELIBRARY_LOCAL; + } + blend_lib_read_nla_strips(reader, id, &nlt->strips); } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index b564a4c468b..31de95817fd 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2708,7 +2708,7 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user) char propname_esc[MAX_IDPROP_NAME * 2]; char prefix[MAX_IDPROP_NAME * 2]; - BLI_strescape(propname_esc, node->name, sizeof(propname_esc)); + BLI_str_escape(propname_esc, node->name, sizeof(propname_esc)); BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc); if (BKE_animdata_fix_paths_remove((ID *)ntree, prefix)) { diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 9a8c560f116..d5434710e23 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -829,13 +829,18 @@ static void make_duplis_instances_component(const DupliContext *ctx) size_to_mat4(scale_matrix, scales[i]); float rotation_matrix[4][4]; eul_to_mat4(rotation_matrix, rotations[i]); - float matrix[4][4]; - mul_m4_m4m4(matrix, rotation_matrix, scale_matrix); - copy_v3_v3(matrix[3], positions[i]); - mul_m4_m4_pre(matrix, ctx->object->obmat); + float instance_offset_matrix[4][4]; + mul_m4_m4m4(instance_offset_matrix, rotation_matrix, scale_matrix); + copy_v3_v3(instance_offset_matrix[3], positions[i]); + float matrix[4][4]; + mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix); make_dupli(ctx, object, matrix, i); - make_recursive_duplis(ctx, object, matrix, i); + + float space_matrix[4][4]; + mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat); + mul_m4_m4_pre(space_matrix, ctx->object->obmat); + make_recursive_duplis(ctx, object, space_matrix, i); } } diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 97bef99944a..355db8f0d60 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -1561,7 +1561,6 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) /* we only saved what was used */ space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */ } - space_outliner->treehash = NULL; space_outliner->tree.first = space_outliner->tree.last = NULL; space_outliner->runtime = NULL; } @@ -1825,10 +1824,8 @@ void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrAr while ((tselem = BLI_mempool_iterstep(&iter))) { BLO_read_id_address(reader, NULL, &tselem->id); } - if (space_outliner->treehash) { - /* rebuild hash table, because it depends on ids too */ - space_outliner->storeflag |= SO_TREESTORE_REBUILD; - } + /* rebuild hash table, because it depends on ids too */ + space_outliner->storeflag |= SO_TREESTORE_REBUILD; } break; } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e083f7ceec0..e5f9d59270e 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -3138,13 +3138,13 @@ void BKE_tracking_get_rna_path_for_track(const struct MovieTracking *tracking, { MovieTrackingObject *object = BKE_tracking_find_object_for_track(tracking, track); char track_name_esc[MAX_NAME * 2]; - BLI_strescape(track_name_esc, track->name, sizeof(track_name_esc)); + BLI_str_escape(track_name_esc, track->name, sizeof(track_name_esc)); if (object == NULL) { BLI_snprintf(rna_path, rna_path_len, "tracking.tracks[\"%s\"]", track_name_esc); } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"].tracks[\"%s\"]", @@ -3164,7 +3164,7 @@ void BKE_tracking_get_rna_path_prefix_for_track(const struct MovieTracking *trac } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"]", object_name_esc); } } @@ -3176,13 +3176,13 @@ void BKE_tracking_get_rna_path_for_plane_track(const struct MovieTracking *track { MovieTrackingObject *object = BKE_tracking_find_object_for_plane_track(tracking, plane_track); char track_name_esc[MAX_NAME * 2]; - BLI_strescape(track_name_esc, plane_track->name, sizeof(track_name_esc)); + BLI_str_escape(track_name_esc, plane_track->name, sizeof(track_name_esc)); if (object == NULL) { BLI_snprintf(rna_path, rna_path_len, "tracking.plane_tracks[\"%s\"]", track_name_esc); } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"].plane_tracks[\"%s\"]", @@ -3203,7 +3203,7 @@ void BKE_tracking_get_rna_path_prefix_for_plane_track( } else { char object_name_esc[MAX_NAME * 2]; - BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc)); + BLI_str_escape(object_name_esc, object->name, sizeof(object_name_esc)); BLI_snprintf(rna_path, rna_path_len, "tracking.objects[\"%s\"].plane_tracks", object_name_esc); } } diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 05d1e427c14..d5e878a9a75 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -34,7 +34,9 @@ #include "BLI_task.h" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "PIL_time.h" +#include "BKE_global.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" @@ -97,7 +99,7 @@ typedef struct AutoTrackContext { /* True when tracking backwards (from higher frame number to lower frame number.) */ bool is_backwards; - /* Movie clips used during the trackign process. */ + /* Movie clips used during the tracking process. */ int num_clips; AutoTrackClip autotrack_clips[MAX_ACCESSOR_CLIP]; @@ -180,7 +182,7 @@ static void libmv_frame_to_normalized_relative(const float frame_coord[2], /** \} */ /* -------------------------------------------------------------------- */ -/** \name Coversion of markers between Blender's DNA and Libmv. +/** \name Conversion of markers between Blender's DNA and Libmv. * \{ */ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track, @@ -702,7 +704,7 @@ bool BKE_autotrack_context_step(AutoTrackContext *context) /* -------------------------------------------------------------------- */ /** \name Context data synchronization. * - * Used to copy trackign result to Blender side, while the trackign is still happening in its + * Used to copy tracking result to Blender side, while the tracking is still happening in its * thread. * * \{ */ @@ -738,7 +740,7 @@ void BKE_autotrack_context_sync(AutoTrackContext *context) } BKE_tracking_marker_insert(track, &marker); - /* Insetr disabled marker at the end of tracked segment. + /* Insert disabled marker at the end of tracked segment. * When tracking forward the disabled marker is added at the next frame from the result, * when tracking backwards the marker is added at the previous frame. */ tracking_marker_insert_disabled(track, &marker, context->is_backwards, false); diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index eb57c28de09..ad2713b9977 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -615,88 +615,6 @@ MovieTrackingMarker *tracking_get_keyframed_marker(MovieTrackingTrack *track, /*********************** Frame accessr *************************/ -typedef struct AccessCacheKey { - int clip_index; - int frame; - int downscale; - libmv_InputMode input_mode; - bool has_region; - float region_min[2], region_max[2]; - int64_t transform_key; -} AccessCacheKey; - -static unsigned int accesscache_hashhash(const void *key_v) -{ - const AccessCacheKey *key = (const AccessCacheKey *)key_v; - /* TODP(sergey): Need better hashing here for faster frame access. */ - return key->clip_index << 16 | key->frame; -} - -static bool accesscache_hashcmp(const void *a_v, const void *b_v) -{ - const AccessCacheKey *a = (const AccessCacheKey *)a_v; - const AccessCacheKey *b = (const AccessCacheKey *)b_v; - if (a->clip_index != b->clip_index || a->frame != b->frame || a->downscale != b->downscale || - a->input_mode != b->input_mode || a->has_region != b->has_region || - a->transform_key != b->transform_key) { - return true; - } - /* If there is region applied, compare it. */ - if (a->has_region) { - if (!equals_v2v2(a->region_min, b->region_min) || !equals_v2v2(a->region_max, b->region_max)) { - return true; - } - } - return false; -} - -static void accesscache_construct_key(AccessCacheKey *key, - int clip_index, - int frame, - libmv_InputMode input_mode, - int downscale, - const libmv_Region *region, - int64_t transform_key) -{ - key->clip_index = clip_index; - key->frame = frame; - key->input_mode = input_mode; - key->downscale = downscale; - key->has_region = (region != NULL); - if (key->has_region) { - copy_v2_v2(key->region_min, region->min); - copy_v2_v2(key->region_max, region->max); - } - key->transform_key = transform_key; -} - -static void accesscache_put(TrackingImageAccessor *accessor, - int clip_index, - int frame, - libmv_InputMode input_mode, - int downscale, - const libmv_Region *region, - int64_t transform_key, - ImBuf *ibuf) -{ - AccessCacheKey key; - accesscache_construct_key(&key, clip_index, frame, input_mode, downscale, region, transform_key); - IMB_moviecache_put(accessor->cache, &key, ibuf); -} - -static ImBuf *accesscache_get(TrackingImageAccessor *accessor, - int clip_index, - int frame, - libmv_InputMode input_mode, - int downscale, - const libmv_Region *region, - int64_t transform_key) -{ - AccessCacheKey key; - accesscache_construct_key(&key, clip_index, frame, input_mode, downscale, region, transform_key); - return IMB_moviecache_get(accessor->cache, &key); -} - static ImBuf *accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor, int clip_index, int frame) @@ -776,33 +694,14 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, const libmv_Region *region, const libmv_FrameTransform *transform) { - ImBuf *ibuf, *orig_ibuf, *final_ibuf; - int64_t transform_key = 0; - if (transform != NULL) { - transform_key = libmv_frameAccessorgetTransformKey(transform); - } /* First try to get fully processed image from the cache. */ - BLI_spin_lock(&accessor->cache_lock); - ibuf = accesscache_get( - accessor, clip_index, frame, input_mode, downscale, region, transform_key); - BLI_spin_unlock(&accessor->cache_lock); - if (ibuf != NULL) { - CACHE_PRINTF("Used cached buffer for frame %d\n", frame); - /* This is a little heuristic here: if we re-used image once, this is - * a high probability of the image to be related to a keyframe matched - * reference image. Those images we don't want to be thrown away because - * if we toss them out we'll be re-calculating them at the next - * iteration. - */ - ibuf->userflags |= IB_PERSISTENT; - return ibuf; - } CACHE_PRINTF("Calculate new buffer for frame %d\n", frame); /* And now we do postprocessing of the original frame. */ - orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame); + ImBuf *orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame); if (orig_ibuf == NULL) { return NULL; } + ImBuf *final_ibuf; /* Cut a region if requested. */ if (region != NULL) { int width = region->max[0] - region->min[0], height = region->max[1] - region->min[1]; @@ -902,11 +801,6 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, final_ibuf = IMB_dupImBuf(orig_ibuf); } IMB_freeImBuf(orig_ibuf); - BLI_spin_lock(&accessor->cache_lock); - /* Put final buffer to cache. */ - accesscache_put( - accessor, clip_index, frame, input_mode, downscale, region, transform_key, final_ibuf); - BLI_spin_unlock(&accessor->cache_lock); return final_ibuf; } @@ -1016,9 +910,6 @@ TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR BLI_assert(num_clips <= MAX_ACCESSOR_CLIP); - accessor->cache = IMB_moviecache_create( - "frame access cache", sizeof(AccessCacheKey), accesscache_hashhash, accesscache_hashcmp); - memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *)); accessor->num_clips = num_clips; @@ -1040,7 +931,6 @@ TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR void tracking_image_accessor_destroy(TrackingImageAccessor *accessor) { - IMB_moviecache_free(accessor->cache); libmv_FrameAccessorDestroy(accessor->libmv_accessor); BLI_spin_end(&accessor->cache_lock); MEM_freeN(accessor->tracks); diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h index 64db84d5ac3..c8e7fea6601 100644 --- a/source/blender/blenkernel/tracking_private.h +++ b/source/blender/blenkernel/tracking_private.h @@ -131,8 +131,6 @@ struct libmv_FrameAccessor; #define MAX_ACCESSOR_CLIP 64 typedef struct TrackingImageAccessor { - struct MovieCache *cache; - struct MovieClip *clips[MAX_ACCESSOR_CLIP]; int num_clips; diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 2d745e63764..096e7818013 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -85,8 +85,11 @@ size_t BLI_vsnprintf_rlen(char *__restrict buffer, char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2); -size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL(); +size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) + ATTR_NONNULL(); +const char *BLI_str_escape_find_quote(const char *str) ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc index 64ea25ccc90..85a6ab42013 100644 --- a/source/blender/blenlib/intern/mesh_intersect.cc +++ b/source/blender/blenlib/intern/mesh_intersect.cc @@ -1055,36 +1055,36 @@ static std::ostream &operator<<(std::ostream &os, const CoplanarClusterInfo &cli enum ITT_value_kind { INONE, IPOINT, ISEGMENT, ICOPLANAR }; struct ITT_value { - enum ITT_value_kind kind; mpq3 p1; /* Only relevant for IPOINT and ISEGMENT kind. */ mpq3 p2; /* Only relevant for ISEGMENT kind. */ int t_source; /* Index of the source triangle that intersected the target one. */ + enum ITT_value_kind kind; - ITT_value() : kind(INONE), t_source(-1) + ITT_value() : t_source(-1), kind(INONE) { } - ITT_value(ITT_value_kind k) : kind(k), t_source(-1) + ITT_value(ITT_value_kind k) : t_source(-1), kind(k) { } - ITT_value(ITT_value_kind k, int tsrc) : kind(k), t_source(tsrc) + ITT_value(ITT_value_kind k, int tsrc) : t_source(tsrc), kind(k) { } - ITT_value(ITT_value_kind k, const mpq3 &p1) : kind(k), p1(p1), t_source(-1) + ITT_value(ITT_value_kind k, const mpq3 &p1) : p1(p1), t_source(-1), kind(k) { } ITT_value(ITT_value_kind k, const mpq3 &p1, const mpq3 &p2) - : kind(k), p1(p1), p2(p2), t_source(-1) + : p1(p1), p2(p2), t_source(-1), kind(k) { } ITT_value(const ITT_value &other) - : kind(other.kind), p1(other.p1), p2(other.p2), t_source(other.t_source) + : p1(other.p1), p2(other.p2), t_source(other.t_source), kind(other.kind) { } ITT_value(ITT_value &&other) noexcept - : kind(other.kind), - p1(std::move(other.p1)), + : p1(std::move(other.p1)), p2(std::move(other.p2)), - t_source(other.t_source) + t_source(other.t_source), + kind(other.kind) { } ~ITT_value() @@ -2178,8 +2178,8 @@ static void calc_overlap_itts_range_func(void *__restrict userdata, } /** - * Fill in itt_map with the vector of ITT_values that result from intersecting the triangles in ov. - * Use a canonical order for triangles: (a,b) where a < b. + * Fill in itt_map with the vector of ITT_values that result from intersecting the triangles in + * ov. Use a canonical order for triangles: (a,b) where a < b. */ static void calc_overlap_itts(Map<std::pair<int, int>, ITT_value> &itt_map, const IMesh &tm, diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 758feef6093..74bbe59bc04 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -264,6 +264,11 @@ void BLI_path_normalize(const char *relabase, char *path) */ void BLI_path_normalize_dir(const char *relabase, char *dir) { + /* Would just create an unexpected "/" path, just early exit entirely. */ + if (dir[0] == '\0') { + return; + } + BLI_path_normalize(relabase, dir); BLI_path_slash_ensure(dir); } diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc index c61e17e6627..8dbfffbad20 100644 --- a/source/blender/blenlib/intern/rand.cc +++ b/source/blender/blenlib/intern/rand.cc @@ -21,10 +21,10 @@ * \ingroup bli */ -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> +#include <cmath> +#include <cstdlib> +#include <cstring> +#include <ctime> #include "MEM_guardedalloc.h" diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 02d12d2df9b..b0d87838d06 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -317,92 +317,135 @@ char *BLI_sprintfN(const char *__restrict format, ...) return n; } -/* match pythons string escaping, assume double quotes - (") - * TODO: should be used to create RNA animation paths. - * TODO: support more fancy string escaping. current code is primitive - * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() - * which is a useful reference. */ -size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +/** + * This roughly matches C and Python's string escaping with double quotes - `"`. + * + * Since every character may need escaping, + * it's common to create a buffer twice as large as the input. + * + * \param dst: The destination string, at least \a dst_maxncpy, typically `(strlen(src) * 2) + 1`. + * \param src: The un-escaped source string. + * \param dst_maxncpy: The maximum number of bytes allowable to copy. + * + * \note This is used for creating animation paths in blend files. + */ +size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) { - size_t len = 0; - BLI_assert(maxncpy != 0); + BLI_assert(dst_maxncpy != 0); - while (len < maxncpy) { - switch (*src) { - case '\0': - goto escape_finish; - case '\\': - case '"': - ATTR_FALLTHROUGH; - - /* less common but should also be support */ - case '\t': - case '\n': - case '\r': - if (len + 1 < maxncpy) { - *dst++ = '\\'; - len++; - } - else { - /* not enough space to escape */ - break; - } - ATTR_FALLTHROUGH; - default: - *dst = *src; + size_t len = 0; + for (; (len < dst_maxncpy) && (*src != '\0'); dst++, src++, len++) { + char c = *src; + if (ELEM(c, '\\', '"') || /* Use as-is. */ + ((c == '\t') && ((void)(c = 't'), true)) || /* Tab. */ + ((c == '\n') && ((void)(c = 'n'), true)) || /* Newline. */ + ((c == '\r') && ((void)(c = 'r'), true)) || /* Carriage return. */ + ((c == '\a') && ((void)(c = 'a'), true)) || /* Bell. */ + ((c == '\b') && ((void)(c = 'b'), true)) || /* Backspace. */ + ((c == '\f') && ((void)(c = 'f'), true))) /* Form-feed. */ + { + if (UNLIKELY(len + 1 >= dst_maxncpy)) { + /* Not enough space to escape. */ break; + } + *dst++ = '\\'; + len++; } - dst++; - src++; - len++; + *dst = c; } - -escape_finish: - *dst = '\0'; return len; } /** - * Makes a copy of the text within the "" that appear after some text 'blahblah' - * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" + * This roughly matches C and Python's string escaping with double quotes - `"`. + * + * The destination will never be larger than the source, it will either be the same + * or up to half when all characters are escaped. + * + * \param dst: The destination string, at least the size of `strlen(src) + 1`. + * \param src: The escaped source string. + * \param dst_maxncpy: The maximum number of bytes allowable to copy. * - * - str: is the entire string to chop - * - prefix: is the part of the string to leave out + * \note This is used for for parsing animation paths in blend files. + */ +size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) +{ + size_t len = 0; + for (size_t i = 0; i < src_maxncpy && (*src != '\0'); i++, src++) { + char c = *src; + if (c == '\\') { + char c_next = *(src + 1); + if (((c_next == '"') && ((void)(c = '"'), true)) || /* Quote. */ + ((c_next == '\\') && ((void)(c = '\\'), true)) || /* Backslash. */ + ((c_next == 't') && ((void)(c = '\t'), true)) || /* Tab. */ + ((c_next == 'n') && ((void)(c = '\n'), true)) || /* Newline. */ + ((c_next == 'r') && ((void)(c = '\r'), true)) || /* Carriage return. */ + ((c_next == 'a') && ((void)(c = '\a'), true)) || /* Bell. */ + ((c_next == 'b') && ((void)(c = '\b'), true)) || /* Backspace. */ + ((c_next == 'f') && ((void)(c = '\f'), true))) /* Form-feed. */ + { + i++; + src++; + } + } + + dst[len++] = c; + } + dst[len] = 0; + return len; +} + +/** + * Find the first un-escaped quote in the string (to find the end of the string). + */ +const char *BLI_str_escape_find_quote(const char *str) +{ + bool escape = false; + while (*str && (*str != '"' || escape)) { + /* A pair of back-slashes represents a single back-slash, + * only use a single back-slash for escaping. */ + escape = (escape == false) && (*str == '\\'); + str++; + } + return (*str == '"') ? str : NULL; +} + +/** + * Makes a copy of the text within the "" that appear after some text `blahblah`. + * i.e. for string `pose["apples"]` with prefix `pose[`, it will return `apples`. * - * Assume that the strings returned must be freed afterwards, and that the inputs will contain - * data we want... + * \param str: is the entire string to chop. + * \param prefix: is the part of the string to step over. * - * \return the offset and a length so as to avoid doing an allocation. + * Assume that the strings returned must be freed afterwards, + * and that the inputs will contain data we want. */ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { - const char *startMatch, *endMatch; + const char *start_match, *end_match; - /* get the starting point (i.e. where prefix starts, and add prefixLen+1 + /* get the starting point (i.e. where prefix starts, and add prefix_len+1 * to it to get be after the first " */ - startMatch = strstr(str, prefix); - if (startMatch) { - const size_t prefixLen = strlen(prefix); - startMatch += prefixLen + 1; + start_match = strstr(str, prefix); + if (start_match) { + const size_t prefix_len = strlen(prefix); + start_match += prefix_len + 1; /* get the end point (i.e. where the next occurrence of " is after the starting point) */ - - endMatch = startMatch; - while ((endMatch = strchr(endMatch, '"'))) { - if (LIKELY(*(endMatch - 1) != '\\')) { - break; + end_match = BLI_str_escape_find_quote(start_match); + if (end_match) { + const size_t unescaped_len = (size_t)(end_match - start_match); + char *result = MEM_mallocN(sizeof(char) * (unescaped_len + 1), __func__); + const size_t escaped_len = BLI_str_unescape(result, start_match, unescaped_len); + if (escaped_len != unescaped_len) { + result = MEM_reallocN(result, sizeof(char) * (escaped_len + 1)); } - endMatch++; - } - - if (endMatch) { - /* return the slice indicated */ - return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch)); + return result; } } - return BLI_strdupn("", 0); + return NULL; } /** diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index 1a119e135d5..dfed24da2d9 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -20,8 +20,8 @@ * Task pool to run tasks in parallel. */ +#include <cstdlib> #include <memory> -#include <stdlib.h> #include <utility> #include "MEM_guardedalloc.h" @@ -149,13 +149,13 @@ class TBBTaskGroup : public tbb::task_group { /* Task Pool */ -typedef enum TaskPoolType { +enum TaskPoolType { TASK_POOL_TBB, TASK_POOL_TBB_SUSPENDED, TASK_POOL_NO_THREADS, TASK_POOL_BACKGROUND, TASK_POOL_BACKGROUND_SERIAL, -} TaskPoolType; +}; struct TaskPool { TaskPoolType type; diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc index 229129bd088..c2498de1af8 100644 --- a/source/blender/blenlib/intern/task_range.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -20,7 +20,7 @@ * Task parallel range functions. */ -#include <stdlib.h> +#include <cstdlib> #include "MEM_guardedalloc.h" diff --git a/source/blender/blenlib/intern/threads.cc b/source/blender/blenlib/intern/threads.cc index a2b1a12c783..0b88cf53442 100644 --- a/source/blender/blenlib/intern/threads.cc +++ b/source/blender/blenlib/intern/threads.cc @@ -21,9 +21,9 @@ * \ingroup bli */ -#include <errno.h> -#include <stdlib.h> -#include <string.h> +#include <cerrno> +#include <cstdlib> +#include <cstring> #include "MEM_guardedalloc.h" @@ -132,13 +132,13 @@ static int num_threads_override = 0; /* just a max for security reasons */ #define RE_MAX_THREAD BLENDER_MAX_THREADS -typedef struct ThreadSlot { +struct ThreadSlot { struct ThreadSlot *next, *prev; void *(*do_thread)(void *); void *callerdata; pthread_t pthread; int avail; -} ThreadSlot; +}; void BLI_threadapi_init(void) { diff --git a/source/blender/blenlib/tests/BLI_array_store_test.cc b/source/blender/blenlib/tests/BLI_array_store_test.cc index ff050ce24db..8bbd109fb81 100644 --- a/source/blender/blenlib/tests/BLI_array_store_test.cc +++ b/source/blender/blenlib/tests/BLI_array_store_test.cc @@ -32,11 +32,11 @@ static void print_mem_saved(const char *id, const BArrayStore *bs) /* -------------------------------------------------------------------- */ /* Test Chunks (building data from list of chunks) */ -typedef struct TestChunk { +struct TestChunk { struct TestChunk *next, *prev; const void *data; size_t data_len; -} TestChunk; +}; static TestChunk *testchunk_list_add(ListBase *lb, const void *data, size_t data_len) { @@ -111,14 +111,14 @@ static char *testchunk_as_data_array(TestChunk **tc_array, int tc_array_len, siz /* Test Buffer */ /* API to handle local allocation of data so we can compare it with the data in the array_store */ -typedef struct TestBuffer { +struct TestBuffer { struct TestBuffer *next, *prev; const void *data; size_t data_len; /* for reference */ BArrayState *state; -} TestBuffer; +}; static TestBuffer *testbuffer_list_add(ListBase *lb, const void *data, size_t data_len) { diff --git a/source/blender/blenlib/tests/BLI_expr_pylike_eval_test.cc b/source/blender/blenlib/tests/BLI_expr_pylike_eval_test.cc index 390f687dbd1..e9ca3c68a71 100644 --- a/source/blender/blenlib/tests/BLI_expr_pylike_eval_test.cc +++ b/source/blender/blenlib/tests/BLI_expr_pylike_eval_test.cc @@ -2,7 +2,7 @@ #include "testing/testing.h" -#include <string.h> +#include <cstring> #include "BLI_expr_pylike_eval.h" #include "BLI_math.h" diff --git a/source/blender/blenlib/tests/BLI_heap_simple_test.cc b/source/blender/blenlib/tests/BLI_heap_simple_test.cc index f3a65125eeb..97644fc26ab 100644 --- a/source/blender/blenlib/tests/BLI_heap_simple_test.cc +++ b/source/blender/blenlib/tests/BLI_heap_simple_test.cc @@ -1,7 +1,7 @@ /* Apache License, Version 2.0 */ #include "testing/testing.h" -#include <string.h> +#include <cstring> #include "MEM_guardedalloc.h" diff --git a/source/blender/blenlib/tests/BLI_heap_test.cc b/source/blender/blenlib/tests/BLI_heap_test.cc index 8b207c17c84..b8fc62e46ca 100644 --- a/source/blender/blenlib/tests/BLI_heap_test.cc +++ b/source/blender/blenlib/tests/BLI_heap_test.cc @@ -1,7 +1,7 @@ /* Apache License, Version 2.0 */ #include "testing/testing.h" -#include <string.h> +#include <cstring> #include "MEM_guardedalloc.h" diff --git a/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc b/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc index f2ae121e8ae..e9810aed179 100644 --- a/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc +++ b/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc @@ -37,8 +37,8 @@ TEST(LockfreeLinkList, InsertMultiple) LockfreeLinkNode nodes[num_nodes]; BLI_linklist_lockfree_init(&list); /* Insert all the nodes. */ - for (int i = 0; i < num_nodes; ++i) { - BLI_linklist_lockfree_insert(&list, &nodes[i]); + for (LockfreeLinkNode &node : nodes) { + BLI_linklist_lockfree_insert(&list, &node); } /* Check head and tail. */ EXPECT_EQ(list.head, &list.dummy_node); diff --git a/source/blender/blenlib/tests/BLI_math_rotation_test.cc b/source/blender/blenlib/tests/BLI_math_rotation_test.cc index 1b1c4ef24a1..02257ba83dd 100644 --- a/source/blender/blenlib/tests/BLI_math_rotation_test.cc +++ b/source/blender/blenlib/tests/BLI_math_rotation_test.cc @@ -4,7 +4,7 @@ #include "BLI_math_rotation.h" -#include <math.h> +#include <cmath> /* Test that quaternion converts to itself via matrix. */ static void test_quat_to_mat_to_quat(float w, float x, float y, float z) diff --git a/source/blender/blenlib/tests/BLI_stack_test.cc b/source/blender/blenlib/tests/BLI_stack_test.cc index 211916e3193..1fef5998b99 100644 --- a/source/blender/blenlib/tests/BLI_stack_test.cc +++ b/source/blender/blenlib/tests/BLI_stack_test.cc @@ -1,7 +1,7 @@ /* Apache License, Version 2.0 */ #include "testing/testing.h" -#include <string.h> +#include <cstring> #include "BLI_array.h" #include "BLI_stack.h" diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 58135adbcca..88cecaa5fee 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -27,14 +27,14 @@ TEST(string, StrPartition) { const char delim[] = {'-', '.', '_', '~', '\\', '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "mat.e-r_ial"; /* "mat.e-r_ial" -> "mat", '.', "e-r_ial", 3 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 3); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 3); EXPECT_EQ(&str[3], sep); EXPECT_STREQ("e-r_ial", suf); } @@ -44,8 +44,8 @@ TEST(string, StrPartition) const char *str = ".mate-rial--"; /* ".mate-rial--" -> "", '.', "mate-rial--", 0 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("mate-rial--", suf); } @@ -54,8 +54,8 @@ TEST(string, StrPartition) const char *str = ".__.--_"; /* ".__.--_" -> "", '.', "__.--_", 0 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("__.--_", suf); } @@ -64,8 +64,8 @@ TEST(string, StrPartition) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -74,8 +74,8 @@ TEST(string, StrPartition) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_partition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_partition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -86,14 +86,14 @@ TEST(string, StrRPartition) { const char delim[] = {'-', '.', '_', '~', '\\', '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "mat.e-r_ial"; /* "mat.e-r_ial" -> "mat.e-r", '_', "ial", 7 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 7); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 7); EXPECT_EQ(&str[7], sep); EXPECT_STREQ("ial", suf); } @@ -103,8 +103,8 @@ TEST(string, StrRPartition) const char *str = ".mate-rial--"; /* ".mate-rial--" -> ".mate-rial-", '-', "", 11 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 11); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 11); EXPECT_EQ(&str[11], sep); EXPECT_STREQ("", suf); } @@ -113,8 +113,8 @@ TEST(string, StrRPartition) const char *str = ".__.--_"; /* ".__.--_" -> ".__.--", '_', "", 6 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 6); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 6); EXPECT_EQ(&str[6], sep); EXPECT_STREQ("", suf); } @@ -123,8 +123,8 @@ TEST(string, StrRPartition) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -133,8 +133,8 @@ TEST(string, StrRPartition) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_rpartition(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_rpartition(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -145,7 +145,7 @@ TEST(string, StrPartitionEx) { const char delim[] = {'-', '.', '_', '~', '\\', '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; /* Only considering 'from_right' cases here. */ @@ -153,8 +153,8 @@ TEST(string, StrPartitionEx) const char *str = "mat.e-r_ia.l"; /* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */ - pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 5); + pre_len = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 5); EXPECT_EQ(&str[5], sep); EXPECT_STREQ("r_ia.l", suf); } @@ -164,8 +164,8 @@ TEST(string, StrPartitionEx) const char *str = "mate.rial"; /* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */ - pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 4); + pre_len = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 4); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -176,14 +176,14 @@ TEST(string, StrPartitionUtf8) { const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial"; /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 2); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 2); EXPECT_EQ(&str[2], sep); EXPECT_STREQ("te-r\xe2\x98\xafial", suf); } @@ -193,8 +193,8 @@ TEST(string, StrPartitionUtf8) const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1"; /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "", '\xe2\x98\xaf', "mate-rial-\xc3\xb1", 0 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ("mate-rial-\xc3\xb1", suf); } @@ -203,8 +203,8 @@ TEST(string, StrPartitionUtf8) const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1"; /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "", '\xe2\x98\xaf', ".\xc3\xb1_.--\xc3\xb1", 0 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(&str[0], sep); EXPECT_STREQ(".\xc3\xb1_.--\xc3\xb1", suf); } @@ -213,8 +213,8 @@ TEST(string, StrPartitionUtf8) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -223,8 +223,8 @@ TEST(string, StrPartitionUtf8) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -235,14 +235,14 @@ TEST(string, StrRPartitionUtf8) { const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; { const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial"; /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "mat\xc3\xb1te-r", '\xe2\x98\xaf', "ial", 8 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(&str[8], sep); EXPECT_STREQ("ial", suf); } @@ -252,8 +252,8 @@ TEST(string, StrRPartitionUtf8) const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1"; /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "\xe2\x98\xafmate-rial-", '\xc3\xb1', "", 13 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 13); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 13); EXPECT_EQ(&str[13], sep); EXPECT_STREQ("", suf); } @@ -262,8 +262,8 @@ TEST(string, StrRPartitionUtf8) const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1"; /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "\xe2\x98\xaf.\xc3\xb1_.--", '\xc3\xb1', "", 10 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 10); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 10); EXPECT_EQ(&str[10], sep); EXPECT_STREQ("", suf); } @@ -272,8 +272,8 @@ TEST(string, StrRPartitionUtf8) const char *str = ""; /* "" -> "", NULL, NULL, 0 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 0); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 0); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -282,8 +282,8 @@ TEST(string, StrRPartitionUtf8) const char *str = "material"; /* "material" -> "material", NULL, NULL, 8 */ - pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf); - EXPECT_EQ(pre_ln, 8); + pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf); + EXPECT_EQ(pre_len, 8); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -294,7 +294,7 @@ TEST(string, StrPartitionExUtf8) { const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; - size_t pre_ln; + size_t pre_len; /* Only considering 'from_right' cases here. */ @@ -303,8 +303,8 @@ TEST(string, StrPartitionExUtf8) /* "ma\xc3\xb1te-r\xe2\x98\xafial" over * "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */ - pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 2); + pre_len = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 2); EXPECT_EQ(&str[2], sep); EXPECT_STREQ("te-r\xe2\x98\xafial", suf); } @@ -314,8 +314,8 @@ TEST(string, StrPartitionExUtf8) const char *str = "mate\xe2\x98\xafrial"; /* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */ - pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true); - EXPECT_EQ(pre_ln, 4); + pre_len = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true); + EXPECT_EQ(pre_len, 4); EXPECT_EQ(sep, (void *)nullptr); EXPECT_EQ(suf, (void *)nullptr); } @@ -802,3 +802,76 @@ TEST_F(StringCasecmpNatural, TextAndNumbers) testReturnsLessThanZeroForAll(negative); testReturnsMoreThanZeroForAll(positive); } + +/* BLI_str_escape, BLI_str_unescape */ + +class StringEscape : public testing::Test { + protected: + StringEscape() + { + } + + using CompareWordsArray = vector<std::array<const char *, 2>>; + + void testEscapeWords(const CompareWordsArray &items) + { + size_t dst_test_len; + char dst_test[64]; + for (const auto &item : items) { + /* Escape the string. */ + dst_test_len = BLI_str_escape(dst_test, item[0], SIZE_MAX); + EXPECT_STREQ(dst_test, item[1]); + EXPECT_EQ(dst_test_len, strlen(dst_test)); + /* Escape back. */ + dst_test_len = BLI_str_unescape(dst_test, item[1], strlen(item[1])); + EXPECT_STREQ(dst_test, item[0]); + EXPECT_EQ(dst_test_len, strlen(dst_test)); + } + } +}; + +TEST_F(StringEscape, Simple) +{ + const CompareWordsArray equal{ + {"", ""}, + {"/", "/"}, + {"'", "'"}, + {"?", "?"}, + }; + + const CompareWordsArray escaped{ + {"\\", "\\\\"}, + {"A\\", "A\\\\"}, + {"\\A", "\\\\A"}, + {"A\\B", "A\\\\B"}, + {"?", "?"}, + {"\"\\", "\\\"\\\\"}, + {"\\\"", "\\\\\\\""}, + {"\"\\\"", "\\\"\\\\\\\""}, + + {"\"\"\"", "\\\"\\\"\\\""}, + {"\\\\\\", "\\\\\\\\\\\\"}, + }; + + testEscapeWords(equal); + testEscapeWords(escaped); +} + +TEST_F(StringEscape, Control) +{ + const CompareWordsArray escaped{ + {"\n", "\\n"}, + {"\r", "\\r"}, + {"\t", "\\t"}, + {"\a", "\\a"}, + {"\b", "\\b"}, + {"\f", "\\f"}, + {"A\n", "A\\n"}, + {"\nA", "\\nA"}, + {"\n\r\t\a\b\f", "\\n\\r\\t\\a\\b\\f"}, + {"\n_\r_\t_\a_\b_\f", "\\n_\\r_\\t_\\a_\\b_\\f"}, + {"\n\\\r\\\t\\\a\\\b\\\f", "\\n\\\\\\r\\\\\\t\\\\\\a\\\\\\b\\\\\\f"}, + }; + + testEscapeWords(escaped); +} diff --git a/source/blender/blenlib/tests/BLI_task_test.cc b/source/blender/blenlib/tests/BLI_task_test.cc index 2a3fddf5e3d..fce3e56d105 100644 --- a/source/blender/blenlib/tests/BLI_task_test.cc +++ b/source/blender/blenlib/tests/BLI_task_test.cc @@ -1,7 +1,7 @@ /* Apache License, Version 2.0 */ #include "testing/testing.h" -#include <string.h> +#include <cstring> #include "atomic_ops.h" diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c index 2848aac2c77..c281e2fa643 100644 --- a/source/blender/blenloader/intern/blend_validate.c +++ b/source/blender/blenloader/intern/blend_validate.c @@ -148,7 +148,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports) } } - BLI_linklist_free(names, free); + BLI_linklist_freeN(names); } BLO_blendhandle_close(bh); diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 7a527b82e9f..1aecba5ba90 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -134,7 +134,7 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) * \param bh: The blendhandle to access. * \param ofblocktype: The type of names to get. * \param tot_names: The length of the returned list. - * \return A BLI_linklist of strings. The string links should be freed with malloc. + * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN(). */ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, int *tot_names) { @@ -147,7 +147,7 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, if (bhead->code == ofblocktype) { const char *idname = blo_bhead_id_name(fd, bhead); - BLI_linklist_prepend(&names, strdup(idname + 2)); + BLI_linklist_prepend(&names, BLI_strdup(idname + 2)); tot++; } else if (bhead->code == ENDB) { @@ -254,7 +254,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to * (e.g. "Scene", "Mesh", "Light", etc.). * * \param bh: The blendhandle to access. - * \return A BLI_linklist of strings. The string links should be freed with malloc. + * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN(). */ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) { @@ -272,7 +272,7 @@ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) const char *str = BKE_idtype_idcode_to_name(bhead->code); if (BLI_gset_add(gathered, (void *)str)) { - BLI_linklist_prepend(&names, strdup(str)); + BLI_linklist_prepend(&names, BLI_strdup(str)); } } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2c10dd446f1..9ce767b7ce1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2834,10 +2834,8 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, tselem->id = NULL; } } - if (space_outliner->treehash) { - /* rebuild hash table, because it depends on ids too */ - space_outliner->storeflag |= SO_TREESTORE_REBUILD; - } + /* rebuild hash table, because it depends on ids too */ + space_outliner->storeflag |= SO_TREESTORE_REBUILD; } } else if (sl->spacetype == SPACE_NODE) { diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 9278ff51b8d..a98e7c46f10 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -181,7 +181,7 @@ static void seq_convert_transform_crop(const Scene *scene, /* Convert offset animation, but only if crop is not used. */ if ((seq->flag & use_transform_flag) != 0 && (seq->flag & use_crop_flag) == 0) { char name_esc[(sizeof(seq->name) - 2) * 2], *path; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_x", name_esc); seq_convert_transform_animation(scene, path, image_size_x); @@ -408,7 +408,7 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) const size_t node_name_escaped_max_length = (node_name_length * 2); char *node_name_escaped = MEM_mallocN(node_name_escaped_max_length + 1, "escaped name"); - BLI_strescape(node_name_escaped, node->name, node_name_escaped_max_length); + BLI_str_escape(node_name_escaped, node->name, node_name_escaped_max_length); char *rna_path_prefix = BLI_sprintfN("nodes[\"%s\"].inputs", node_name_escaped); BKE_animdata_fix_paths_rename_all_ex( @@ -483,6 +483,13 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) } } } + + /* Wet Paint Radius Factor */ + for (Brush *br = bmain->brushes.first; br; br = br->id.next) { + if (br->ob_mode & OB_MODE_SCULPT && br->wet_paint_radius_factor == 0.0f) { + br->wet_paint_radius_factor = 1.0f; + } + } } static void panels_remove_x_closed_flag_recursive(Panel *panel) @@ -1164,17 +1171,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - "versioning_userdef.c", #blo_do_versions_userdef - * - "versioning_userdef.c", #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ + if (!MAIN_VERSION_ATLEAST(bmain, 292, 5)) { /* Initialize the opacity of the overlay wireframe */ if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "wireframe_opacity")) { for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { @@ -1223,5 +1220,28 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) LISTBASE_FOREACH (PointCloud *, pointcloud, &bmain->pointclouds) { do_versions_point_attribute_names(&pointcloud->pdata); } + + /* Cryptomatte render pass */ + if (!DNA_struct_elem_find(fd->filesdna, "ViewLayer", "short", "cryptomatte_levels")) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + view_layer->cryptomatte_levels = 6; + view_layer->cryptomatte_flag = VIEW_LAYER_CRYPTOMATTE_ACCURATE; + } + } + } + } + + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #blo_do_versions_userdef + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ } } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index f9050183dda..7bc11317bb4 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -246,6 +246,19 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) FROM_DEFAULT_V4_UCHAR(space_graph.vertex_active); } + if (!USER_VERSION_ATLEAST(292, 5)) { + for (int i = 0; i < COLLECTION_COLOR_TOT; ++i) { + FROM_DEFAULT_V4_UCHAR(collection_color[i].color); + } + FROM_DEFAULT_V4_UCHAR(space_sequencer.row_alternate); + FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_geometry); + FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_attribute); + } + + if (!USER_VERSION_ATLEAST(292, 6)) { + FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_shader); + } + /** * Versioning code until next subversion bump goes here. * @@ -257,12 +270,6 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) */ { /* Keep this block, even when empty. */ - for (int i = 0; i < COLLECTION_COLOR_TOT; ++i) { - FROM_DEFAULT_V4_UCHAR(collection_color[i].color); - } - FROM_DEFAULT_V4_UCHAR(space_sequencer.row_alternate); - FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_geometry); - FROM_DEFAULT_V4_UCHAR(space_node.nodeclass_attribute); } #undef FROM_DEFAULT_V4_UCHAR @@ -814,10 +821,6 @@ void blo_do_versions_userdef(UserDef *userdef) userdef->uiflag &= ~USER_UIFLAG_UNUSED_3; } - if (!USER_VERSION_ATLEAST(292, 4)) { - userdef->animation_flag = USER_ANIM_SHOW_CHANNEL_GROUP_COLORS; - } - /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/tests/blendfile_loading_base_test.cc b/source/blender/blenloader/tests/blendfile_loading_base_test.cc index a3aabf6ac10..8d8dc3aebf7 100644 --- a/source/blender/blenloader/tests/blendfile_loading_base_test.cc +++ b/source/blender/blenloader/tests/blendfile_loading_base_test.cc @@ -103,7 +103,7 @@ void BlendfileLoadingBaseTest::TearDownTestCase() BKE_blender_atexit(); BKE_tempdir_session_purge(); - + BKE_appdir_exit(); CLG_exit(); testing::Test::TearDownTestCase(); diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 05b84ba21e2..4ce70e7bd5a 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -182,7 +182,7 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = { static BMOpDefine bmo_recalc_face_normals_def = { "recalc_face_normals", /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -485,8 +485,7 @@ static BMOpDefine bmo_collapse_uvs_def = { static BMOpDefine bmo_weld_verts_def = { "weld_verts", /* slots_in */ - /* maps welded vertices to verts they should weld to */ - {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, /* maps welded vertices to verts they should weld to */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -527,11 +526,11 @@ static BMOpDefine bmo_join_triangles_def = { "join_triangles", /* slots_in */ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ - {"cmp_seam", BMO_OP_SLOT_BOOL}, - {"cmp_sharp", BMO_OP_SLOT_BOOL}, - {"cmp_uvs", BMO_OP_SLOT_BOOL}, - {"cmp_vcols", BMO_OP_SLOT_BOOL}, - {"cmp_materials", BMO_OP_SLOT_BOOL}, + {"cmp_seam", BMO_OP_SLOT_BOOL}, /* Compare seam */ + {"cmp_sharp", BMO_OP_SLOT_BOOL}, /* Compare sharp */ + {"cmp_uvs", BMO_OP_SLOT_BOOL}, /* Compare UVs */ + {"cmp_vcols", BMO_OP_SLOT_BOOL}, /* compare VCols */ + {"cmp_materials", BMO_OP_SLOT_BOOL}, /* compare materials */ {"angle_face_threshold", BMO_OP_SLOT_FLT}, {"angle_shape_threshold", BMO_OP_SLOT_FLT}, {{'\0'}}, @@ -587,9 +586,9 @@ static BMOpDefine bmo_bridge_loops_def = { {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ {"use_pairs", BMO_OP_SLOT_BOOL}, {"use_cyclic", BMO_OP_SLOT_BOOL}, - {"use_merge", BMO_OP_SLOT_BOOL}, - {"merge_factor", BMO_OP_SLOT_FLT}, - {"twist_offset", BMO_OP_SLOT_INT}, + {"use_merge", BMO_OP_SLOT_BOOL}, /* merge rather than creating faces */ + {"merge_factor", BMO_OP_SLOT_FLT}, /* merge factor */ + {"twist_offset", BMO_OP_SLOT_INT}, /* twist offset for closed loops */ {{'\0'}}, }, /* slots_out */ @@ -831,8 +830,8 @@ static BMOpDefine bmo_transform_def = { static BMOpDefine bmo_object_load_bmesh_def = { "object_load_bmesh", /* slots_in */ - {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}}, - {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}}, /* pointer to an scene structure */ + {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, /* pointer to an object structure */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -850,10 +849,8 @@ static BMOpDefine bmo_bmesh_to_mesh_def = { "bmesh_to_mesh", /* slots_in */ { - /* pointer to a mesh structure to fill in */ - {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, - /* pointer to an object structure */ - {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, /* pointer to a mesh structure to fill in */ + {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, /* pointer to an object structure */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -871,10 +868,8 @@ static BMOpDefine bmo_mesh_to_bmesh_def = { "mesh_to_bmesh", /* slots_in */ { - /* pointer to a Mesh structure */ - {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, - /* pointer to an Object structure */ - {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, /* pointer to a Mesh structure */ + {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, /* pointer to an Object structure */ {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */ {{'\0'}}, }, @@ -955,8 +950,8 @@ static BMOpDefine bmo_extrude_vert_indiv_def = { static BMOpDefine bmo_connect_verts_def = { "connect_verts", /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces to explicitly exclude from connecting */ {"check_degenerate", BMO_OP_SLOT_BOOL}, /* prevent splits with overlaps & intersections */ {{'\0'}}, }, @@ -978,7 +973,7 @@ static BMOpDefine bmo_connect_verts_def = { static BMOpDefine bmo_connect_verts_concave_def = { "connect_verts_concave", /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ {{'\0'}}, }, /* slots_out */ @@ -1001,7 +996,7 @@ static BMOpDefine bmo_connect_verts_nonplanar_def = { "connect_verts_nonplanar", /* slots_in */ {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ - {"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ {{'\0'}}, }, /* slots_out */ @@ -1023,9 +1018,9 @@ static BMOpDefine bmo_connect_verts_nonplanar_def = { static BMOpDefine bmo_connect_vert_pair_def = { "connect_vert_pair", /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices to explicitly exclude from connecting */ + {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces to explicitly exclude from connecting */ {{'\0'}}, }, /* slots_out */ @@ -1048,7 +1043,7 @@ static BMOpDefine bmo_extrude_face_region_def = { "extrude_face_region", /* slots_in */ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ - {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, + {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, /* input edges to explicitly exclude from extrusion */ {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */ @@ -1070,9 +1065,9 @@ static BMOpDefine bmo_extrude_face_region_def = { static BMOpDefine bmo_dissolve_verts_def = { "dissolve_verts", /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"use_face_split", BMO_OP_SLOT_BOOL}, - {"use_boundary_tear", BMO_OP_SLOT_BOOL}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"use_face_split", BMO_OP_SLOT_BOOL}, /* split off face corners to maintain surrounding geometry */ + {"use_boundary_tear", BMO_OP_SLOT_BOOL}, /* split off face corners instead of merging faces */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -1089,9 +1084,9 @@ static BMOpDefine bmo_dissolve_verts_def = { static BMOpDefine bmo_dissolve_edges_def = { "dissolve_edges", /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ - {"use_face_split", BMO_OP_SLOT_BOOL}, + {"use_face_split", BMO_OP_SLOT_BOOL}, /* split off face corners to maintain surrounding geometry */ {{'\0'}}, }, /* slots_out */ @@ -1111,7 +1106,7 @@ static BMOpDefine bmo_dissolve_edges_def = { static BMOpDefine bmo_dissolve_faces_def = { "dissolve_faces", /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ {{'\0'}}, }, @@ -1144,10 +1139,10 @@ static BMOpDefine bmo_dissolve_limit_def = { "dissolve_limit", /* slots_in */ {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ - {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, - {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"delimit", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_FLAG}, bmo_enum_dissolve_limit_flags}, + {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, /* dissolve all vertices in between face boundaries */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"delimit", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_FLAG}, bmo_enum_dissolve_limit_flags}, /* delimit dissolve operation */ {{'\0'}}, }, /* slots_out */ @@ -1169,7 +1164,7 @@ static BMOpDefine bmo_dissolve_degenerate_def = { "dissolve_degenerate", /* slots_in */ {{"dist", BMO_OP_SLOT_FLT}, /* maximum distance to consider degenerate */ - {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ {{'\0'}}, }, /* slots_out */ @@ -1201,9 +1196,9 @@ static BMO_FlagSet bmo_enum_triangulate_ngon_method[] = { static BMOpDefine bmo_triangulate_def = { "triangulate", /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {"quad_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_quad_method}, - {"ngon_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_ngon_method}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"quad_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_quad_method}, /* method for splitting the quads into triangles */ + {"ngon_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_ngon_method}, /* method for splitting the polygons into triangles */ {{'\0'}}, }, /* slots_out */ @@ -1228,7 +1223,7 @@ static BMOpDefine bmo_unsubdivide_def = { "unsubdivide", /* slots_in */ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"iterations", BMO_OP_SLOT_INT}, + {"iterations", BMO_OP_SLOT_INT}, /* number of times to unsubdivide */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -1256,13 +1251,13 @@ static BMO_FlagSet bmo_enum_subdivide_edges_quad_corner_type[] = { static BMOpDefine bmo_subdivide_edges_def = { "subdivide_edges", /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"smooth", BMO_OP_SLOT_FLT}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"smooth", BMO_OP_SLOT_FLT}, /* smoothness factor */ {"smooth_falloff", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* smooth falloff type */ - {"fractal", BMO_OP_SLOT_FLT}, - {"along_normal", BMO_OP_SLOT_FLT}, - {"cuts", BMO_OP_SLOT_INT}, - {"seed", BMO_OP_SLOT_INT}, + {"fractal", BMO_OP_SLOT_FLT}, /* fractal randomness factor */ + {"along_normal", BMO_OP_SLOT_FLT}, /* apply fractal displacement along normal only */ + {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ + {"seed", BMO_OP_SLOT_INT}, /* seed for the random number generator */ {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */ {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, {"quad_corner_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edges_quad_corner_type}, /* quad corner type */ @@ -1304,10 +1299,10 @@ static BMOpDefine bmo_subdivide_edgering_def = { /* slots_in */ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ {"interp_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edgering_interp_mode}, /* interpolation method */ - {"smooth", BMO_OP_SLOT_FLT}, - {"cuts", BMO_OP_SLOT_INT}, + {"smooth", BMO_OP_SLOT_FLT}, /* smoothness factor */ + {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ {"profile_shape", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* profile shape type */ - {"profile_shape_factor", BMO_OP_SLOT_FLT}, + {"profile_shape_factor", BMO_OP_SLOT_FLT}, /* how much intermediary new edges are shrunk/expanded */ {{'\0'}}, }, {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ @@ -1327,7 +1322,7 @@ static BMOpDefine bmo_subdivide_edgering_def = { static BMOpDefine bmo_bisect_plane_def = { "bisect_plane", /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance when testing if a vert is exactly on the plane */ {"plane_co", BMO_OP_SLOT_VEC}, /* point on the plane */ {"plane_no", BMO_OP_SLOT_VEC}, /* direction of the plane */ @@ -1365,7 +1360,7 @@ static BMO_FlagSet bmo_enum_delete_context[] = { static BMOpDefine bmo_delete_def = { "delete", /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ {"context", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_delete_context}, /* geometry types to delete */ {{'\0'}}, }, @@ -1385,9 +1380,8 @@ static BMOpDefine bmo_delete_def = { static BMOpDefine bmo_duplicate_def = { "duplicate", /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - /* destination bmesh, if NULL will use current on */ - {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, /* destination bmesh, if NULL will use current on */ {"use_select_history", BMO_OP_SLOT_BOOL}, {"use_edge_flip_from_face", BMO_OP_SLOT_BOOL}, {{'\0'}}, @@ -1418,9 +1412,8 @@ static BMOpDefine bmo_duplicate_def = { static BMOpDefine bmo_split_def = { "split", /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - /* destination bmesh, if NULL will use current one */ - {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, /* destination bmesh, if NULL will use current one */ {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */ {{'\0'}}, }, @@ -1444,7 +1437,7 @@ static BMOpDefine bmo_split_def = { static BMOpDefine bmo_spin_def = { "spin", /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ {"cent", BMO_OP_SLOT_VEC}, /* rotation center */ {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */ {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */ @@ -1657,7 +1650,7 @@ static BMOpDefine bmo_create_cone_def = { /* slots_in */ {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ - {"segments", BMO_OP_SLOT_INT}, + {"segments", BMO_OP_SLOT_INT}, /* number of vertices in the base circle */ {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */ {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */ {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */ @@ -1682,7 +1675,7 @@ static BMOpDefine bmo_create_circle_def = { /* slots_in */ {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ - {"segments", BMO_OP_SLOT_INT}, + {"segments", BMO_OP_SLOT_INT}, /* number of vertices in the circle */ {"radius", BMO_OP_SLOT_FLT}, /* Radius of the circle. */ {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ @@ -1795,7 +1788,7 @@ static BMOpDefine bmo_bevel_def = { {"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */ {"custom_profile", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_STRUCT}}, /* CurveProfile */ {"vmesh_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, - bmo_enum_bevel_vmesh_method}, + bmo_enum_bevel_vmesh_method}, /* The method to use to create meshes at intersections. */ {{'\0'}}, }, /* slots_out */ @@ -1852,7 +1845,7 @@ static BMOpDefine bmo_beautify_fill_def = { static BMOpDefine bmo_triangle_fill_def = { "triangle_fill", /* slots_in */ - {{"use_beauty", BMO_OP_SLOT_BOOL}, + {{"use_beauty", BMO_OP_SLOT_BOOL}, /* use best triangulation division */ {"use_dissolve", BMO_OP_SLOT_BOOL}, /* dissolve resulting faces */ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ {"normal", BMO_OP_SLOT_VEC}, /* optionally pass the fill normal to use */ @@ -1876,8 +1869,8 @@ static BMOpDefine bmo_triangle_fill_def = { static BMOpDefine bmo_solidify_def = { "solidify", /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"thickness", BMO_OP_SLOT_FLT}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"thickness", BMO_OP_SLOT_FLT}, /* thickness */ {{'\0'}}, }, /* slots_out */ @@ -1898,11 +1891,11 @@ static BMOpDefine bmo_inset_individual_def = { "inset_individual", /* slots_in */ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"thickness", BMO_OP_SLOT_FLT}, - {"depth", BMO_OP_SLOT_FLT}, - {"use_even_offset", BMO_OP_SLOT_BOOL}, - {"use_interpolate", BMO_OP_SLOT_BOOL}, - {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, /* thickness */ + {"depth", BMO_OP_SLOT_FLT}, /* depth */ + {"use_even_offset", BMO_OP_SLOT_BOOL}, /* scale the offset to give more even thickness */ + {"use_interpolate", BMO_OP_SLOT_BOOL}, /* blend face data across the inset */ + {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* scale the offset by surrounding geometry */ {{'\0'}}, }, /* slots_out */ @@ -1923,15 +1916,15 @@ static BMOpDefine bmo_inset_region_def = { "inset_region", /* slots_in */ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {"use_boundary", BMO_OP_SLOT_BOOL}, - {"use_even_offset", BMO_OP_SLOT_BOOL}, - {"use_interpolate", BMO_OP_SLOT_BOOL}, - {"use_relative_offset", BMO_OP_SLOT_BOOL}, - {"use_edge_rail", BMO_OP_SLOT_BOOL}, - {"thickness", BMO_OP_SLOT_FLT}, - {"depth", BMO_OP_SLOT_FLT}, - {"use_outset", BMO_OP_SLOT_BOOL}, + {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces to explicitly exclude from inset */ + {"use_boundary", BMO_OP_SLOT_BOOL}, /* inset face boundaries */ + {"use_even_offset", BMO_OP_SLOT_BOOL}, /* scale the offset to give more even thickness */ + {"use_interpolate", BMO_OP_SLOT_BOOL}, /* blend face data across the inset */ + {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* scale the offset by surrounding geometry */ + {"use_edge_rail", BMO_OP_SLOT_BOOL}, /* inset the region along existing edges */ + {"thickness", BMO_OP_SLOT_FLT}, /* thickness */ + {"depth", BMO_OP_SLOT_FLT}, /* depth */ + {"use_outset", BMO_OP_SLOT_BOOL}, /* outset rather than inset */ {{'\0'}}, }, /* slots_out */ @@ -1951,12 +1944,12 @@ static BMOpDefine bmo_inset_region_def = { static BMOpDefine bmo_offset_edgeloops_def = { "offset_edgeloops", /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input faces */ - {"use_cap_endpoint", BMO_OP_SLOT_BOOL}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"use_cap_endpoint", BMO_OP_SLOT_BOOL}, /* extend loop around end-points */ {{'\0'}}, }, /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */ {{'\0'}}, }, bmo_offset_edgeloops_exec, @@ -1973,15 +1966,15 @@ static BMOpDefine bmo_wireframe_def = { "wireframe", /* slots_in */ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"thickness", BMO_OP_SLOT_FLT}, - {"offset", BMO_OP_SLOT_FLT}, - {"use_replace", BMO_OP_SLOT_BOOL}, - {"use_boundary", BMO_OP_SLOT_BOOL}, - {"use_even_offset", BMO_OP_SLOT_BOOL}, - {"use_crease", BMO_OP_SLOT_BOOL}, - {"crease_weight", BMO_OP_SLOT_FLT}, - {"use_relative_offset", BMO_OP_SLOT_BOOL}, - {"material_offset", BMO_OP_SLOT_INT}, + {"thickness", BMO_OP_SLOT_FLT}, /* thickness */ + {"offset", BMO_OP_SLOT_FLT}, /* offset the thickness from the center */ + {"use_replace", BMO_OP_SLOT_BOOL}, /* remove original geometry */ + {"use_boundary", BMO_OP_SLOT_BOOL}, /* inset face boundaries */ + {"use_even_offset", BMO_OP_SLOT_BOOL}, /* scale the offset to give more even thickness */ + {"use_crease", BMO_OP_SLOT_BOOL}, /* crease hub edges for improved subdivision surface */ + {"crease_weight", BMO_OP_SLOT_FLT}, /* the mean crease weight for resulting edges */ + {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* scale the offset by surrounding geometry */ + {"material_offset", BMO_OP_SLOT_INT}, /* offset material index of generated faces */ {{'\0'}}, }, /* slots_out */ @@ -2045,8 +2038,8 @@ static BMOpDefine bmo_poke_def = { static BMOpDefine bmo_convex_hull_def = { "convex_hull", /* slots_in */ - {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"use_existing_faces", BMO_OP_SLOT_BOOL}, + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"use_existing_faces", BMO_OP_SLOT_BOOL}, /* skip hull triangles that are covered by a pre-existing face */ {{'\0'}}, }, /* slots_out */ @@ -2076,7 +2069,7 @@ static BMOpDefine bmo_convex_hull_def = { static BMOpDefine bmo_symmetrize_def = { "symmetrize", /* slots_in */ - {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ {"direction", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_neg_xyz_and_xyz}, /* axis to use */ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ {{'\0'}}, diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc index 6031e160c8c..bfb093c569f 100644 --- a/source/blender/bmesh/tools/bmesh_boolean.cc +++ b/source/blender/bmesh/tools/bmesh_boolean.cc @@ -30,6 +30,10 @@ #include "bmesh_boolean.h" #include "bmesh_edgesplit.h" +#include "PIL_time.h" + +// #define PERF_DEBUG + namespace blender::meshintersect { #ifdef WITH_GMP @@ -354,7 +358,14 @@ static bool bmesh_boolean(BMesh *bm, { IMeshArena arena; IMesh m_triangulated; +# ifdef PERF_DEBUG + double start_time = PIL_check_seconds_timer(); +# endif IMesh m_in = mesh_from_bm(bm, looptris, looptris_tot, &m_triangulated, &arena); +# ifdef PERF_DEBUG + double mesh_time = PIL_check_seconds_timer(); + std::cout << "bmesh_boolean, imesh_from_bm done, time = " << mesh_time - start_time << "\n"; +# endif std::function<int(int)> shape_fn; if (use_self && boolean_mode == BoolOpType::None) { /* Unary knife operation. Want every face where test_fn doesn't return -1. */ @@ -379,7 +390,16 @@ static bool bmesh_boolean(BMesh *bm, } IMesh m_out = boolean_mesh( m_in, boolean_mode, nshapes, shape_fn, use_self, &m_triangulated, &arena); +# ifdef PERF_DEBUG + double boolean_time = PIL_check_seconds_timer(); + std::cout << "boolean done, time = " << boolean_time - mesh_time << "\n"; +# endif bool any_change = apply_mesh_output_to_bmesh(bm, m_out, keep_hidden); +# ifdef PERF_DEBUG + double apply_mesh_time = PIL_check_seconds_timer(); + std::cout << "applied boolean output to bmesh, time = " << apply_mesh_time - boolean_time + << "\n"; +# endif if (use_separate_all) { /* We are supposed to separate all faces that are incident on intersection edges. */ BM_mesh_edgesplit(bm, false, true, false); diff --git a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp index e95dd4233c4..b111fba44b7 100644 --- a/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp +++ b/source/blender/compositor/intern/COM_ChunkOrderHotspot.cpp @@ -17,7 +17,7 @@ */ #include "COM_ChunkOrderHotspot.h" -#include <math.h> +#include <cmath> ChunkOrderHotspot::ChunkOrderHotspot(int x, int y, float addition) { diff --git a/source/blender/compositor/intern/COM_CompositorContext.cpp b/source/blender/compositor/intern/COM_CompositorContext.cpp index 52e705ffb79..2e168221b7b 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.cpp +++ b/source/blender/compositor/intern/COM_CompositorContext.cpp @@ -18,7 +18,7 @@ #include "COM_CompositorContext.h" #include "COM_defines.h" -#include <stdio.h> +#include <cstdio> CompositorContext::CompositorContext() { diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 9b3355f535a..d8f67571ee5 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -16,7 +16,7 @@ * Copyright 2011, Blender Foundation. */ -#include <string.h> +#include <cstring> #include "DNA_node_types.h" diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 27cec28f5d5..b026d2e60d9 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -17,9 +17,9 @@ */ #include <algorithm> -#include <math.h> +#include <cmath> +#include <cstdlib> #include <sstream> -#include <stdlib.h> #include "atomic_ops.h" diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index 74aefaf0e6d..897d4e1df02 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -16,7 +16,7 @@ * Copyright 2011, Blender Foundation. */ -#include <string.h> +#include <cstring> #include "BKE_node.h" diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp index 0842721a9e5..1a30806f28c 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.cpp +++ b/source/blender/compositor/intern/COM_NodeOperation.cpp @@ -16,7 +16,7 @@ * Copyright 2011, Blender Foundation. */ -#include <stdio.h> +#include <cstdio> #include <typeinfo> #include "COM_ExecutionSystem.h" diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index 1237e728079..35a3314db3b 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -304,7 +304,7 @@ void NodeOperationBuilder::add_operation_input_constants() /* Note: unconnected inputs cached first to avoid modifying * m_operations while iterating over it */ - typedef std::vector<NodeOperationInput *> Inputs; + using Inputs = std::vector<NodeOperationInput *>; Inputs pending_inputs; for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) { NodeOperation *op = *it; @@ -597,7 +597,7 @@ void NodeOperationBuilder::add_complex_operation_buffers() } } -typedef std::set<NodeOperation *> Tags; +using Tags = std::set<NodeOperation *>; static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *op) { diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index 51ae9d6652e..acfe800e433 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -19,7 +19,7 @@ #include "COM_OpenCLDevice.h" #include "COM_WorkScheduler.h" -typedef enum COM_VendorID { NVIDIA = 0x10DE, AMD = 0x1002 } COM_VendorID; +enum COM_VendorID { NVIDIA = 0x10DE, AMD = 0x1002 }; const cl_image_format IMAGE_FORMAT_COLOR = { CL_RGBA, CL_FLOAT, diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 450b64eec5a..f726caa3d66 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -16,8 +16,8 @@ * Copyright 2011, Blender Foundation. */ +#include <cstdio> #include <list> -#include <stdio.h> #include "COM_CPUDevice.h" #include "COM_OpenCLDevice.h" diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index 74f5fceacfb..b2dfb558028 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -330,11 +330,11 @@ void DilateStepOperation::initExecution() } // small helper to pass data from initializeTileData to executePixel -typedef struct tile_info { +struct tile_info { rcti rect; int width; float *buffer; -} tile_info; +}; static tile_info *create_cache(int xmin, int xmax, int ymin, int ymax) { diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp index 7ef0d7b7606..fbbd373ba09 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp @@ -16,7 +16,7 @@ * Copyright 2011, Blender Foundation. */ -#include <stdlib.h> +#include <cstdlib> #include "BLI_math.h" #include "COM_DoubleEdgeMaskOperation.h" diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index e87d40b4c86..157c595afcb 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -16,7 +16,7 @@ * Copyright 2011, Blender Foundation. */ -#include <limits.h> +#include <climits> #include "BLI_utildefines.h" #include "COM_FastGaussianBlurOperation.h" diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp index acc1dddacdd..362905761bb 100644 --- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp @@ -23,7 +23,7 @@ * 2D Fast Hartley Transform, used for convolution */ -typedef float fREAL; +using fREAL = float; // returns next highest power of 2 of x, as well its log2 in L2 static unsigned int nextPow2(unsigned int x, unsigned int *L2) diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp index f7fabfb9572..21d9177ddd5 100644 --- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp @@ -19,7 +19,7 @@ #include "COM_OutputFileMultiViewOperation.h" #include "COM_OutputFileOperation.h" -#include <string.h> +#include <cstring> #include "BLI_listbase.h" #include "BLI_path_util.h" diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index c5623fdbd37..2676ab1b9ca 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -18,7 +18,7 @@ #include "COM_OutputFileOperation.h" -#include <string.h> +#include <cstring> #include "BLI_listbase.h" #include "BLI_path_util.h" diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index 0776c97563e..f7b908deaf4 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -16,7 +16,7 @@ * Copyright 2011, Blender Foundation. */ -#include <string.h> +#include <cstring> #include "MEM_guardedalloc.h" @@ -141,7 +141,7 @@ void VectorBlurOperation::generateVectorBlur(float *data, /* ****************** Spans ******************************* */ /* span fill in method, is also used to localize data for zbuffering */ -typedef struct ZSpan { +struct ZSpan { /* range for clipping */ int rectx, recty; @@ -157,8 +157,7 @@ typedef struct ZSpan { int *rectz; DrawBufPixel *rectdraw; float clipcrop; - -} ZSpan; +}; /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */ void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop) @@ -294,10 +293,10 @@ static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2]) /* ******************** VECBLUR ACCUM BUF ************************* */ -typedef struct DrawBufPixel { +struct DrawBufPixel { const float *colpoin; float alpha; -} DrawBufPixel; +}; static void zbuf_fill_in_rgba( ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4) diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp index 7f7c1b7b639..37b7d68d495 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.cpp +++ b/source/blender/compositor/operations/COM_WrapOperation.cpp @@ -16,7 +16,7 @@ * Copyright 2011, Blender Foundation. */ -#include <math.h> +#include <cmath> #include "COM_WrapOperation.h" diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index 574978e5a5f..9fb995bf463 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -19,7 +19,7 @@ #include "COM_WriteBufferOperation.h" #include "COM_OpenCLDevice.h" #include "COM_defines.h" -#include <stdio.h> +#include <cstdio> WriteBufferOperation::WriteBufferOperation(DataType datatype) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 9cae343dcde..5af70305e13 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -25,8 +25,8 @@ #include "intern/builder/deg_builder_nodes.h" -#include <stdio.h> -#include <stdlib.h> +#include <cstdio> +#include <cstdlib> #include "MEM_guardedalloc.h" @@ -1247,8 +1247,7 @@ void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *particle_se &particle_settings->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_EVAL); op_node->set_as_exit(); /* Texture slots. */ - for (int mtex_index = 0; mtex_index < MAX_MTEX; mtex_index++) { - MTex *mtex = particle_settings->mtex[mtex_index]; + for (MTex *mtex : particle_settings->mtex) { if (mtex == nullptr || mtex->tex == nullptr) { continue; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index 3c55d832568..8ba4b4a427f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -25,8 +25,8 @@ #include "intern/builder/deg_builder_nodes.h" -#include <stdio.h> -#include <stdlib.h> +#include <cstdio> +#include <cstdlib> #include "MEM_guardedalloc.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 7a6dc6e2315..c7669b9fecb 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -25,8 +25,8 @@ #include "intern/builder/deg_builder_nodes.h" -#include <stdio.h> -#include <stdlib.h> +#include <cstdio> +#include <cstdlib> #include "MEM_guardedalloc.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc index 4406cc83a0d..197e14c1a21 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc @@ -23,8 +23,8 @@ #include "intern/builder/deg_builder_pchanmap.h" -#include <stdio.h> -#include <string.h> +#include <cstdio> +#include <cstring> #include "BLI_utildefines.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index a55966632d8..11d34782569 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -25,9 +25,9 @@ #include "intern/builder/deg_builder_relations.h" +#include <cstdio> +#include <cstdlib> #include <cstring> /* required for STREQ later on. */ -#include <stdio.h> -#include <stdlib.h> #include "MEM_guardedalloc.h" @@ -1907,8 +1907,7 @@ void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part) particle_settings_init_key, particle_settings_eval_key, "Particle Settings Init Order"); add_relation(particle_settings_reset_key, particle_settings_eval_key, "Particle Settings Reset"); /* Texture slots. */ - for (int mtex_index = 0; mtex_index < MAX_MTEX; mtex_index++) { - MTex *mtex = part->mtex[mtex_index]; + for (MTex *mtex : part->mtex) { if (mtex == nullptr || mtex->tex == nullptr) { continue; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index 39a60c9029c..32c36d78250 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -25,9 +25,9 @@ #include "intern/builder/deg_builder_relations.h" +#include <cstdio> +#include <cstdlib> #include <cstring> /* required for STREQ later on. */ -#include <stdio.h> -#include <stdlib.h> #include "MEM_guardedalloc.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index b58d4a22712..8df8d4914c3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -25,9 +25,9 @@ #include "intern/builder/deg_builder_relations.h" +#include <cstdio> +#include <cstdlib> #include <cstring> /* required for STREQ later on. */ -#include <stdio.h> -#include <stdlib.h> #include "MEM_guardedalloc.h" diff --git a/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc b/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc index d02aa16f26b..dd71cc0504e 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc +++ b/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc @@ -36,7 +36,7 @@ class AllObjectsNodeBuilder : public DepsgraphNodeBuilder { { } - virtual bool need_pull_base_into_graph(Base * /*base*/) override + bool need_pull_base_into_graph(Base * /*base*/) override { return true; } @@ -49,7 +49,7 @@ class AllObjectsRelationBuilder : public DepsgraphRelationBuilder { { } - virtual bool need_pull_base_into_graph(Base * /*base*/) override + bool need_pull_base_into_graph(Base * /*base*/) override { return true; } diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc index 5fd4a0fc3dd..9e62432ea54 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc +++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc @@ -55,7 +55,7 @@ class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder { { } - virtual bool need_pull_base_into_graph(Base *base) override + bool need_pull_base_into_graph(Base *base) override { if (!filter_.contains(&base->object->id)) { return false; @@ -63,7 +63,7 @@ class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder { return DepsgraphNodeBuilder::need_pull_base_into_graph(base); } - virtual void build_object_proxy_group(Object *object, bool is_visible) override + void build_object_proxy_group(Object *object, bool is_visible) override { if (object->proxy_group == nullptr) { return; @@ -88,7 +88,7 @@ class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder { { } - virtual bool need_pull_base_into_graph(Base *base) override + bool need_pull_base_into_graph(Base *base) override { if (!filter_.contains(&base->object->id)) { return false; @@ -96,7 +96,7 @@ class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder { return DepsgraphRelationBuilder::need_pull_base_into_graph(base); } - virtual void build_object_proxy_group(Object *object) override + void build_object_proxy_group(Object *object) override { if (object->proxy_group == nullptr) { return; diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index d0eedd6d811..57de62e1880 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -25,7 +25,7 @@ #include "MEM_guardedalloc.h" -#include <string.h> /* XXX: memcpy */ +#include <cstring> /* XXX: memcpy */ #include "BLI_listbase.h" #include "BLI_utildefines.h" @@ -90,8 +90,8 @@ bool DEG_id_type_any_updated(const Depsgraph *graph) const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph); /* Loop over all ID types. */ - for (int id_type_index = 0; id_type_index < MAX_LIBARRAY; id_type_index++) { - if (deg_graph->id_type_updated[id_type_index]) { + for (char id_type_index : deg_graph->id_type_updated) { + if (id_type_index) { return true; } } diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc index ed7011ba306..6ce7cc0837b 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc @@ -47,9 +47,9 @@ namespace deg = blender::deg; namespace blender::deg { namespace { -typedef deque<OperationNode *> TraversalQueue; +using TraversalQueue = deque<OperationNode *>; -typedef void (*DEGForeachOperation)(OperationNode *op_node, void *user_data); +using DEGForeachOperation = void (*)(OperationNode *, void *); bool deg_foreach_needs_visit(const OperationNode *op_node, const int flags) { diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index aec3dd4b9ea..95ee8234ef3 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -25,9 +25,9 @@ #include "intern/depsgraph_tag.h" +#include <cstdio> #include <cstring> /* required for memset */ #include <queue> -#include <stdio.h> #include "BLI_math_bits.h" #include "BLI_task.h" diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index fa7cfb305ee..1b24e2b7ad2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -82,7 +82,7 @@ enum { COMPONENT_STATE_DONE = 2, }; -typedef deque<OperationNode *> FlushQueue; +using FlushQueue = deque<OperationNode *>; namespace { diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.cc index 8e9fff56023..8fe0dd95bc2 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.cc @@ -31,7 +31,7 @@ #include "BKE_volume.h" -#include <stdio.h> +#include <cstdio> namespace blender::deg { diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc index 6266acae651..0d3563ee3de 100644 --- a/source/blender/depsgraph/intern/node/deg_node.cc +++ b/source/blender/depsgraph/intern/node/deg_node.cc @@ -23,7 +23,7 @@ #include "intern/node/deg_node.h" -#include <stdio.h> +#include <cstdio> #include "BLI_utildefines.h" diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index 6ffe5db3fec..d824fb14718 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -23,8 +23,8 @@ #include "intern/node/deg_node_component.h" +#include <cstdio> #include <cstring> /* required for STREQ later on. */ -#include <stdio.h> #include "BLI_ghash.h" #include "BLI_hash.hh" diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 345da466960..4f2fcab5823 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -23,8 +23,8 @@ #include "intern/node/deg_node_id.h" +#include <cstdio> #include <cstring> /* required for STREQ later on. */ -#include <stdio.h> #include "BLI_string.h" #include "BLI_utildefines.h" diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 2de6ee1f57d..a6cc9fddd69 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -80,6 +80,7 @@ set(SRC engines/image/image_engine.c engines/image/image_shader.c engines/eevee/eevee_bloom.c + engines/eevee/eevee_cryptomatte.c engines/eevee/eevee_data.c engines/eevee/eevee_depth_of_field.c engines/eevee/eevee_effects.c @@ -250,6 +251,7 @@ data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/renderpass_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/renderpass_postprocess_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/cryptomatte_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/surface_frag.glsl SRC) diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c new file mode 100644 index 00000000000..44ff86b3333 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -0,0 +1,654 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup EEVEE + * + * This file implements Cryptomatte for EEVEE. Cryptomatte is used to extract mattes using + * information already available at render time. See + * https://raw.githubusercontent.com/Psyop/Cryptomatte/master/specification/IDmattes_poster.pdf + * for reference to the cryptomatte specification. + * + * The challenge with cryptomatte in EEVEE is the merging and sorting of the samples. + * User can enable up to 3 cryptomatte layers (Object, Material and Asset). + * + * Process + * + * - Cryptomatte sample: Rendering of a cryptomatte sample is stored in a GPUBuffer. The buffer + * holds a single float per pixel per number of active cryptomatte layers. The float is the + * cryptomatte hash of each layer. After drawing the cryptomatte sample the intermediate result is + * downloaded to a CPU buffer (`cryptomatte_download_buffer`). + * + * Accurate mode + * + * There are two accuracy modes. The difference between the two is the number of render samples + * they take into account to create the render passes. When accurate mode is off the number of + * levels is used as the number of cryptomatte samples to take. When accuracy mode is on the number + * of render samples is used. + * + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BKE_cryptomatte.h" + +#include "GPU_batch.h" + +#include "RE_pipeline.h" + +#include "BLI_alloca.h" +#include "BLI_math_bits.h" +#include "BLI_rect.h" + +#include "DNA_hair_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_particle_types.h" + +#include "eevee_private.h" + +/* -------------------------------------------------------------------- */ +/** \name Data Management cryptomatte accum buffer + * \{ */ + +BLI_INLINE eViewLayerCryptomatteFlags eevee_cryptomatte_active_layers(const ViewLayer *view_layer) +{ + const eViewLayerCryptomatteFlags cryptomatte_layers = view_layer->cryptomatte_flag & + VIEW_LAYER_CRYPTOMATTE_ALL; + return cryptomatte_layers; +} + +/* The number of cryptomatte layers that are enabled */ +BLI_INLINE int eevee_cryptomatte_layers_count(const ViewLayer *view_layer) +{ + const eViewLayerCryptomatteFlags cryptomatte_layers = eevee_cryptomatte_active_layers( + view_layer); + return count_bits_i(cryptomatte_layers); +} + +/* The number of render result passes are needed to store a single cryptomatte layer. Per + * renderpass 2 cryptomatte samples can be stored. */ +BLI_INLINE int eevee_cryptomatte_passes_per_layer(const ViewLayer *view_layer) +{ + const int num_cryptomatte_levels = view_layer->cryptomatte_levels; + const int num_cryptomatte_passes = (num_cryptomatte_levels + 1) / 2; + return num_cryptomatte_passes; +} + +BLI_INLINE int eevee_cryptomatte_layer_stride(const ViewLayer *view_layer) +{ + return view_layer->cryptomatte_levels; +} + +BLI_INLINE int eevee_cryptomatte_layer_offset(const ViewLayer *view_layer, const int layer) +{ + return view_layer->cryptomatte_levels * layer; +} + +BLI_INLINE int eevee_cryptomatte_pixel_stride(const ViewLayer *view_layer) +{ + return eevee_cryptomatte_layer_stride(view_layer) * eevee_cryptomatte_layers_count(view_layer); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Init Renderpasses + * \{ */ + +void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + + /* Cryptomatte is only rendered for final image renders */ + if (!DRW_state_is_image_render()) { + return; + } + if (eevee_cryptomatte_active_layers(view_layer) != 0) { + g_data->render_passes |= EEVEE_RENDER_PASS_CRYPTOMATTE; + g_data->cryptomatte_accurate_mode = (view_layer->cryptomatte_flag & + VIEW_LAYER_CRYPTOMATTE_ACCURATE) != 0; + } +} + +void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + int UNUSED(tot_samples)) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PrivateData *g_data = vedata->stl->g_data; + + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + + const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); + eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? + GPU_R32F : + (num_cryptomatte_layers == 2) ? GPU_RG32F : GPU_RGBA32F; + const float *viewport_size = DRW_viewport_size_get(); + const int buffer_size = viewport_size[0] * viewport_size[1]; + + if (g_data->cryptomatte_accum_buffer == NULL) { + g_data->cryptomatte_accum_buffer = MEM_calloc_arrayN( + sizeof(EEVEE_CryptomatteSample), + buffer_size * eevee_cryptomatte_pixel_stride(view_layer), + __func__); + /* Download buffer should store a float per active cryptomatte layer. */ + g_data->cryptomatte_download_buffer = MEM_malloc_arrayN( + sizeof(float), buffer_size * num_cryptomatte_layers, __func__); + } + + DRW_texture_ensure_fullscreen_2d(&txl->cryptomatte, format, 0); + GPU_framebuffer_ensure_config(&fbl->cryptomatte_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(txl->cryptomatte), + }); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Populate Cache + * \{ */ + +void EEVEE_cryptomatte_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_CRYPTOMATTE) != 0) { + DRW_PASS_CREATE(psl->cryptomatte_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + } +} + +static DRWShadingGroup *eevee_cryptomatte_shading_group_create(EEVEE_Data *vedata, + EEVEE_ViewLayerData *UNUSED(sldata), + Object *ob, + Material *material, + bool is_hair) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + const eViewLayerCryptomatteFlags cryptomatte_layers = eevee_cryptomatte_active_layers( + view_layer); + float cryptohash[4] = {0.0f}; + + EEVEE_PassList *psl = vedata->psl; + int layer_offset = 0; + if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_OBJECT) != 0) { + uint32_t cryptomatte_hash = BKE_cryptomatte_object_hash(ob); + float cryptomatte_color_value = BKE_cryptomatte_hash_to_float(cryptomatte_hash); + cryptohash[layer_offset] = cryptomatte_color_value; + layer_offset++; + } + if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_MATERIAL) != 0) { + uint32_t cryptomatte_hash = BKE_cryptomatte_material_hash(material); + float cryptomatte_color_value = BKE_cryptomatte_hash_to_float(cryptomatte_hash); + cryptohash[layer_offset] = cryptomatte_color_value; + layer_offset++; + } + if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_ASSET) != 0) { + uint32_t cryptomatte_hash = BKE_cryptomatte_asset_hash(ob); + float cryptomatte_color_value = BKE_cryptomatte_hash_to_float(cryptomatte_hash); + cryptohash[layer_offset] = cryptomatte_color_value; + layer_offset++; + } + + DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_cryptomatte_sh_get(is_hair), + psl->cryptomatte_ps); + DRW_shgroup_uniform_vec4_copy(grp, "cryptohash", cryptohash); + + return grp; +} + +static void eevee_cryptomatte_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + ParticleSystem *psys, + ModifierData *md, + Material *material) +{ + DRWShadingGroup *grp = eevee_cryptomatte_shading_group_create( + vedata, sldata, ob, material, true); + DRW_shgroup_hair_create_sub(ob, psys, md, grp); +} + +void EEVEE_cryptomatte_object_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob) +{ + BLI_assert(ob->type == OB_HAIR); + Hair *hair = ob->data; + Material *material = hair->mat ? hair->mat[HAIR_MATERIAL_NR - 1] : NULL; + eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, NULL, NULL, material); +} + +void EEVEE_cryptomatte_particle_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (ob->type == OB_MESH) { + if (ob != draw_ctx->object_edit) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type != eModifierType_ParticleSystem) { + continue; + } + ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { + continue; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + if (draw_as != PART_DRAW_PATH) { + continue; + } + Mesh *mesh = ob->data; + Material *material = part->omat - 1 < mesh->totcol ? NULL : mesh->mat[part->omat - 1]; + eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, psys, md, material); + } + } + } +} + +void EEVEE_cryptomatte_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + const eViewLayerCryptomatteFlags cryptomatte_layers = eevee_cryptomatte_active_layers( + view_layer); + + if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_MATERIAL) != 0) { + const int materials_len = DRW_cache_object_material_count_get(ob); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + memset(gpumat_array, 0, sizeof(*gpumat_array) * materials_len); + struct GPUBatch **geoms = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len); + if (geoms) { + for (int i = 0; i < materials_len; i++) { + struct GPUBatch *geom = geoms[i]; + if (geom == NULL) { + continue; + } + Material *material = BKE_object_material_get(ob, i + 1); + DRWShadingGroup *grp = eevee_cryptomatte_shading_group_create( + vedata, sldata, ob, material, false); + DRW_shgroup_call(grp, geom, ob); + } + } + } + else { + GPUBatch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + DRWShadingGroup *grp = eevee_cryptomatte_shading_group_create( + vedata, sldata, ob, false, NULL); + DRW_shgroup_call(grp, geom, ob); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Accumulate Samples + * \{ */ + +/* Downloads cryptomatte sample buffer from the GPU and integrate the samples with the accumulated + * cryptomatte samples. */ +static void eevee_cryptomatte_download_buffer(EEVEE_Data *vedata, GPUFrameBuffer *framebuffer) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); + const int num_levels = view_layer->cryptomatte_levels; + const float *viewport_size = DRW_viewport_size_get(); + const int buffer_size = viewport_size[0] * viewport_size[1]; + + EEVEE_CryptomatteSample *accum_buffer = g_data->cryptomatte_accum_buffer; + float *download_buffer = g_data->cryptomatte_download_buffer; + + BLI_assert(accum_buffer); + BLI_assert(download_buffer); + + GPU_framebuffer_read_color(framebuffer, + 0, + 0, + viewport_size[0], + viewport_size[1], + num_cryptomatte_layers, + 0, + GPU_DATA_FLOAT, + download_buffer); + + /* Integrate download buffer into the accum buffer. + * The download buffer contains upto 3 floats per pixel (one float per cryptomatte layer. + * + * NOTE: here we deviate from the cryptomatte standard. During integration the standard always + * sort the samples by its weight to make sure that samples with the lowest weight + * are discarded first. In our case the weight of each sample is always 1 as we don't have + * subsamples and apply the coverage during the post processing. When there is no room for new + * samples the new samples has a weight of 1 and will always be discarded. */ + int download_pixel_index = 0; + int accum_pixel_index = 0; + int accum_pixel_stride = eevee_cryptomatte_pixel_stride(view_layer); + for (int pixel_index = 0; pixel_index < buffer_size; pixel_index++) { + for (int layer = 0; layer < num_cryptomatte_layers; layer++) { + const int layer_offset = eevee_cryptomatte_layer_offset(view_layer, layer); + float download_hash = download_buffer[download_pixel_index++]; + for (int level = 0; level < num_levels; level++) { + EEVEE_CryptomatteSample *sample = &accum_buffer[accum_pixel_index + layer_offset + level]; + if (sample->hash == download_hash) { + sample->weight += 1.0f; + break; + } + /* We test against weight as hash 0.0f is used for samples hitting the world background. */ + if (sample->weight == 0.0f) { + sample->hash = download_hash; + sample->weight = 1.0f; + break; + } + } + } + accum_pixel_index += accum_pixel_stride; + } +} + +void EEVEE_cryptomatte_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_PassList *psl = vedata->psl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + const int cryptomatte_levels = view_layer->cryptomatte_levels; + const int current_sample = effects->taa_current_sample; + + /* In accurate mode all render samples are evaluated. In inaccurate mode this is limited to the + * number of cryptomatte levels. This will reduce the overhead of downloading the GPU buffer and + * integrating it into the accum buffer. */ + if (g_data->cryptomatte_accurate_mode || current_sample < cryptomatte_levels) { + static float clear_color[4] = {0.0}; + GPU_framebuffer_bind(fbl->cryptomatte_fb); + GPU_framebuffer_clear_color(fbl->cryptomatte_fb, clear_color); + DRW_draw_pass(psl->cryptomatte_ps); + + eevee_cryptomatte_download_buffer(vedata, fbl->cryptomatte_fb); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update Render Passes + * \{ */ + +/* Register the render passes needed for cryptomatte + * normally this is done in `EEVEE_render_update_passes`, but it has been placed here to keep + * related code side-by-side for clarity. */ +void EEVEE_cryptomatte_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) +{ + char cryptomatte_pass_name[MAX_NAME]; + const short num_passes = eevee_cryptomatte_passes_per_layer(view_layer); + if ((view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_OBJECT) != 0) { + for (short pass = 0; pass < num_passes; pass++) { + BLI_snprintf_rlen(cryptomatte_pass_name, MAX_NAME, "CryptoObject%02d", pass); + RE_engine_register_pass( + engine, scene, view_layer, cryptomatte_pass_name, 4, "RGBA", SOCK_RGBA); + } + } + if ((view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_MATERIAL) != 0) { + for (short pass = 0; pass < num_passes; pass++) { + BLI_snprintf_rlen(cryptomatte_pass_name, MAX_NAME, "CryptoMaterial%02d", pass); + RE_engine_register_pass( + engine, scene, view_layer, cryptomatte_pass_name, 4, "RGBA", SOCK_RGBA); + } + } + if ((view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_ASSET) != 0) { + for (short pass = 0; pass < num_passes; pass++) { + BLI_snprintf_rlen(cryptomatte_pass_name, MAX_NAME, "CryptoAsset%02d", pass); + RE_engine_register_pass( + engine, scene, view_layer, cryptomatte_pass_name, 4, "RGBA", SOCK_RGBA); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Construct Render Result + * \{ */ + +/* Compare function for cryptomatte samples. Samples with the highest weight will be at the + * beginning of the list. */ +static int eevee_cryptomatte_sample_cmp_reverse(const void *a_, const void *b_) +{ + const EEVEE_CryptomatteSample *a = a_; + const EEVEE_CryptomatteSample *b = b_; + if (a->weight < b->weight) { + return 1; + } + if (a->weight > b->weight) { + return -1; + } + + return 0; +} + +/* Post process the weights. The accumulated weights buffer adds one to each weight per sample. + * During post processing ensure that the total of weights per sample is between 0 and 1. */ +static void eevee_cryptomatte_postprocess_weights(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); + const int num_levels = view_layer->cryptomatte_levels; + const float *viewport_size = DRW_viewport_size_get(); + const int buffer_size = viewport_size[0] * viewport_size[1]; + + EEVEE_CryptomatteSample *accum_buffer = g_data->cryptomatte_accum_buffer; + BLI_assert(accum_buffer); + int accum_pixel_index = 0; + int accum_pixel_stride = eevee_cryptomatte_pixel_stride(view_layer); + + for (int pixel_index = 0; pixel_index < buffer_size; + pixel_index++, accum_pixel_index += accum_pixel_stride) { + for (int layer = 0; layer < num_cryptomatte_layers; layer++) { + const int layer_offset = eevee_cryptomatte_layer_offset(view_layer, layer); + /* Calculate the total weight of the sample. */ + float total_weight = 0.0f; + for (int level = 0; level < num_levels; level++) { + EEVEE_CryptomatteSample *sample = &accum_buffer[accum_pixel_index + layer_offset + level]; + total_weight += sample->weight; + } + BLI_assert(total_weight > 0.0f); + + float total_weight_inv = 1.0f / total_weight; + for (int level = 0; level < num_levels; level++) { + EEVEE_CryptomatteSample *sample = &accum_buffer[accum_pixel_index + layer_offset + level]; + /* Remove background samples. These samples were used to determine the correct weight + * but won't be part of the final result. */ + if (sample->hash == 0.0f) { + sample->weight = 0.0f; + } + sample->weight *= total_weight_inv; + } + + /* Sort accum buffer by coverage of each sample. */ + qsort(&accum_buffer[accum_pixel_index + layer_offset], + num_levels, + sizeof(EEVEE_CryptomatteSample), + eevee_cryptomatte_sample_cmp_reverse); + } + } +} + +/* Extract cryptomatte layer from the cryptomatte_accum_buffer to render passes. */ +static void eevee_cryptomatte_extract_render_passes( + RenderLayer *rl, + const char *viewname, + const char *render_pass_name_format, + EEVEE_CryptomatteSample *accum_buffer, + /* number of render passes per cryptomatte layer. */ + const int num_cryptomatte_passes, + const int num_cryptomatte_levels, + const int accum_pixel_stride, + const int layer_stride, + const int layer_index, + const int rect_width, + const int rect_height, + const int rect_offset_x, + const int rect_offset_y, + const int viewport_width) +{ + char cryptomatte_pass_name[MAX_NAME]; + /* A pass can store 2 levels. Technically the last pass can have a single level if the number of + * levels is an odd number. This parameter counts the number of levels it has processed. */ + int levels_done = 0; + for (int pass = 0; pass < num_cryptomatte_passes; pass++) { + /* Each pass holds 2 cryptomatte samples. */ + const int pass_offset = pass * 2; + BLI_snprintf_rlen(cryptomatte_pass_name, MAX_NAME, render_pass_name_format, pass); + RenderPass *rp_object = RE_pass_find_by_name(rl, cryptomatte_pass_name, viewname); + for (int y = 0; y < rect_height; y++) { + for (int x = 0; x < rect_width; x++) { + const int accum_buffer_offset = (rect_offset_x + x + + (rect_offset_y + y) * viewport_width) * + accum_pixel_stride + + layer_index * layer_stride + pass_offset; + const int render_pass_offset = (y * rect_width + x) * 4; + rp_object->rect[render_pass_offset] = accum_buffer[accum_buffer_offset].hash; + rp_object->rect[render_pass_offset + 1] = accum_buffer[accum_buffer_offset].weight; + if (levels_done + 1 < num_cryptomatte_levels) { + rp_object->rect[render_pass_offset + 2] = accum_buffer[accum_buffer_offset + 1].hash; + rp_object->rect[render_pass_offset + 3] = accum_buffer[accum_buffer_offset + 1].weight; + } + else { + rp_object->rect[render_pass_offset + 2] = 0.0f; + rp_object->rect[render_pass_offset + 3] = 0.0f; + } + } + } + levels_done++; + } +} + +void EEVEE_cryptomatte_render_result(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *UNUSED(sldata)) +{ + EEVEE_PrivateData *g_data = vedata->stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ViewLayer *view_layer = draw_ctx->view_layer; + const eViewLayerCryptomatteFlags cryptomatte_layers = view_layer->cryptomatte_flag & + VIEW_LAYER_CRYPTOMATTE_ALL; + + eevee_cryptomatte_postprocess_weights(vedata); + + const int rect_width = BLI_rcti_size_x(rect); + const int rect_height = BLI_rcti_size_y(rect); + const int rect_offset_x = vedata->stl->g_data->overscan_pixels + rect->xmin; + const int rect_offset_y = vedata->stl->g_data->overscan_pixels + rect->ymin; + const float *viewport_size = DRW_viewport_size_get(); + const int viewport_width = viewport_size[0]; + EEVEE_CryptomatteSample *accum_buffer = g_data->cryptomatte_accum_buffer; + BLI_assert(accum_buffer); + const int num_cryptomatte_levels = view_layer->cryptomatte_levels; + const int num_cryptomatte_passes = eevee_cryptomatte_passes_per_layer(view_layer); + const int layer_stride = eevee_cryptomatte_layer_stride(view_layer); + const int accum_pixel_stride = eevee_cryptomatte_pixel_stride(view_layer); + + int layer_index = 0; + if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_OBJECT) != 0) { + eevee_cryptomatte_extract_render_passes(rl, + viewname, + "CryptoObject%02d", + accum_buffer, + num_cryptomatte_passes, + num_cryptomatte_levels, + accum_pixel_stride, + layer_stride, + layer_index, + rect_width, + rect_height, + rect_offset_x, + rect_offset_y, + viewport_width); + layer_index++; + } + if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_MATERIAL) != 0) { + eevee_cryptomatte_extract_render_passes(rl, + viewname, + "CryptoMaterial%02d", + accum_buffer, + num_cryptomatte_passes, + num_cryptomatte_levels, + accum_pixel_stride, + layer_stride, + layer_index, + rect_width, + rect_height, + rect_offset_x, + rect_offset_y, + viewport_width); + layer_index++; + } + if ((cryptomatte_layers & VIEW_LAYER_CRYPTOMATTE_ASSET) != 0) { + eevee_cryptomatte_extract_render_passes(rl, + viewname, + "CryptoAsset%02d", + accum_buffer, + num_cryptomatte_passes, + num_cryptomatte_levels, + accum_pixel_stride, + layer_stride, + layer_index, + rect_width, + rect_height, + rect_offset_x, + rect_offset_y, + viewport_width); + layer_index++; + } +} + +/** \} */ + +void EEVEE_cryptomatte_free(EEVEE_Data *vedata) +{ + EEVEE_PrivateData *g_data = vedata->stl->g_data; + MEM_SAFE_FREE(g_data->cryptomatte_accum_buffer); + MEM_SAFE_FREE(g_data->cryptomatte_download_buffer); +} diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 5c4ee015c86..47068d0b843 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -240,6 +240,9 @@ void EEVEE_view_layer_data_free(void *storage) DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_light); DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.emit); DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.environment); + for (int aov_index = 0; aov_index < MAX_AOVS; aov_index++) { + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.aovs[aov_index]); + } if (sldata->material_cache) { BLI_memblock_destroy(sldata->material_cache, NULL); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 7d1f40ba5d8..f233b0fda96 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -570,6 +570,8 @@ static void eevee_render_to_image(void *vedata, EEVEE_motion_blur_data_free(&ved->stl->effects->motion_blur); if (RE_engine_test_break(engine)) { + /* Cryptomatte buffers are freed during render_read_result */ + EEVEE_cryptomatte_free(vedata); return; } diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 58f182ecf8d..c7a8f7729eb 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -244,31 +244,31 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, /* Create RenderPass UBO */ if (sldata->renderpass_ubo.combined == NULL) { EEVEE_RenderPassData data; - data = (EEVEE_RenderPassData){true, true, true, true, true, false, false}; + data = (EEVEE_RenderPassData){true, true, true, true, true, false, false, false, 0}; sldata->renderpass_ubo.combined = GPU_uniformbuf_create_ex( sizeof(data), &data, "renderpass_ubo.combined"); - data = (EEVEE_RenderPassData){true, false, false, false, false, true, false}; + data = (EEVEE_RenderPassData){true, false, false, false, false, true, false, false, 0}; sldata->renderpass_ubo.diff_color = GPU_uniformbuf_create_ex( sizeof(data), &data, "renderpass_ubo.diff_color"); - data = (EEVEE_RenderPassData){true, true, false, false, false, false, false}; + data = (EEVEE_RenderPassData){true, true, false, false, false, false, false, false, 0}; sldata->renderpass_ubo.diff_light = GPU_uniformbuf_create_ex( sizeof(data), &data, "renderpass_ubo.diff_light"); - data = (EEVEE_RenderPassData){false, false, true, false, false, false, false}; + data = (EEVEE_RenderPassData){false, false, true, false, false, false, false, false, 0}; sldata->renderpass_ubo.spec_color = GPU_uniformbuf_create_ex( sizeof(data), &data, "renderpass_ubo.spec_color"); - data = (EEVEE_RenderPassData){false, false, true, true, false, false, false}; + data = (EEVEE_RenderPassData){false, false, true, true, false, false, false, false, 0}; sldata->renderpass_ubo.spec_light = GPU_uniformbuf_create_ex( sizeof(data), &data, "renderpass_ubo.spec_light"); - data = (EEVEE_RenderPassData){false, false, false, false, true, false, false}; + data = (EEVEE_RenderPassData){false, false, false, false, true, false, false, false, 0}; sldata->renderpass_ubo.emit = GPU_uniformbuf_create_ex( sizeof(data), &data, "renderpass_ubo.emit"); - data = (EEVEE_RenderPassData){true, true, true, true, true, false, true}; + data = (EEVEE_RenderPassData){true, true, true, true, true, false, true, false, 0}; sldata->renderpass_ubo.environment = GPU_uniformbuf_create_ex( sizeof(data), &data, "renderpass_ubo.environment"); } @@ -276,6 +276,51 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, /* Used combined pass by default. */ g_data->renderpass_ubo = sldata->renderpass_ubo.combined; + { + g_data->num_aovs_used = 0; + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_AOV) != 0) { + EEVEE_RenderPassData data = {true, true, true, true, true, false, false, true, 0}; + if (stl->g_data->aov_hash == EEVEE_AOV_HASH_ALL) { + ViewLayer *view_layer = draw_ctx->view_layer; + int aov_index = 0; + LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { + if ((aov->flag & AOV_CONFLICT) != 0) { + continue; + } + if (aov_index == MAX_AOVS) { + break; + } + data.renderPassAOVActive = EEVEE_renderpasses_aov_hash(aov); + if (sldata->renderpass_ubo.aovs[aov_index]) { + GPU_uniformbuf_update(sldata->renderpass_ubo.aovs[aov_index], &data); + } + else { + sldata->renderpass_ubo.aovs[aov_index] = GPU_uniformbuf_create_ex( + sizeof(data), &data, "renderpass_ubo.aovs"); + } + aov_index++; + } + g_data->num_aovs_used = aov_index; + } + else { + /* Rendering a single AOV in the 3d viewport */ + data.renderPassAOVActive = stl->g_data->aov_hash; + if (sldata->renderpass_ubo.aovs[0]) { + GPU_uniformbuf_update(sldata->renderpass_ubo.aovs[0], &data); + } + else { + sldata->renderpass_ubo.aovs[0] = GPU_uniformbuf_create_ex( + sizeof(data), &data, "renderpass_ubo.aovs"); + } + g_data->num_aovs_used = 1; + } + } + /* Free AOV UBO's that are not in use. */ + for (int aov_index = g_data->num_aovs_used; aov_index < MAX_AOVS; aov_index++) { + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.aovs[aov_index]); + } + } + /* HACK: EEVEE_material_get can create a new context. This can only be * done when there is no active framebuffer. We do this here otherwise * `EEVEE_renderpasses_output_init` will fail. It cannot be done in @@ -949,6 +994,11 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) { material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear); } + if (pd->render_passes & EEVEE_RENDER_PASS_AOV) { + for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) { + material_renderpass_init(fbl, &txl->aov_surface_accum[aov_index], texture_format, do_clear); + } + } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear); @@ -960,6 +1010,7 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl, DRWPass *renderpass, + DRWPass *renderpass2, EEVEE_PrivateData *pd, GPUTexture *output_tx, struct GPUUniformBuf *renderpass_option_ubo) @@ -969,6 +1020,9 @@ static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl, pd->renderpass_ubo = renderpass_option_ubo; DRW_draw_pass(renderpass); + if (renderpass2) { + DRW_draw_pass(renderpass2); + } GPU_framebuffer_texture_detach(fbl->material_accum_fb, output_tx); } @@ -983,38 +1037,69 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v if (fbl->material_accum_fb != NULL) { DRWPass *material_accum_ps = psl->material_accum_ps; + DRWPass *background_accum_ps = psl->background_accum_ps; if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { material_renderpass_accumulate( - fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.environment); + fbl, background_accum_ps, NULL, pd, txl->env_accum, sldata->renderpass_ubo.environment); } if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) { material_renderpass_accumulate( - fbl, material_accum_ps, pd, txl->emit_accum, sldata->renderpass_ubo.emit); + fbl, material_accum_ps, NULL, pd, txl->emit_accum, sldata->renderpass_ubo.emit); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) { - material_renderpass_accumulate( - fbl, material_accum_ps, pd, txl->diff_color_accum, sldata->renderpass_ubo.diff_color); + material_renderpass_accumulate(fbl, + material_accum_ps, + NULL, + pd, + txl->diff_color_accum, + sldata->renderpass_ubo.diff_color); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { - material_renderpass_accumulate( - fbl, material_accum_ps, pd, txl->diff_light_accum, sldata->renderpass_ubo.diff_light); + material_renderpass_accumulate(fbl, + material_accum_ps, + NULL, + pd, + txl->diff_light_accum, + sldata->renderpass_ubo.diff_light); if (effects->enabled_effects & EFFECT_SSS) { EEVEE_subsurface_output_accumulate(sldata, vedata); } } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) { - material_renderpass_accumulate( - fbl, material_accum_ps, pd, txl->spec_color_accum, sldata->renderpass_ubo.spec_color); + material_renderpass_accumulate(fbl, + material_accum_ps, + NULL, + pd, + txl->spec_color_accum, + sldata->renderpass_ubo.spec_color); } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { - material_renderpass_accumulate( - fbl, material_accum_ps, pd, txl->spec_light_accum, sldata->renderpass_ubo.spec_light); + material_renderpass_accumulate(fbl, + material_accum_ps, + NULL, + pd, + txl->spec_light_accum, + sldata->renderpass_ubo.spec_light); if (effects->enabled_effects & EFFECT_SSR) { EEVEE_reflection_output_accumulate(sldata, vedata); } } + if (pd->render_passes & EEVEE_RENDER_PASS_AOV) { + for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) { + material_renderpass_accumulate(fbl, + material_accum_ps, + background_accum_ps, + pd, + txl->aov_surface_accum[aov_index], + sldata->renderpass_ubo.aovs[aov_index]); + } + } + /* Free unused aov textures. */ + for (int aov_index = pd->num_aovs_used; aov_index < MAX_AOVS; aov_index++) { + DRW_TEXTURE_FREE_SAFE(txl->aov_surface_accum[aov_index]); + } /* Restore default. */ pd->renderpass_ubo = sldata->renderpass_ubo.combined; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index f5cef8f3c25..a6a480ca967 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -53,6 +53,7 @@ extern struct DrawEngineType draw_engine_eevee_type; #define MAX_SHADOW_CASCADE 8 #define MAX_SHADOW_CUBE (MAX_SHADOW - MAX_CASCADE_NUM * MAX_SHADOW_CASCADE) #define MAX_BLOOM_STEP 16 +#define MAX_AOVS 64 // #define DEBUG_SHADOW_DISTRIBUTION @@ -163,7 +164,10 @@ BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d) #define EEVEE_RENDERPASSES_MATERIAL \ (EEVEE_RENDER_PASS_EMIT | EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_DIFFUSE_LIGHT | \ EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_SPECULAR_LIGHT | \ - EEVEE_RENDER_PASS_ENVIRONMENT) + EEVEE_RENDER_PASS_ENVIRONMENT | EEVEE_RENDER_PASS_AOV) +#define EEVEE_AOV_HASH_ALL -1 +#define EEVEE_AOV_HASH_COLOR_TYPE_MASK 1 +#define MAX_CRYPTOMATTE_LAYERS 3 /* Material shader variations */ enum { @@ -293,6 +297,7 @@ typedef struct EEVEE_PassList { /* Renderpass Accumulation. */ struct DRWPass *material_accum_ps; struct DRWPass *background_accum_ps; + struct DRWPass *cryptomatte_ps; struct DRWPass *depth_ps; struct DRWPass *depth_cull_ps; @@ -325,6 +330,7 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP]; struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1]; struct GPUFrameBuffer *bloom_pass_accum_fb; + struct GPUFrameBuffer *cryptomatte_fb; struct GPUFrameBuffer *shadow_accum_fb; struct GPUFrameBuffer *ssr_accum_fb; struct GPUFrameBuffer *sss_blur_fb; @@ -376,10 +382,12 @@ typedef struct EEVEE_TextureList { struct GPUTexture *diff_light_accum; struct GPUTexture *spec_color_accum; struct GPUTexture *spec_light_accum; + struct GPUTexture *aov_surface_accum[MAX_AOVS]; struct GPUTexture *emit_accum; struct GPUTexture *bloom_accum; struct GPUTexture *ssr_accum; struct GPUTexture *shadow_accum; + struct GPUTexture *cryptomatte; struct GPUTexture *refract_color; struct GPUTexture *taa_history; @@ -430,7 +438,9 @@ typedef struct EEVEE_RenderPassData { int renderPassEmit; int renderPassSSSColor; int renderPassEnvironment; - int _pad[1]; + int renderPassAOV; + int renderPassAOVActive; + int _pad[3]; } EEVEE_RenderPassData; /* ************ LIGHT UBO ************* */ @@ -860,6 +870,7 @@ typedef struct EEVEE_ViewLayerData { struct GPUUniformBuf *spec_color; struct GPUUniformBuf *spec_light; struct GPUUniformBuf *emit; + struct GPUUniformBuf *aovs[MAX_AOVS]; } renderpass_ubo; /* Common Uniform Buffer */ @@ -904,6 +915,11 @@ typedef struct EEVEE_WorldEngineData { DrawData dd; } EEVEE_WorldEngineData; +typedef struct EEVEE_CryptomatteSample { + float hash; + float weight; +} EEVEE_CryptomatteSample; + /* *********************************** */ typedef struct EEVEE_Data { @@ -959,6 +975,12 @@ typedef struct EEVEE_PrivateData { /* Renderpasses */ /* Bitmask containing the active render_passes */ eViewLayerEEVEEPassType render_passes; + int aov_hash; + int num_aovs_used; + bool cryptomatte_accurate_mode; + EEVEE_CryptomatteSample *cryptomatte_accum_buffer; + float *cryptomatte_download_buffer; + /* Uniform references that are referenced inside the `renderpass_pass`. They are updated * to reuse the drawing pass and the shading group. */ int renderpass_type; @@ -1111,6 +1133,7 @@ struct GPUShader *EEVEE_shaders_effect_ambient_occlusion_layer_sh_get(void); struct GPUShader *EEVEE_shaders_effect_ambient_occlusion_debug_sh_get(void); struct GPUShader *EEVEE_shaders_effect_screen_raytrace_sh_get(EEVEE_SSRShaderOptions options); struct GPUShader *EEVEE_shaders_renderpasses_post_process_sh_get(void); +struct GPUShader *EEVEE_shaders_cryptomatte_sh_get(bool is_hair); struct GPUShader *EEVEE_shaders_shadow_sh_get(void); struct GPUShader *EEVEE_shaders_shadow_accum_sh_get(void); struct GPUShader *EEVEE_shaders_subsurface_first_pass_sh_get(void); @@ -1215,6 +1238,30 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata); void EEVEE_bloom_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); void EEVEE_bloom_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +/* eevee_cryptomatte.c */ +void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata); +void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + int tot_samples); +void EEVEE_cryptomatte_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_cryptomatte_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob); +void EEVEE_cryptomatte_particle_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob); +void EEVEE_cryptomatte_object_hair_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob); +void EEVEE_cryptomatte_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_cryptomatte_update_passes(struct RenderEngine *engine, + struct Scene *scene, + struct ViewLayer *view_layer); +void EEVEE_cryptomatte_render_result(struct RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata); +void EEVEE_cryptomatte_free(EEVEE_Data *vedata); + /* eevee_occlusion.c */ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, @@ -1284,10 +1331,12 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, bool post_effect); void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - eViewLayerEEVEEPassType renderpass_type); + eViewLayerEEVEEPassType renderpass_type, + int aov_index); void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_renderpasses_draw_debug(EEVEE_Data *vedata); bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata); +int EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov); /* eevee_temporal_sampling.c */ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 504e4e1d336..2b2ff2e5c90 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -191,6 +191,7 @@ void EEVEE_render_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_subsurface_cache_init(sldata, vedata); EEVEE_temporal_sampling_cache_init(sldata, vedata); EEVEE_volumes_cache_init(sldata, vedata); + EEVEE_cryptomatte_cache_init(sldata, vedata); } /* Used by light cache. in this case engine is NULL. */ @@ -200,9 +201,15 @@ void EEVEE_render_cache(void *vedata, struct Depsgraph *depsgraph) { EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_Data *data = vedata; + EEVEE_StorageList *stl = data->stl; + EEVEE_PrivateData *g_data = stl->g_data; EEVEE_LightProbesInfo *pinfo = sldata->probes; bool cast_shadow = false; + const bool do_cryptomatte = (engine != NULL) && + ((g_data->render_passes & EEVEE_RENDER_PASS_CRYPTOMATTE) != 0); + eevee_id_update(vedata, &ob->id); if (pinfo->vis_data.collection) { @@ -227,14 +234,23 @@ void EEVEE_render_cache(void *vedata, const int ob_visibility = DRW_object_visibility_in_active_context(ob); if (ob_visibility & OB_VISIBLE_PARTICLES) { EEVEE_particle_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + if (do_cryptomatte) { + EEVEE_cryptomatte_particle_hair_cache_populate(data, sldata, ob); + } } if (ob_visibility & OB_VISIBLE_SELF) { if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); + if (do_cryptomatte) { + EEVEE_cryptomatte_cache_populate(data, sldata, ob); + } } else if (ob->type == OB_HAIR) { EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + if (do_cryptomatte) { + EEVEE_cryptomatte_object_hair_cache_populate(data, sldata, ob); + } } else if (ob->type == OB_VOLUME) { Scene *scene = DEG_get_evaluated_scene(depsgraph); @@ -301,7 +317,7 @@ static void eevee_render_result_normal(RenderLayer *rl, } if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_NORMAL) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_NORMAL); + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_NORMAL, 0); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_NORMAL, 3, vedata->fbl->renderpass_fb, vedata); } @@ -321,7 +337,7 @@ static void eevee_render_result_z(RenderLayer *rl, } if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_Z) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_Z); + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_Z, 0); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_Z, 1, vedata->fbl->renderpass_fb, vedata); } @@ -334,7 +350,7 @@ static void eevee_render_result_mist(RenderLayer *rl, EEVEE_ViewLayerData *sldata) { if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_MIST) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_MIST); + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_MIST, 0); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_MIST, 1, vedata->fbl->renderpass_fb, vedata); } @@ -347,7 +363,7 @@ static void eevee_render_result_shadow(RenderLayer *rl, EEVEE_ViewLayerData *sldata) { if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_SHADOW) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_SHADOW); + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_SHADOW, 0); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_SHADOW, 3, vedata->fbl->renderpass_fb, vedata); } @@ -360,7 +376,7 @@ static void eevee_render_result_occlusion(RenderLayer *rl, EEVEE_ViewLayerData *sldata) { if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_AO) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_AO); + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_AO, 0); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_AO, 3, vedata->fbl->renderpass_fb, vedata); } @@ -378,7 +394,7 @@ static void eevee_render_result_bloom(RenderLayer *rl, } if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_BLOOM) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_BLOOM); + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_BLOOM, 0); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_BLOOM, 3, vedata->fbl->renderpass_fb, vedata); } @@ -386,7 +402,7 @@ static void eevee_render_result_bloom(RenderLayer *rl, #define EEVEE_RENDER_RESULT_MATERIAL_PASS(pass_name, eevee_pass_type) \ if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_##eevee_pass_type) != 0) { \ - EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_##eevee_pass_type); \ + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_##eevee_pass_type, 0); \ eevee_render_color_result( \ rl, viewname, rect, RE_PASSNAME_##pass_name, 3, vedata->fbl->renderpass_fb, vedata); \ } @@ -462,8 +478,49 @@ static void eevee_render_result_volume_transmittance(RenderLayer *rl, EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_TRANSMITTANCE, VOLUME_TRANSMITTANCE) } +static void eevee_render_result_aovs(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_AOV) != 0) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + int aov_index = 0; + LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { + if ((aov->flag & AOV_CONFLICT) != 0) { + continue; + } + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_AOV, aov_index); + switch (aov->type) { + case AOV_TYPE_COLOR: + eevee_render_color_result( + rl, viewname, rect, aov->name, 4, vedata->fbl->renderpass_fb, vedata); + break; + case AOV_TYPE_VALUE: + eevee_render_color_result( + rl, viewname, rect, aov->name, 1, vedata->fbl->renderpass_fb, vedata); + } + aov_index++; + } + } +} + #undef EEVEE_RENDER_RESULT_MATERIAL_PASS +static void eevee_render_result_cryptomatte(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_CRYPTOMATTE) != 0) { + EEVEE_cryptomatte_render_result(rl, viewname, rect, vedata, sldata); + } + EEVEE_cryptomatte_free(vedata); +} + static void eevee_render_draw_background(EEVEE_Data *vedata) { EEVEE_FramebufferList *fbl = vedata->fbl; @@ -641,6 +698,8 @@ void EEVEE_render_read_result(EEVEE_Data *vedata, eevee_render_result_bloom(rl, viewname, rect, vedata, sldata); eevee_render_result_volume_scatter(rl, viewname, rect, vedata, sldata); eevee_render_result_volume_transmittance(rl, viewname, rect, vedata, sldata); + eevee_render_result_aovs(rl, viewname, rect, vedata, sldata); + eevee_render_result_cryptomatte(rl, viewname, rect, vedata, sldata); } void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) @@ -675,6 +734,23 @@ void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *v CHECK_PASS_EEVEE(VOLUME_TRANSMITTANCE, SOCK_RGBA, 3, "RGB"); CHECK_PASS_EEVEE(BLOOM, SOCK_RGBA, 3, "RGB"); + LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { + if ((aov->flag & AOV_CONFLICT) != 0) { + continue; + } + switch (aov->type) { + case AOV_TYPE_COLOR: + RE_engine_register_pass(engine, scene, view_layer, aov->name, 4, "RGBA", SOCK_RGBA); + break; + case AOV_TYPE_VALUE: + RE_engine_register_pass(engine, scene, view_layer, aov->name, 1, "X", SOCK_FLOAT); + break; + default: + break; + } + } + EEVEE_cryptomatte_update_passes(engine, scene, view_layer); + #undef CHECK_PASS_LEGACY #undef CHECK_PASS_EEVEE } diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index be73225b348..e7a03c678a8 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -27,6 +27,7 @@ #include "BKE_global.h" /* for G.debug_value */ +#include "BLI_hash.h" #include "BLI_string_utils.h" #include "DEG_depsgraph_query.h" @@ -36,12 +37,13 @@ typedef enum eRenderPassPostProcessType { PASS_POST_UNDEFINED = 0, PASS_POST_ACCUMULATED_COLOR = 1, - PASS_POST_ACCUMULATED_LIGHT = 2, - PASS_POST_ACCUMULATED_VALUE = 3, - PASS_POST_DEPTH = 4, - PASS_POST_AO = 5, - PASS_POST_NORMAL = 6, - PASS_POST_TWO_LIGHT_BUFFERS = 7, + PASS_POST_ACCUMULATED_COLOR_ALPHA = 2, + PASS_POST_ACCUMULATED_LIGHT = 3, + PASS_POST_ACCUMULATED_VALUE = 4, + PASS_POST_DEPTH = 5, + PASS_POST_AO = 6, + PASS_POST_NORMAL = 7, + PASS_POST_TWO_LIGHT_BUFFERS = 8, } eRenderPassPostProcessType; /* bitmask containing all renderpasses that need post-processing */ @@ -70,6 +72,15 @@ bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata) return (g_data->render_passes & ~EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) == 0; } +/* Calculate the hash for an AOV. The least significant bit is used to store the AOV + * type the rest of the bits are used for the name hash. */ +int EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov) +{ + int hash = BLI_hash_string(aov->name); + SET_FLAG_FROM_TEST(hash, aov->type == AOV_TYPE_COLOR, EEVEE_AOV_HASH_COLOR_TYPE_MASK); + return hash; +} + void EEVEE_renderpasses_init(EEVEE_Data *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -81,10 +92,24 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata) if (v3d) { const Scene *scene = draw_ctx->scene; eViewLayerEEVEEPassType render_pass = v3d->shading.render_pass; + g_data->aov_hash = 0; + if (render_pass == EEVEE_RENDER_PASS_BLOOM && ((scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) == 0)) { render_pass = EEVEE_RENDER_PASS_COMBINED; } + if (render_pass == EEVEE_RENDER_PASS_AOV) { + ViewLayerAOV *aov = BLI_findstring( + &view_layer->aovs, v3d->shading.aov_name, offsetof(ViewLayerAOV, name)); + if (aov != NULL) { + g_data->aov_hash = EEVEE_renderpasses_aov_hash(aov); + } + else { + /* AOV not found in view layer. */ + render_pass = EEVEE_RENDER_PASS_COMBINED; + } + } + g_data->render_passes = render_pass; } else { @@ -110,11 +135,16 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata) ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT) #undef ENABLE_FROM_LEGACY + if (DRW_state_is_image_render() && !BLI_listbase_is_empty(&view_layer->aovs)) { + enabled_render_passes |= EEVEE_RENDER_PASS_AOV; + g_data->aov_hash = EEVEE_AOV_HASH_ALL; + } + g_data->render_passes = (enabled_render_passes & EEVEE_RENDERPASSES_ALL) | EEVEE_RENDER_PASS_COMBINED; } - EEVEE_material_renderpasses_init(vedata); + EEVEE_cryptomatte_renderpasses_init(vedata); } void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, @@ -174,6 +204,11 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, DRW_TEXTURE_FREE_SAFE(txl->renderpass); GPU_FRAMEBUFFER_FREE_SAFE(fbl->renderpass_fb); } + + /* Cryptomatte doesn't use the GPU shader for post processing */ + if ((g_data->render_passes & (EEVEE_RENDER_PASS_CRYPTOMATTE)) != 0) { + EEVEE_cryptomatte_output_init(sldata, vedata, tot_samples); + } } void EEVEE_renderpasses_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) @@ -216,7 +251,8 @@ void EEVEE_renderpasses_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve * After invoking this function the active frame-buffer is set to `vedata->fbl->renderpass_fb`. */ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, - eViewLayerEEVEEPassType renderpass_type) + eViewLayerEEVEEPassType renderpass_type, + int aov_index) { EEVEE_PassList *psl = vedata->psl; EEVEE_TextureList *txl = vedata->txl; @@ -311,6 +347,11 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), } break; } + case EEVEE_RENDER_PASS_AOV: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR_ALPHA; + g_data->renderpass_input = txl->aov_surface_accum[aov_index]; + break; + } case EEVEE_RENDER_PASS_BLOOM: { g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; g_data->renderpass_input = txl->bloom_accum; @@ -350,6 +391,9 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, (EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_VOLUME_SCATTER)) != 0) { EEVEE_volumes_output_accumulate(sldata, vedata); } + if ((render_pass & EEVEE_RENDER_PASS_CRYPTOMATTE) != 0) { + EEVEE_cryptomatte_output_accumulate(sldata, vedata); + } } else { if ((render_pass & EEVEE_RENDER_PASS_BLOOM) != 0 && @@ -392,7 +436,7 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } if (is_valid) { - EEVEE_renderpasses_postprocess(sldata, vedata, render_pass); + EEVEE_renderpasses_postprocess(sldata, vedata, render_pass, 0); GPU_framebuffer_bind(dfbl->default_fb); DRW_transform_none(txl->renderpass); } diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index f46a98ed845..7a277c18f01 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -121,6 +121,7 @@ static struct { /* Render Passes */ struct GPUShader *postprocess_sh; + struct GPUShader *cryptomatte_sh[2]; /* Screen Space Reflection */ struct GPUShader *ssr_sh[SSR_MAX_SHADER]; @@ -186,6 +187,7 @@ extern char datatoc_btdf_lut_frag_glsl[]; extern char datatoc_closure_lib_glsl[]; extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_common_utiltex_lib_glsl[]; +extern char datatoc_cryptomatte_frag_glsl[]; extern char datatoc_cubemap_lib_glsl[]; extern char datatoc_default_frag_glsl[]; extern char datatoc_lookdev_world_frag_glsl[]; @@ -695,6 +697,34 @@ GPUShader *EEVEE_shaders_renderpasses_post_process_sh_get(void) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Cryptomatte + * \{ */ + +GPUShader *EEVEE_shaders_cryptomatte_sh_get(bool is_hair) +{ + const int index = is_hair ? 1 : 0; + if (e_data.cryptomatte_sh[index] == NULL) { + DynStr *ds = BLI_dynstr_new(); + BLI_dynstr_append(ds, SHADER_DEFINES); + + if (is_hair) { + BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); + } + else { + BLI_dynstr_append(ds, "#define MESH_SHADER\n"); + } + char *defines = BLI_dynstr_get_cstring(ds); + e_data.cryptomatte_sh[index] = DRW_shader_create_with_shaderlib( + datatoc_surface_vert_glsl, NULL, datatoc_cryptomatte_frag_glsl, e_data.lib, defines); + BLI_dynstr_free(ds); + MEM_freeN(defines); + } + return e_data.cryptomatte_sh[index]; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Screen Raytrace * \{ */ @@ -1428,6 +1458,8 @@ void EEVEE_shaders_free(void) DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh); + DRW_SHADER_FREE_SAFE(e_data.cryptomatte_sh[0]); + DRW_SHADER_FREE_SAFE(e_data.cryptomatte_sh[1]); for (int i = 0; i < 2; i++) { DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[i]); DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[i]); diff --git a/source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl b/source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl new file mode 100644 index 00000000000..1e499dbf991 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/cryptomatte_frag.glsl @@ -0,0 +1,7 @@ +uniform vec4 cryptohash; +out vec4 fragColor; + +void main() +{ + fragColor = cryptohash; +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl index 36cf3cecf40..3e0a5e76d00 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl @@ -1,3 +1,4 @@ +#define EEVEE_AOV_HASH_COLOR_TYPE_MASK 1 /* ---------------------------------------------------------------------- */ /** \name Resources @@ -12,6 +13,8 @@ layout(std140) uniform renderpass_block bool renderPassEmit; bool renderPassSSSColor; bool renderPassEnvironment; + bool renderPassAOV; + int renderPassAOVActive; }; /** \} */ @@ -40,4 +43,14 @@ vec3 render_pass_emission_mask(vec3 emission_light) return renderPassEmit ? emission_light : vec3(0.0); } +bool render_pass_aov_is_color() +{ + return (renderPassAOVActive & EEVEE_AOV_HASH_COLOR_TYPE_MASK) != 0; +} + +int render_pass_aov_hash() +{ + return renderPassAOVActive & ~EEVEE_AOV_HASH_COLOR_TYPE_MASK; +} + /** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index 89a411bc7cb..eb6ca4b9de8 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -4,12 +4,13 @@ #define PASS_POST_UNDEFINED 0 #define PASS_POST_ACCUMULATED_COLOR 1 -#define PASS_POST_ACCUMULATED_LIGHT 2 -#define PASS_POST_ACCUMULATED_VALUE 3 -#define PASS_POST_DEPTH 4 -#define PASS_POST_AO 5 -#define PASS_POST_NORMAL 6 -#define PASS_POST_TWO_LIGHT_BUFFERS 7 +#define PASS_POST_ACCUMULATED_COLOR_ALPHA 2 +#define PASS_POST_ACCUMULATED_LIGHT 3 +#define PASS_POST_ACCUMULATED_VALUE 4 +#define PASS_POST_DEPTH 5 +#define PASS_POST_AO 6 +#define PASS_POST_NORMAL 7 +#define PASS_POST_TWO_LIGHT_BUFFERS 8 uniform int postProcessType; uniform int currentSample; @@ -55,7 +56,7 @@ vec3 safe_divide_even_color(vec3 a, vec3 b) void main() { - vec3 color; + vec4 color = vec4(0.0, 0.0, 0.0, 1.0); ivec2 texel = ivec2(gl_FragCoord.xy); if (postProcessType == PASS_POST_DEPTH) { @@ -66,11 +67,11 @@ void main() else { depth = -get_view_z_from_depth(depth); } - color = vec3(depth); + color.rgb = vec3(depth); } else if (postProcessType == PASS_POST_AO) { float ao_accum = texelFetch(inputBuffer, texel, 0).r; - color = vec3(min(1.0, ao_accum / currentSample)); + color.rgb = vec3(min(1.0, ao_accum / currentSample)); } else if (postProcessType == PASS_POST_NORMAL) { float depth = texelFetch(depthBuffer, texel, 0).r; @@ -80,35 +81,39 @@ void main() if (depth != 1.0 && any(notEqual(encoded_normal, vec2(0.0)))) { vec3 decoded_normal = normal_decode(texelFetch(inputBuffer, texel, 0).rg, vec3(0.0)); vec3 world_normal = mat3(ViewMatrixInverse) * decoded_normal; - color = world_normal; + color.rgb = world_normal; } else { - color = vec3(0.0); + color.rgb = vec3(0.0); } } else if (postProcessType == PASS_POST_ACCUMULATED_VALUE) { float accumulated_value = texelFetch(inputBuffer, texel, 0).r; - color = vec3(accumulated_value / currentSample); + color.rgb = vec3(accumulated_value / currentSample); } else if (postProcessType == PASS_POST_ACCUMULATED_COLOR) { vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; + color.rgb = (accumulated_color / currentSample); + } + else if (postProcessType == PASS_POST_ACCUMULATED_COLOR_ALPHA) { + vec4 accumulated_color = texelFetch(inputBuffer, texel, 0); color = (accumulated_color / currentSample); } else if (postProcessType == PASS_POST_ACCUMULATED_LIGHT) { vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb; vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; - color = safe_divide_even_color(accumulated_light, accumulated_color); + color.rgb = safe_divide_even_color(accumulated_light, accumulated_color); } else if (postProcessType == PASS_POST_TWO_LIGHT_BUFFERS) { vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb + texelFetch(inputSecondLightBuffer, texel, 0).rgb; vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; - color = safe_divide_even_color(accumulated_light, accumulated_color); + color.rgb = safe_divide_even_color(accumulated_light, accumulated_color); } else { /* Output error color: Unknown how to post process this pass. */ - color = vec3(1.0, 0.0, 1.0); + color.rgb = vec3(1.0, 0.0, 1.0); } - fragColor = vec4(color, 1.0); + fragColor = color; } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 368530fde05..519b015a6ad 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -252,7 +252,7 @@ void GPENCIL_cache_init(void *ved) pd->do_fast_drawing = false; pd->obact = draw_ctx->obact; - if (pd->obact && pd->obact->type == OB_GPENCIL) { + if (pd->obact && pd->obact->type == OB_GPENCIL && !(pd->draw_depth_only)) { /* Check if active object has a temp stroke data. */ bGPdata *gpd = (bGPdata *)pd->obact->data; if (gpd->runtime.sbuffer_used > 0) { @@ -498,7 +498,7 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, bool hide_onion = gpl && gpf && gpf->runtime.onion_id != 0 && ((gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN) != 0); - if (hide_material || (!show_stroke && !show_fill) || only_lines || hide_onion) { + if (hide_material || (!show_stroke && !show_fill) || (only_lines && hide_onion) || hide_onion) { return; } diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index d01aaaed8b0..cb65fbd6ae7 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -95,7 +95,7 @@ static DRWShadingGroup *gpencil_vfx_pass_create(const char *name, static void gpencil_vfx_blur(BlurShaderFxData *fx, Object *ob, gpIterVfxData *iter) { - if (fx->radius[0] == 0.0f && fx->radius[1] == 0.0f) { + if ((fx->samples == 0.0f) || (fx->radius[0] == 0.0f && fx->radius[1] == 0.0f)) { return; } diff --git a/source/blender/draw/engines/image/image_private.h b/source/blender/draw/engines/image/image_private.h index ad7ff78cb41..d5821cc5d70 100644 --- a/source/blender/draw/engines/image/image_private.h +++ b/source/blender/draw/engines/image/image_private.h @@ -43,7 +43,7 @@ typedef struct IMAGE_PrivateData { void *lock; struct ImBuf *ibuf; struct Image *image; - struct DRWView* view; + struct DRWView *view; struct GPUTexture *texture; bool owns_texture; diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc index 39d8e45cc19..d365f76aabe 100644 --- a/source/blender/draw/tests/shaders_test.cc +++ b/source/blender/draw/tests/shaders_test.cc @@ -332,6 +332,8 @@ TEST_F(DrawTest, eevee_glsl_shaders_static) EXPECT_NE(EEVEE_shaders_probe_grid_fill_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_probe_planar_downsample_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_renderpasses_post_process_sh_get(), nullptr); + EXPECT_NE(EEVEE_shaders_cryptomatte_sh_get(false), nullptr); + EXPECT_NE(EEVEE_shaders_cryptomatte_sh_get(true), nullptr); EXPECT_NE(EEVEE_shaders_shadow_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_shadow_accum_sh_get(), nullptr); EXPECT_NE(EEVEE_shaders_subsurface_first_pass_sh_get(), nullptr); diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index ba3796ad245..124992bed71 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -49,6 +49,7 @@ #include "BKE_gpencil.h" #include "BKE_lib_id.h" #include "BKE_mask.h" +#include "BKE_nla.h" #include "BKE_scene.h" #include "DEG_depsgraph.h" @@ -1063,18 +1064,27 @@ static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, eAnim_ChannelType type) { ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale, *ale_next; - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + eAnimFilter_Flags filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | + ANIMFILTER_LIST_CHANNELS); /* get all visible channels */ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* now, only keep the ones that are of the types we are interested in */ - for (ale = anim_data.first; ale; ale = ale_next) { - ale_next = ale->next; - + LISTBASE_FOREACH_MUTABLE (bAnimListElem *, ale, &anim_data) { if (ale->type != type) { BLI_freelinkN(&anim_data, ale); + continue; + } + + if (type == ANIMTYPE_NLATRACK) { + NlaTrack *nlt = (NlaTrack *)ale->data; + + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No re-arrangement of non-local tracks of override data. */ + BLI_freelinkN(&anim_data, ale); + continue; + } } } @@ -1146,6 +1156,7 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn { AnimChanRearrangeFp rearrange_func; ListBase anim_data_visible = {NULL, NULL}; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ac->obact); /* hack: invert mode so that functions will work in right order */ mode *= -1; @@ -1156,6 +1167,29 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn return; } + /* In liboverride case, we need to extract non-local NLA tracks from current anim data before we + * can perform the move, and add then back afterwards. It's the only way to prevent them from + * being affected by the reordering. + * + * Note that both override apply code for NLA tracks collection, and NLA editing code, are + * responsible to ensure that non-local tracks always remain first in the list. */ + ListBase extracted_nonlocal_nla_tracks = {NULL, NULL}; + if (is_liboverride) { + NlaTrack *nla_track; + for (nla_track = adt->nla_tracks.first; nla_track != NULL; nla_track = nla_track->next) { + if (!BKE_nlatrack_is_nonlocal_in_liboverride(&ac->obact->id, nla_track)) { + break; + } + } + if (nla_track != NULL && nla_track->prev != NULL) { + extracted_nonlocal_nla_tracks.first = adt->nla_tracks.first; + extracted_nonlocal_nla_tracks.last = nla_track->prev; + adt->nla_tracks.first = nla_track; + nla_track->prev->next = NULL; + nla_track->prev = NULL; + } + } + /* Filter visible data. */ rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK); @@ -1163,6 +1197,14 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn rearrange_animchannel_islands( &adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible); + /* Add back non-local NLA tracks at the begining of the animation data's list. */ + if (!BLI_listbase_is_empty(&extracted_nonlocal_nla_tracks)) { + BLI_assert(is_liboverride); + ((NlaTrack *)extracted_nonlocal_nla_tracks.last)->next = adt->nla_tracks.first; + ((NlaTrack *)adt->nla_tracks.first)->prev = extracted_nonlocal_nla_tracks.last; + adt->nla_tracks.first = extracted_nonlocal_nla_tracks.first; + } + /* free temp data */ BLI_freelistN(&anim_data_visible); } diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index e552a321bca..32ce78e405e 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -216,11 +216,13 @@ static void animchan_sync_fcurve_scene(bAnimListElem *ale) /* get strip name, and check if this strip is selected */ char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - Sequence *seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); - if (seq_name) { - MEM_freeN(seq_name); + if (seq_name == NULL) { + return; } + Sequence *seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); + MEM_freeN(seq_name); + if (seq == NULL) { return; } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 2e65fff69f1..f4a487140ff 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1063,13 +1063,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id /* only consider if F-Curve involves pose.bones */ if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) { - bPoseChannel *pchan; - char *bone_name; /* get bone-name, and check if this bone is selected */ - bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + bPoseChannel *pchan = NULL; + char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (bone_name) { + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); } @@ -1106,13 +1105,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = NULL; - char *seq_name; if (ed) { /* get strip name, and check if this strip is selected */ - seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); + char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); if (seq_name) { + seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, false); MEM_freeN(seq_name); } } @@ -1130,13 +1128,12 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id /* check for selected nodes */ if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) { - bNode *node; - char *node_name; + bNode *node = NULL; /* get strip name, and check if this strip is selected */ - node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes["); - node = nodeFindNodebyName(ntree, node_name); + char *node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes["); if (node_name) { + node = nodeFindNodebyName(ntree, node_name); MEM_freeN(node_name); } diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index 72103d68b05..5992545bdbe 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -112,7 +112,8 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints["); /* assemble the string to display in the UI... */ - structname = BLI_sprintfN("%s : %s", pchanName, constName); + structname = BLI_sprintfN( + "%s : %s", pchanName ? pchanName : "", constName ? constName : ""); free_structname = 1; /* free the temp names */ diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 08b02020f76..6ed9803dbd3 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -767,16 +767,15 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) * Storing the relevant information here helps avoiding crashes if we undo-repaste. */ if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) { Object *ob = (Object *)aci->id; - bPoseChannel *pchan; - char *bone_name; - bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); - if (pchan) { - aci->is_bone = true; - } + char *bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); if (bone_name) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); + + if (pchan) { + aci->is_bone = true; + } } } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 09c33c48170..e8146ca960a 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -2236,20 +2236,18 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op)) /* in pose mode, only delete the F-Curve if it belongs to a selected bone */ if (ob->mode & OB_MODE_POSE) { if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) { - bPoseChannel *pchan; - char *bone_name; /* get bone-name, and check if this bone is selected */ - bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (bone_name) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); - } - /* delete if bone is selected*/ - if ((pchan) && (pchan->bone)) { - if (pchan->bone->flag & BONE_SELECTED) { - can_delete = true; + /* delete if bone is selected*/ + if ((pchan) && (pchan->bone)) { + if (pchan->bone->flag & BONE_SELECTED) { + can_delete = true; + } } } } @@ -2342,13 +2340,12 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op) * In object mode, we're dealing with the entire object. */ if ((ob->mode & OB_MODE_POSE) && strstr(fcu->rna_path, "pose.bones[\"")) { - bPoseChannel *pchan; - char *bone_name; + bPoseChannel *pchan = NULL; /* get bone-name, and check if this bone is selected */ - bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (bone_name) { + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); MEM_freeN(bone_name); } diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index fde062b8454..af323bf91e4 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -453,10 +453,13 @@ static void updateDuplicateActionConstraintSettings(EditBone *dup_bone, float mat[4][4]; + bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = NULL}; + BKE_constraint_custom_object_space_get(cob.space_obj_world_matrix, curcon); + unit_m4(mat); bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, act_con->subtarget); BKE_constraint_mat_convertspace( - ob, target_pchan, mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false); + ob, target_pchan, &cob, mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false); float max_axis_val = 0; int max_axis = 0; @@ -605,8 +608,11 @@ static void updateDuplicateLocRotConstraintSettings(Object *ob, unit_m4(local_mat); + bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan}; + BKE_constraint_custom_object_space_get(cob.space_obj_world_matrix, curcon); + BKE_constraint_mat_convertspace( - ob, pchan, local_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false); + ob, pchan, &cob, local_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false); if (curcon->type == CONSTRAINT_TYPE_ROTLIMIT) { /* Zero out any location translation */ @@ -657,9 +663,12 @@ static void updateDuplicateTransformConstraintSettings(Object *ob, float target_mat[4][4], own_mat[4][4], imat[4][4]; + bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan}; + BKE_constraint_custom_object_space_get(cob.space_obj_world_matrix, curcon); + unit_m4(own_mat); BKE_constraint_mat_convertspace( - ob, pchan, own_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false); + ob, pchan, &cob, own_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false); /* ###Source map mirroring### */ float old_min, old_max; @@ -717,7 +726,7 @@ static void updateDuplicateTransformConstraintSettings(Object *ob, bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, trans->subtarget); unit_m4(target_mat); BKE_constraint_mat_convertspace( - ob, target_pchan, target_mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false); + ob, target_pchan, &cob, target_mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false); invert_m4_m4(imat, target_mat); /* convert values into local object space */ diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 731d0d10e0b..6a03207b3b0 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -1090,6 +1090,7 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex if (boneName) { bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName); + MEM_freeN(boneName); if (pchan) { /* select if bone is visible and can be affected */ @@ -1098,9 +1099,6 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex changed = true; } } - - /* free temp memory */ - MEM_freeN(boneName); } } } diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index e374010cf44..337fb18f835 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -791,6 +791,7 @@ if(WITH_BLENDER) # images data_to_c_simple(../../../../release/datafiles/splash.png SRC) data_to_c_simple(../../../../release/datafiles/alert_icons.png SRC) + data_to_c_simple(../../../../release/datafiles/blender_logo.png SRC) # XXX These are handy, but give nasty "false changes" in svn :/ # svg_to_png(../../../../release/datafiles/blender_icons.svg # ../../../../release/datafiles/blender_icons16.png diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c index f7caf8e4c6a..8755dea51e1 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c @@ -50,7 +50,6 @@ #include "WM_api.h" #include "WM_types.h" -#include "wm.h" /* own includes */ #include "../gizmo_geometry.h" @@ -66,7 +65,13 @@ typedef struct SnapGizmo3D { /* We could have other snap contexts, for now only support 3D view. */ SnapObjectContext *snap_context_v3d; - int mval[2]; + + /* Copy of the parameters of the last event state in order to detect updates. */ + struct { + int x; + int y; + short shift, ctrl, alt, oskey; + } last_eventstate; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmKeyMap *keymap; @@ -77,6 +82,37 @@ typedef struct SnapGizmo3D { short snap_elem; } SnapGizmo3D; +/* Checks if the current event is different from the one captured in the last update. */ +static bool eventstate_has_changed(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) +{ + if (wm && wm->winactive) { + const wmEvent *event = wm->winactive->eventstate; + if ((event->x != snap_gizmo->last_eventstate.x) || + (event->y != snap_gizmo->last_eventstate.y) || + (event->ctrl != snap_gizmo->last_eventstate.ctrl) || + (event->shift != snap_gizmo->last_eventstate.shift) || + (event->alt != snap_gizmo->last_eventstate.alt) || + (event->oskey != snap_gizmo->last_eventstate.oskey)) { + return true; + } + } + return false; +} + +/* Copies the current eventstate. */ +static void eventstate_save(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) +{ + if (wm && wm->winactive) { + const wmEvent *event = wm->winactive->eventstate; + snap_gizmo->last_eventstate.x = event->x; + snap_gizmo->last_eventstate.y = event->y; + snap_gizmo->last_eventstate.ctrl = event->ctrl; + snap_gizmo->last_eventstate.shift = event->shift; + snap_gizmo->last_eventstate.alt = event->alt; + snap_gizmo->last_eventstate.oskey = event->oskey; + } +} + #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) { @@ -84,6 +120,15 @@ static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) return false; } + const wmEvent *event = wm->winactive->eventstate; + if ((event->ctrl == snap_gizmo->last_eventstate.ctrl) && + (event->shift == snap_gizmo->last_eventstate.shift) && + (event->alt == snap_gizmo->last_eventstate.alt) && + (event->oskey == snap_gizmo->last_eventstate.oskey)) { + /* Nothing has changed. */ + return snap_gizmo->invert_snap; + } + if (snap_gizmo->keymap == NULL) { /* Lazy initialization. */ snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); @@ -92,7 +137,6 @@ static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) const int snap_on = snap_gizmo->snap_on; wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap); - const wmEvent *event = wm->winactive->eventstate; for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { if (kmi->flag & KMI_INACTIVE) { continue; @@ -250,12 +294,6 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, float r_nor[3]) { SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; - Scene *scene = DEG_get_input_scene(depsgraph); - float co[3], no[3]; - short snap_elem = 0; - int snap_elem_index[3] = {-1, -1, -1}; - int index = -1; - if (snap_gizmo->use_snap_override != -1) { if (snap_gizmo->use_snap_override == false) { snap_gizmo->snap_elem = 0; @@ -265,7 +303,12 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm); +#endif + eventstate_save(snap_gizmo, wm); + Scene *scene = DEG_get_input_scene(depsgraph); + +#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK if (snap_gizmo->use_snap_override == -1) { const ToolSettings *ts = scene->toolsettings; if (snap_gizmo->invert_snap != !(ts->snap_flag & SCE_SNAP)) { @@ -273,10 +316,13 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz, return 0; } } -#else - UNUSED_VARS(wm); #endif + float co[3], no[3]; + short snap_elem = 0; + int snap_elem_index[3] = {-1, -1, -1}; + int index = -1; + wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "snap_elements"); int snap_elements = RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop); if (gz_prop->prop != snap_gizmo->prop_snap_force) { @@ -381,14 +427,17 @@ static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) return; } - ARegion *region = CTX_wm_region(C); - RegionView3D *rv3d = region->regiondata; + wmWindowManager *wm = CTX_wm_manager(C); + if (eventstate_has_changed(snap_gizmo, wm)) { + /* The eventstate has changed but the snap has not been updated. + * This means that the current position is no longer valid. */ + snap_gizmo->snap_elem = 0; + return; + } - /* Ideally, we shouldn't assign values here. - * But `test_select` is not called during navigation. - * And `snap_elem` is not really useful in this case. */ - if ((rv3d->rflag & RV3D_NAVIGATING) || - (!(gz->state & WM_GIZMO_STATE_HIGHLIGHT) && !wm_gizmomap_modal_get(region->gizmo_map))) { + RegionView3D *rv3d = CTX_wm_region_data(C); + if (rv3d->rflag & RV3D_NAVIGATING) { + /* Don't draw the gizmo while navigating. It can be distracting. */ snap_gizmo->snap_elem = 0; return; } @@ -418,30 +467,17 @@ static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; - -#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmWindowManager *wm = CTX_wm_manager(C); - const bool invert = invert_snap(snap_gizmo, wm); - if (snap_gizmo->invert_snap == invert && snap_gizmo->mval[0] == mval[0] && - snap_gizmo->mval[1] == mval[1]) { + if (!eventstate_has_changed(snap_gizmo, wm)) { /* Performance, do not update. */ return snap_gizmo->snap_elem ? 0 : -1; } - snap_gizmo->invert_snap = invert; -#else - if (snap_gizmo->mval[0] == mval[0] && snap_gizmo->mval[1] == mval[1]) { - /* Performance, do not update. */ - return snap_gizmo->snap_elem ? 0 : -1; - } -#endif - copy_v2_v2_int(snap_gizmo->mval, mval); - ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); const float mval_fl[2] = {UNPACK2(mval)}; short snap_elem = ED_gizmotypes_snap_3d_update( - gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, mval_fl, NULL, NULL); + gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, wm, mval_fl, NULL, NULL); if (snap_elem) { ED_region_tag_redraw_editor_overlays(region); diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 33b02d525d5..63aa242275a 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1312,7 +1312,7 @@ static void gpencil_layer_to_curve(bContext *C, Scene *scene = CTX_data_scene(C); bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_USE_PREV); - bGPDstroke *gps, *prev_gps = NULL; + bGPDstroke *prev_gps = NULL; Object *ob; Curve *cu; Nurb *nu = NULL; @@ -1353,7 +1353,10 @@ static void gpencil_layer_to_curve(bContext *C, gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; /* add points to curve */ - for (gps = gpf->strokes.first; gps; gps = gps->next) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if (gps->totpoints < 1) { + continue; + } const bool add_start_point = (link_strokes && !(prev_gps)); const bool add_end_point = (link_strokes && !(gps->next)); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index a963632a01b..33a1469beab 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -1586,6 +1586,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) gps = link->data; BLI_remlink(&gpf->strokes, gps); BLI_addtail(&gpf->strokes, gps); + changed = true; } break; /* Bring Forward */ @@ -1593,6 +1594,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH_BACKWARD (LinkData *, link, &selected) { gps = link->data; BLI_listbase_link_move(&gpf->strokes, gps, 1); + changed = true; } break; /* Send Backward */ @@ -1600,6 +1602,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (LinkData *, link, &selected) { gps = link->data; BLI_listbase_link_move(&gpf->strokes, gps, -1); + changed = true; } break; /* Send to Back */ @@ -1608,12 +1611,12 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) gps = link->data; BLI_remlink(&gpf->strokes, gps); BLI_addhead(&gpf->strokes, gps); + changed = true; } break; default: BLI_assert(0); break; - changed = true; } } BLI_freelistN(&selected); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 15162f491d5..95c94f8cfed 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -3577,7 +3577,7 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) if (tot_strokes == max_join_strokes) { BKE_reportf(op->reports, RPT_WARNING, - "Too many strokes selected. Only joined first %d strokes.", + "Too many strokes selected, only joined first %d strokes", max_join_strokes); break; } @@ -5206,158 +5206,3 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Reset Stroke Vertex Color Operator - * \{ */ - -static void gpencil_reset_vertex(bGPDstroke *gps, eGp_Vertex_Mode mode) -{ - if (mode != GPPAINT_MODE_STROKE) { - zero_v4(gps->vert_color_fill); - } - - if (mode != GPPAINT_MODE_FILL) { - bGPDspoint *pt; - for (int i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - zero_v4(pt->vert_color); - } - } -} - -static int gpencil_stroke_reset_vertex_color_exec(bContext *C, wmOperator *op) -{ - Object *obact = CTX_data_active_object(C); - bGPdata *gpd = (bGPdata *)obact->data; - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - bGPDstroke *gps = NULL; - - if (gpd == NULL) { - BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); - return OPERATOR_CANCELLED; - } - eGp_Vertex_Mode mode = RNA_enum_get(op->ptr, "mode"); - - /* First need to check if there are something selected. If not, apply to all strokes. */ - bool all_strokes = true; - CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { - bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; - for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { - if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { - if (gpf == NULL) { - continue; - } - for (gps = gpf->strokes.first; gps; gps = gps->next) { - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - - if (is_curve_edit) { - if (gps->editcurve == NULL) { - continue; - } - bGPDcurve *gpc = gps->editcurve; - if (gpc->flag & GP_CURVE_SELECT) { - all_strokes = false; - break; - } - } - else { - if (gps->flag & GP_STROKE_SELECT) { - all_strokes = false; - break; - } - } - } - /* if not multiedit, exit loop*/ - if (!is_multiedit) { - break; - } - } - } - } - CTX_DATA_END; - - /* Reset Vertex colors. */ - bool changed = false; - CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { - bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; - - for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { - if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { - if (gpf == NULL) { - continue; - } - - for (gps = gpf->strokes.first; gps; gps = gps->next) { - /* skip strokes that are invalid for current view */ - if (ED_gpencil_stroke_can_use(C, gps) == false) { - continue; - } - - if (is_curve_edit) { - if (gps->editcurve == NULL) { - continue; - } - bGPDcurve *gpc = gps->editcurve; - if ((all_strokes) || (gpc->flag & GP_CURVE_SELECT)) { - gpencil_reset_vertex(gps, mode); - } - } - else { - if ((all_strokes) || (gps->flag & GP_STROKE_SELECT)) { - gpencil_reset_vertex(gps, mode); - } - } - - changed = true; - } - /* if not multiedit, exit loop*/ - if (!is_multiedit) { - break; - } - } - } - } - CTX_DATA_END; - - if (changed) { - /* updates */ - DEG_id_tag_update(&gpd->id, - ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); - DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - } - - return OPERATOR_FINISHED; -} - -void GPENCIL_OT_stroke_reset_vertex_color(wmOperatorType *ot) -{ - static EnumPropertyItem mode_types_items[] = { - {GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Reset Vertex Color to Stroke only"}, - {GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Reset Vertex Color to Fill only"}, - {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", "Reset Vertex Color to Stroke and Fill"}, - {0, NULL, 0, NULL, NULL}, - }; - - /* identifiers */ - ot->name = "Reset Vertex Color"; - ot->idname = "GPENCIL_OT_stroke_reset_vertex_color"; - ot->description = "Reset vertex color for all or selected strokes"; - - /* callbacks */ - ot->exec = gpencil_stroke_reset_vertex_color_exec; - ot->poll = gpencil_stroke_edit_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "mode", mode_types_items, GPPAINT_MODE_BOTH, "Mode", ""); -} - -/** \} */ diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index 69e50beb66e..c3fd8d10b64 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -60,23 +60,69 @@ #include "gpencil_intern.h" -enum { - GP_PAINT_VERTEX_STROKE = 0, - GP_PAINT_VERTEX_FILL = 1, - GP_PAINT_VERTEX_BOTH = 2, -}; - static const EnumPropertyItem gpencil_modesEnumPropertyItem_mode[] = { - {GP_PAINT_VERTEX_STROKE, "STROKE", 0, "Stroke", ""}, - {GP_PAINT_VERTEX_FILL, "FILL", 0, "Fill", ""}, - {GP_PAINT_VERTEX_BOTH, "BOTH", 0, "Both", ""}, + {GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", ""}, + {GPPAINT_MODE_FILL, "FILL", 0, "Fill", ""}, + {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", ""}, {0, NULL, 0, NULL, NULL}, }; +/* Helper: Check if any stroke is selected. */ +static bool is_any_stroke_selected(bContext *C, const bool is_multiedit, const bool is_curve_edit) +{ + bool is_selected = false; + + /* If not enabled any mask mode, the strokes are considered as not selected. */ + ToolSettings *ts = CTX_data_tool_settings(C); + if (!GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex)) { + return false; + } + + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + + if (is_curve_edit) { + if (gps->editcurve == NULL) { + continue; + } + bGPDcurve *gpc = gps->editcurve; + if (gpc->flag & GP_CURVE_SELECT) { + is_selected = true; + break; + } + } + else { + if (gps->flag & GP_STROKE_SELECT) { + is_selected = true; + break; + } + } + } + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } + } + } + } + CTX_DATA_END; + + return is_selected; +} + /* Poll callback for stroke vertex paint operator. */ static bool gpencil_vertexpaint_mode_poll(bContext *C) { - ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); if ((ob == NULL) || (ob->type != OB_GPENCIL)) { return false; @@ -84,10 +130,6 @@ static bool gpencil_vertexpaint_mode_poll(bContext *C) bGPdata *gpd = (bGPdata *)ob->data; if (GPENCIL_VERTEX_MODE(gpd)) { - if (!(GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex))) { - return false; - } - /* Any data to use. */ if (gpd->layers.first) { return true; @@ -101,10 +143,9 @@ static int gpencil_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator { Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; - bool changed = false; - int i; - bGPDspoint *pt; - const int mode = RNA_enum_get(op->ptr, "mode"); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const eGp_Vertex_Mode mode = RNA_enum_get(op->ptr, "mode"); + const bool any_selected = is_any_stroke_selected(C, is_multiedit, false); float gain, offset; { @@ -130,34 +171,56 @@ static int gpencil_vertexpaint_brightness_contrast_exec(bContext *C, wmOperator } /* Loop all selected strokes. */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - if (gps->flag & GP_STROKE_SELECT) { - changed = true; - /* Fill color. */ - if (gps->flag & GP_STROKE_SELECT) { - changed = true; - if (mode != GP_PAINT_VERTEX_STROKE) { - if (gps->vert_color_fill[3] > 0.0f) { - for (int i2 = 0; i2 < 3; i2++) { - gps->vert_color_fill[i2] = gain * gps->vert_color_fill[i2] + offset; - } - } + bool changed = false; + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; } - } - /* Stroke points. */ - if (mode != GP_PAINT_VERTEX_FILL) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) { - for (int i2 = 0; i2 < 3; i2++) { - pt->vert_color[i2] = gain * pt->vert_color[i2] + offset; + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + + if ((!any_selected) || (gps->flag & GP_STROKE_SELECT)) { + /* Fill color. */ + if (mode != GPPAINT_MODE_STROKE) { + if (gps->vert_color_fill[3] > 0.0f) { + changed = true; + for (int i2 = 0; i2 < 3; i2++) { + gps->vert_color_fill[i2] = gain * gps->vert_color_fill[i2] + offset; + } + } + } + /* Stroke points. */ + if (mode != GPPAINT_MODE_FILL) { + changed = true; + int i; + bGPDspoint *pt; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (((!any_selected) || (pt->flag & GP_SPOINT_SELECT)) && + (pt->vert_color[3] > 0.0f)) { + for (int i2 = 0; i2 < 3; i2++) { + pt->vert_color[i2] = gain * pt->vert_color[i2] + offset; + } + } + } } } } + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } } } } - GP_EDITABLE_STROKES_END(gpstroke_iter); + CTX_DATA_END; /* notifiers */ if (changed) { @@ -185,7 +248,8 @@ void GPENCIL_OT_vertex_color_brightness_contrast(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* params */ - ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", ""); + ot->prop = RNA_def_enum( + ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, GPPAINT_MODE_BOTH, "Mode", ""); const float min = -100, max = +100; prop = RNA_def_float(ot->srna, "brightness", 0.0f, min, max, "Brightness", "", min, max); prop = RNA_def_float(ot->srna, "contrast", 0.0f, min, max, "Contrast", "", min, max); @@ -197,64 +261,88 @@ static int gpencil_vertexpaint_hsv_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; - bool changed = false; - int i; - bGPDspoint *pt; - float hsv[3]; - - const int mode = RNA_enum_get(op->ptr, "mode"); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const eGp_Vertex_Mode mode = RNA_enum_get(op->ptr, "mode"); + const bool any_selected = is_any_stroke_selected(C, is_multiedit, false); float hue = RNA_float_get(op->ptr, "h"); float sat = RNA_float_get(op->ptr, "s"); float val = RNA_float_get(op->ptr, "v"); - /* Loop all selected strokes. */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - if (gps->flag & GP_STROKE_SELECT) { - changed = true; - - /* Fill color. */ - if (mode != GP_PAINT_VERTEX_STROKE) { - if (gps->vert_color_fill[3] > 0.0f) { + bool changed = false; + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; - rgb_to_hsv_v(gps->vert_color_fill, hsv); + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } - hsv[0] += (hue - 0.5f); - if (hsv[0] > 1.0f) { - hsv[0] -= 1.0f; - } - else if (hsv[0] < 0.0f) { - hsv[0] += 1.0f; + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; } - hsv[1] *= sat; - hsv[2] *= val; - hsv_to_rgb_v(hsv, gps->vert_color_fill); - } - } + if ((!any_selected) || (gps->flag & GP_STROKE_SELECT)) { + float hsv[3]; - /* Stroke points. */ - if (mode != GP_PAINT_VERTEX_FILL) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) { - rgb_to_hsv_v(pt->vert_color, hsv); + /* Fill color. */ + if (mode != GPPAINT_MODE_STROKE) { + if (gps->vert_color_fill[3] > 0.0f) { + changed = true; - hsv[0] += (hue - 0.5f); - if (hsv[0] > 1.0f) { - hsv[0] -= 1.0f; - } - else if (hsv[0] < 0.0f) { - hsv[0] += 1.0f; + rgb_to_hsv_v(gps->vert_color_fill, hsv); + + hsv[0] += (hue - 0.5f); + if (hsv[0] > 1.0f) { + hsv[0] -= 1.0f; + } + else if (hsv[0] < 0.0f) { + hsv[0] += 1.0f; + } + hsv[1] *= sat; + hsv[2] *= val; + + hsv_to_rgb_v(hsv, gps->vert_color_fill); + } } - hsv[1] *= sat; - hsv[2] *= val; - hsv_to_rgb_v(hsv, pt->vert_color); + /* Stroke points. */ + if (mode != GPPAINT_MODE_FILL) { + changed = true; + int i; + bGPDspoint *pt; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (((!any_selected) || (pt->flag & GP_SPOINT_SELECT)) && + (pt->vert_color[3] > 0.0f)) { + rgb_to_hsv_v(pt->vert_color, hsv); + + hsv[0] += (hue - 0.5f); + if (hsv[0] > 1.0f) { + hsv[0] -= 1.0f; + } + else if (hsv[0] < 0.0f) { + hsv[0] += 1.0f; + } + hsv[1] *= sat; + hsv[2] *= val; + + hsv_to_rgb_v(hsv, pt->vert_color); + } + } + } } } + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } } } } - GP_EDITABLE_STROKES_END(gpstroke_iter); + + CTX_DATA_END; /* notifiers */ if (changed) { @@ -280,7 +368,8 @@ void GPENCIL_OT_vertex_color_hsv(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* params */ - ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", ""); + ot->prop = RNA_def_enum( + ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, GPPAINT_MODE_BOTH, "Mode", ""); RNA_def_float(ot->srna, "h", 0.5f, 0.0f, 1.0f, "Hue", "", 0.0f, 1.0f); RNA_def_float(ot->srna, "s", 1.0f, 0.0f, 2.0f, "Saturation", "", 0.0f, 2.0f); RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f); @@ -291,41 +380,62 @@ static int gpencil_vertexpaint_invert_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const eGp_Vertex_Mode mode = RNA_enum_get(op->ptr, "mode"); + const bool any_selected = is_any_stroke_selected(C, is_multiedit, false); + bool changed = false; - int i; - bGPDspoint *pt; + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; - const int mode = RNA_enum_get(op->ptr, "mode"); + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } - /* Loop all selected strokes. */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - if (gps->flag & GP_STROKE_SELECT) { - changed = true; - /* Fill color. */ - if (gps->flag & GP_STROKE_SELECT) { - changed = true; - if (mode != GP_PAINT_VERTEX_STROKE) { - if (gps->vert_color_fill[3] > 0.0f) { - for (int i2 = 0; i2 < 3; i2++) { - gps->vert_color_fill[i2] = 1.0f - gps->vert_color_fill[i2]; - } + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; } - } - } - /* Stroke points. */ - if (mode != GP_PAINT_VERTEX_FILL) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) { - for (int i2 = 0; i2 < 3; i2++) { - pt->vert_color[i2] = 1.0f - pt->vert_color[i2]; + if ((!any_selected) || (gps->flag & GP_STROKE_SELECT)) { + /* Fill color. */ + if (mode != GPPAINT_MODE_STROKE) { + if (gps->vert_color_fill[3] > 0.0f) { + changed = true; + for (int i2 = 0; i2 < 3; i2++) { + gps->vert_color_fill[i2] = 1.0f - gps->vert_color_fill[i2]; + } + } + } + + /* Stroke points. */ + if (mode != GPPAINT_MODE_FILL) { + changed = true; + int i; + bGPDspoint *pt; + + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (((!any_selected) || (pt->flag & GP_SPOINT_SELECT)) && + (pt->vert_color[3] > 0.0f)) { + for (int i2 = 0; i2 < 3; i2++) { + pt->vert_color[i2] = 1.0f - pt->vert_color[i2]; + } + } + } } } } + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } } } } - GP_EDITABLE_STROKES_END(gpstroke_iter); + CTX_DATA_END; /* notifiers */ if (changed) { @@ -351,7 +461,8 @@ void GPENCIL_OT_vertex_color_invert(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* params */ - ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", ""); + ot->prop = RNA_def_enum( + ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, GPPAINT_MODE_BOTH, "Mode", ""); } static int gpencil_vertexpaint_levels_exec(bContext *C, wmOperator *op) @@ -359,41 +470,63 @@ static int gpencil_vertexpaint_levels_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); bGPdata *gpd = (bGPdata *)ob->data; - bool changed = false; - bGPDspoint *pt; - - const int mode = RNA_enum_get(op->ptr, "mode"); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const eGp_Vertex_Mode mode = RNA_enum_get(op->ptr, "mode"); + const bool any_selected = is_any_stroke_selected(C, is_multiedit, false); float gain = RNA_float_get(op->ptr, "gain"); float offset = RNA_float_get(op->ptr, "offset"); - /* Loop all selected strokes. */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + bool changed = false; + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; - /* Fill color. */ - if (gps->flag & GP_STROKE_SELECT) { - changed = true; - if (mode != GP_PAINT_VERTEX_STROKE) { - if (gps->vert_color_fill[3] > 0.0f) { - for (int i2 = 0; i2 < 3; i2++) { - gps->vert_color_fill[i2] = gain * (gps->vert_color_fill[i2] + offset); - } + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; } - } - } - /* Stroke points. */ - if (mode != GP_PAINT_VERTEX_FILL) { - int i; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((pt->flag & GP_SPOINT_SELECT) && (pt->vert_color[3] > 0.0f)) { - for (int i2 = 0; i2 < 3; i2++) { - pt->vert_color[i2] = gain * (pt->vert_color[i2] + offset); + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; } + + if ((!any_selected) || (gps->flag & GP_STROKE_SELECT)) { + /* Fill color. */ + if (mode != GPPAINT_MODE_STROKE) { + if (gps->vert_color_fill[3] > 0.0f) { + changed = true; + for (int i2 = 0; i2 < 3; i2++) { + gps->vert_color_fill[i2] = gain * (gps->vert_color_fill[i2] + offset); + } + } + } + /* Stroke points. */ + if (mode != GPPAINT_MODE_FILL) { + changed = true; + int i; + bGPDspoint *pt; + + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (((!any_selected) || (pt->flag & GP_SPOINT_SELECT)) && + (pt->vert_color[3] > 0.0f)) { + for (int i2 = 0; i2 < 3; i2++) { + pt->vert_color[i2] = gain * (pt->vert_color[i2] + offset); + } + } + } + } + } + } + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; } } } } - GP_EDITABLE_STROKES_END(gpstroke_iter); + CTX_DATA_END; /* notifiers */ if (changed) { @@ -420,7 +553,8 @@ void GPENCIL_OT_vertex_color_levels(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* params */ - ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", ""); + ot->prop = RNA_def_enum( + ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, GPPAINT_MODE_BOTH, "Mode", ""); RNA_def_float( ot->srna, "offset", 0.0f, -1.0f, 1.0f, "Offset", "Value to add to colors", -1.0f, 1.0f); @@ -436,36 +570,58 @@ static int gpencil_vertexpaint_set_exec(bContext *C, wmOperator *op) Paint *paint = &ts->gp_vertexpaint->paint; Brush *brush = paint->brush; + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const eGp_Vertex_Mode mode = RNA_enum_get(op->ptr, "mode"); + const bool any_selected = is_any_stroke_selected(C, is_multiedit, false); + float factor = RNA_float_get(op->ptr, "factor"); + bool changed = false; - int i; - bGPDspoint *pt; + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; - const int mode = RNA_enum_get(op->ptr, "mode"); - float factor = RNA_float_get(op->ptr, "factor"); + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } - /* Loop all selected strokes. */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - - /* Fill color. */ - if (gps->flag & GP_STROKE_SELECT) { - changed = true; - if (mode != GP_PAINT_VERTEX_STROKE) { - copy_v3_v3(gps->vert_color_fill, brush->rgb); - gps->vert_color_fill[3] = factor; - } - } + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } - /* Stroke points. */ - if (mode != GP_PAINT_VERTEX_FILL) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) { - copy_v3_v3(pt->vert_color, brush->rgb); - pt->vert_color[3] = factor; + if ((!any_selected) || (gps->flag & GP_STROKE_SELECT)) { + /* Fill color. */ + if (mode != GPPAINT_MODE_STROKE) { + changed = true; + copy_v3_v3(gps->vert_color_fill, brush->rgb); + gps->vert_color_fill[3] = factor; + } + + /* Stroke points. */ + if (mode != GPPAINT_MODE_FILL) { + changed = true; + int i; + bGPDspoint *pt; + + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if ((!any_selected) || (pt->flag & GP_SPOINT_SELECT)) { + copy_v3_v3(pt->vert_color, brush->rgb); + pt->vert_color[3] = factor; + } + } + } + } + } + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; } } } } - GP_EDITABLE_STROKES_END(gpstroke_iter); + CTX_DATA_END; /* notifiers */ if (changed) { @@ -492,7 +648,8 @@ void GPENCIL_OT_vertex_color_set(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* params */ - ot->prop = RNA_def_enum(ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, 0, "Mode", ""); + ot->prop = RNA_def_enum( + ot->srna, "mode", gpencil_modesEnumPropertyItem_mode, GPPAINT_MODE_BOTH, "Mode", ""); RNA_def_float(ot->srna, "factor", 1.0f, 0.001f, 1.0f, "Factor", "Mix Factor", 0.001f, 1.0f); } @@ -900,3 +1057,114 @@ void GPENCIL_OT_extract_palette_vertex(wmOperatorType *ot) ot->srna, "selected", false, "Only Selected", "Convert only selected strokes"); RNA_def_int(ot->srna, "threshold", 1, 1, 4, "Threshold", "", 1, 4); } + +/* -------------------------------------------------------------------- */ +/** \name Reset Stroke Vertex Color Operator + * \{ */ + +static void gpencil_reset_vertex(bGPDstroke *gps, eGp_Vertex_Mode mode) +{ + if (mode != GPPAINT_MODE_STROKE) { + zero_v4(gps->vert_color_fill); + } + + if (mode != GPPAINT_MODE_FILL) { + bGPDspoint *pt; + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + zero_v4(pt->vert_color); + } + } +} + +static int gpencil_stroke_reset_vertex_color_exec(bContext *C, wmOperator *op) +{ + Object *obact = CTX_data_active_object(C); + bGPdata *gpd = (bGPdata *)obact->data; + const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const eGp_Vertex_Mode mode = RNA_enum_get(op->ptr, "mode"); + + /* First need to check if there are something selected. If not, apply to all strokes. */ + const bool any_selected = is_any_stroke_selected(C, is_multiedit, is_curve_edit); + + /* Reset Vertex colors. */ + bool changed = false; + CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* skip strokes that are invalid for current view */ + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } + + if (is_curve_edit) { + if (gps->editcurve == NULL) { + continue; + } + bGPDcurve *gpc = gps->editcurve; + if ((!any_selected) || (gpc->flag & GP_CURVE_SELECT)) { + gpencil_reset_vertex(gps, mode); + } + } + else { + if ((!any_selected) || (gps->flag & GP_STROKE_SELECT)) { + gpencil_reset_vertex(gps, mode); + } + } + + changed = true; + } + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } + } + } + } + CTX_DATA_END; + + if (changed) { + /* updates */ + DEG_id_tag_update(&gpd->id, + ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + } + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_stroke_reset_vertex_color(wmOperatorType *ot) +{ + static EnumPropertyItem mode_types_items[] = { + {GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Reset Vertex Color to Stroke only"}, + {GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Reset Vertex Color to Fill only"}, + {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", "Reset Vertex Color to Stroke and Fill"}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Reset Vertex Color"; + ot->idname = "GPENCIL_OT_stroke_reset_vertex_color"; + ot->description = "Reset vertex color for all or selected strokes"; + + /* callbacks */ + ot->exec = gpencil_stroke_reset_vertex_color_exec; + ot->poll = gpencil_vertexpaint_mode_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "mode", mode_types_items, GPPAINT_MODE_BOTH, "Mode", ""); +} + +/** \} */ diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h index ba77da24406..40b0a8d96b1 100644 --- a/source/blender/editors/include/ED_datafiles.h +++ b/source/blender/editors/include/ED_datafiles.h @@ -50,6 +50,9 @@ extern char datatoc_prvicons_png[]; extern int datatoc_alert_icons_png_size; extern char datatoc_alert_icons_png[]; +extern int datatoc_blender_logo_png_size; +extern char datatoc_blender_logo_png[]; + extern int datatoc_splash_png_size; extern char datatoc_splash_png[]; diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 84808416074..a5a8df916d6 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -101,9 +101,9 @@ typedef struct FileSelection { struct View2D; struct rcti; -struct FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile); +struct FileSelectParams *ED_fileselect_ensure_active_params(struct SpaceFile *sfile); +struct FileSelectParams *ED_fileselect_get_active_params(const struct SpaceFile *sfile); -short ED_fileselect_set_params(struct SpaceFile *sfile); void ED_fileselect_set_params_from_userdef(struct SpaceFile *sfile); void ED_fileselect_params_to_userdef(struct SpaceFile *sfile, const int temp_win_size[], diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index f9dc23502c7..005dbf0e381 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -26,6 +26,7 @@ #include "BLI_compiler_attrs.h" #include "BLI_sys_types.h" /* size_t */ #include "RNA_types.h" +#include "UI_interface_icons.h" #ifdef __cplusplus extern "C" { @@ -1351,7 +1352,7 @@ struct PointerRNA *UI_but_operator_ptr_get(uiBut *but); void UI_but_unit_type_set(uiBut *but, const int unit_type); int UI_but_unit_type_get(const uiBut *but); -enum { +typedef enum uiStringInfoType { BUT_GET_RNAPROP_IDENTIFIER = 1, BUT_GET_RNASTRUCT_IDENTIFIER, BUT_GET_RNAENUM_IDENTIFIER, @@ -1364,10 +1365,10 @@ enum { BUT_GET_RNAENUM_TIP, BUT_GET_OP_KEYMAP, BUT_GET_PROP_KEYMAP, -}; +} uiStringInfoType; typedef struct uiStringInfo { - int type; + uiStringInfoType type; char *strinfo; } uiStringInfo; @@ -2431,6 +2432,9 @@ void uiItemTabsEnumR_prop(uiLayout *layout, /* Only for testing, inspecting layouts. */ const char *UI_layout_introspect(uiLayout *layout); +/* Helper to add a big icon and create a split layout for alert boxes. */ +uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon); + /* UI Operators */ typedef struct uiDragColorHandle { float color[3]; diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 685b34b7185..4a02c6b6e88 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -6795,7 +6795,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) va_start(args, but); while ((si = (uiStringInfo *)va_arg(args, void *))) { - int type = si->type; + uiStringInfoType type = si->type; char *tmp = NULL; if (type == BUT_GET_LABEL) { diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 02a9c3742d7..39b405a02b8 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -90,9 +90,8 @@ static IDProperty *shortcut_property_from_rna(bContext *C, uiBut *but) } /* Create ID property of data path, to pass to the operator. */ - IDProperty *prop; const IDPropertyTemplate val = {0}; - prop = IDP_New(IDP_GROUP, &val, __func__); + IDProperty *prop = IDP_New(IDP_GROUP, &val, __func__); IDP_AddToGroup(prop, IDP_NewString(final_data_path, "data_path", strlen(final_data_path) + 1)); MEM_freeN((void *)final_data_path); @@ -167,43 +166,40 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) static uiBlock *menu_change_shortcut(bContext *C, ARegion *region, void *arg) { wmWindowManager *wm = CTX_wm_manager(C); - uiBlock *block; uiBut *but = (uiBut *)arg; - wmKeyMap *km; - wmKeyMapItem *kmi; PointerRNA ptr; - uiLayout *layout; const uiStyle *style = UI_style_get_dpi(); IDProperty *prop; const char *idname = shortcut_get_operator_property(C, but, &prop); - kmi = WM_key_event_operator(C, - idname, - but->opcontext, - prop, - EVT_TYPE_MASK_HOTKEY_INCLUDE, - EVT_TYPE_MASK_HOTKEY_EXCLUDE, - &km); + wmKeyMap *km; + wmKeyMapItem *kmi = WM_key_event_operator(C, + idname, + but->opcontext, + prop, + EVT_TYPE_MASK_HOTKEY_INCLUDE, + EVT_TYPE_MASK_HOTKEY_EXCLUDE, + &km); U.runtime.is_dirty = true; BLI_assert(kmi != NULL); RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); - block = UI_block_begin(C, region, "_popup", UI_EMBOSS); + uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS); UI_block_func_handle_set(block, but_shortcut_name_func, but); UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); UI_block_direction_set(block, UI_DIR_CENTER_Y); - layout = UI_block_layout(block, - UI_LAYOUT_VERTICAL, - UI_LAYOUT_PANEL, - 0, - 0, - U.widget_unit * 10, - U.widget_unit * 2, - 0, - style); + uiLayout *layout = UI_block_layout(block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + 0, + 0, + U.widget_unit * 10, + U.widget_unit * 2, + 0, + style); uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), ICON_HAND); uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); @@ -223,22 +219,17 @@ static int g_kmi_id_hack; static uiBlock *menu_add_shortcut(bContext *C, ARegion *region, void *arg) { wmWindowManager *wm = CTX_wm_manager(C); - uiBlock *block; uiBut *but = (uiBut *)arg; - wmKeyMap *km; - wmKeyMapItem *kmi; PointerRNA ptr; - uiLayout *layout; const uiStyle *style = UI_style_get_dpi(); - int kmi_id; IDProperty *prop; const char *idname = shortcut_get_operator_property(C, but, &prop); /* XXX this guess_opname can potentially return a different keymap * than being found on adding later... */ - km = WM_keymap_guess_opname(C, idname); - kmi = WM_keymap_add_item(km, idname, EVT_AKEY, KM_PRESS, 0, 0); - kmi_id = kmi->id; + wmKeyMap *km = WM_keymap_guess_opname(C, idname); + wmKeyMapItem *kmi = WM_keymap_add_item(km, idname, EVT_AKEY, KM_PRESS, 0, 0); + int kmi_id = kmi->id; /* This takes ownership of prop, or prop can be NULL for reset. */ WM_keymap_item_properties_reset(kmi, prop); @@ -252,19 +243,19 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *region, void *arg) RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); - block = UI_block_begin(C, region, "_popup", UI_EMBOSS); + uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS); UI_block_func_handle_set(block, but_shortcut_name_func, but); UI_block_direction_set(block, UI_DIR_CENTER_Y); - layout = UI_block_layout(block, - UI_LAYOUT_VERTICAL, - UI_LAYOUT_PANEL, - 0, - 0, - U.widget_unit * 10, - U.widget_unit * 2, - 0, - style); + uiLayout *layout = UI_block_layout(block, + UI_LAYOUT_VERTICAL, + UI_LAYOUT_PANEL, + 0, + 0, + U.widget_unit * 10, + U.widget_unit * 2, + 0, + style); uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"), ICON_HAND); uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); @@ -282,24 +273,21 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *region, void *arg) static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) { uiBut *but = (uiBut *)arg1; - wmKeyMap *km; - wmKeyMapItem *kmi; - int kmi_id; IDProperty *prop; const char *idname = shortcut_get_operator_property(C, but, &prop); #ifdef USE_KEYMAP_ADD_HACK - km = WM_keymap_guess_opname(C, idname); - kmi_id = g_kmi_id_hack; + wmKeyMap *km = WM_keymap_guess_opname(C, idname); + int kmi_id = g_kmi_id_hack; UNUSED_VARS(but); #else - kmi_id = WM_key_event_operator_id(C, idname, but->opcontext, prop, true, &km); + int kmi_id = WM_key_event_operator_id(C, idname, but->opcontext, prop, true, &km); #endif shortcut_free_operator_property(prop); - kmi = WM_keymap_item_find_id(km, kmi_id); + wmKeyMapItem *kmi = WM_keymap_item_find_id(km, kmi_id); WM_keymap_remove_item(km, kmi); } @@ -312,18 +300,17 @@ static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - wmKeyMap *km; - wmKeyMapItem *kmi; IDProperty *prop; const char *idname = shortcut_get_operator_property(C, but, &prop); - kmi = WM_key_event_operator(C, - idname, - but->opcontext, - prop, - EVT_TYPE_MASK_HOTKEY_INCLUDE, - EVT_TYPE_MASK_HOTKEY_EXCLUDE, - &km); + wmKeyMap *km; + wmKeyMapItem *kmi = WM_key_event_operator(C, + idname, + but->opcontext, + prop, + EVT_TYPE_MASK_HOTKEY_INCLUDE, + EVT_TYPE_MASK_HOTKEY_EXCLUDE, + &km); BLI_assert(kmi != NULL); WM_keymap_remove_item(km, kmi); @@ -349,7 +336,6 @@ static bool ui_but_is_user_menu_compatible(bContext *C, uiBut *but) static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *um) { - MenuType *mt = NULL; if (but->optype) { IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; return (bUserMenuItem *)ED_screen_user_menu_item_find_operator( @@ -373,7 +359,9 @@ static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu * } return umi; } - if ((mt = UI_but_menutype_get(but))) { + + MenuType *mt = UI_but_menutype_get(but); + if (mt != NULL) { return (bUserMenuItem *)ED_screen_user_menu_item_find_menu(&um->items, mt); } return NULL; @@ -515,7 +503,6 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) uiPopupMenu *pup; uiLayout *layout; - { uiStringInfo label = {BUT_GET_LABEL, NULL}; @@ -979,7 +966,6 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) if (ui_but_is_user_menu_compatible(C, but)) { uiBlock *block = uiLayoutGetBlock(layout); const int w = uiLayoutGetWidth(layout); - uiBut *but2; bool item_found = false; uint um_array_len; @@ -991,7 +977,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } bUserMenuItem *umi = ui_but_user_menu_find(C, but, um); if (umi != NULL) { - but2 = uiDefIconTextBut( + uiBut *but2 = uiDefIconTextBut( block, UI_BTYPE_BUT, 0, @@ -1016,7 +1002,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } if (!item_found) { - but2 = uiDefIconTextBut( + uiBut *but2 = uiDefIconTextBut( block, UI_BTYPE_BUT, 0, @@ -1043,11 +1029,10 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) const char *idname = shortcut_get_operator_property(C, but, &prop); if (idname != NULL) { uiBlock *block = uiLayoutGetBlock(layout); - uiBut *but2; const int w = uiLayoutGetWidth(layout); - wmKeyMap *km; /* We want to know if this op has a shortcut, be it hotkey or not. */ + wmKeyMap *km; wmKeyMapItem *kmi = WM_key_event_operator( C, idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km); @@ -1066,77 +1051,80 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) ""); #endif - but2 = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_HAND, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), - 0, - 0, - w, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - ""); + uiBut *but2 = uiDefIconTextBut( + block, + UI_BTYPE_BUT, + 0, + ICON_HAND, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), + 0, + 0, + w, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + ""); UI_but_func_set(but2, popup_change_shortcut_func, but, NULL); } else { - but2 = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_HAND, - IFACE_("Non-Keyboard Shortcut"), - 0, - 0, - w, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Only keyboard shortcuts can be edited that way, " - "please use User Preferences otherwise")); + uiBut *but2 = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_HAND, + IFACE_("Non-Keyboard Shortcut"), + 0, + 0, + w, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + TIP_("Only keyboard shortcuts can be edited that way, " + "please use User Preferences otherwise")); UI_but_flag_enable(but2, UI_BUT_DISABLED); } - but2 = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_BLANK1, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"), - 0, - 0, - w, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - ""); + uiBut *but2 = uiDefIconTextBut( + block, + UI_BTYPE_BUT, + 0, + ICON_BLANK1, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"), + 0, + 0, + w, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + ""); UI_but_func_set(but2, remove_shortcut_func, but, NULL); } /* only show 'assign' if there's a suitable key map for it to go in */ else if (WM_keymap_guess_opname(C, idname)) { - but2 = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_HAND, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"), - 0, - 0, - w, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - ""); + uiBut *but2 = uiDefIconTextBut( + block, + UI_BTYPE_BUT, + 0, + ICON_HAND, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"), + 0, + 0, + w, + UI_UNIT_Y, + NULL, + 0, + 0, + 0, + 0, + ""); UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); } @@ -1239,9 +1227,6 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *region, Panel *panel) bScreen *screen = CTX_wm_screen(C); const bool has_panel_category = UI_panel_category_is_visible(region); const bool any_item_visible = has_panel_category; - PointerRNA ptr; - uiPopupMenu *pup; - uiLayout *layout; if (!any_item_visible) { return; @@ -1250,10 +1235,11 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *region, Panel *panel) return; } + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_Panel, panel, &ptr); - pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE); - layout = UI_popup_menu_layout(pup); + uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE); + uiLayout *layout = UI_popup_menu_layout(pup); if (has_panel_category) { char tmpstr[80]; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 3c028977a36..f914ccd7497 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -838,6 +838,7 @@ static void ui_apply_but_undo(uiBut *but) /* fallback, else we don't get an undo! */ if (str == NULL || str[0] == '\0' || str_len_clip == 0) { str = "Unknown Action"; + str_len_clip = strlen(str); } /* Optionally override undo when undo system doesn't support storing properties. */ diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index d61e80e6505..0403287125c 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5951,3 +5951,45 @@ const char *UI_layout_introspect(uiLayout *layout) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Alert Box with Big Icon + * \{ */ + +/** + * Helper to add a big icon and create a split layout for alert popups. + * Returns the layout to place further items into the alert box. + */ +uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon) +{ + const uiStyle *style = UI_style_get_dpi(); + const short icon_size = 64 * U.dpi_fac; + const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); + const int dialog_width = icon_size + (text_points_max * size * U.dpi_fac); + /* By default, the space between icon and text/buttons will be equal to the 'columnspace', + this extra padding will add some space by increasing the left column width, + making the icon placement more symmetrical, between the block edge and the text. */ + const float icon_padding = 5.0f * U.dpi_fac; + /* Calculate the factor of the fixed icon column depending on the block width. */ + const float split_factor = ((float)icon_size + icon_padding) / + (float)(dialog_width - style->columnspace); + + uiLayout *block_layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style); + + /* Split layout to put alert icon on left side. */ + uiLayout *split_block = uiLayoutSplit(block_layout, split_factor, false); + + /* Alert icon on the left. */ + uiLayout *layout = uiLayoutRow(split_block, false); + /* Using 'align_left' with 'row' avoids stretching the icon along the width of column. */ + uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_LEFT); + uiDefButAlert(block, icon, 0, 0, icon_size, icon_size); + + /* The rest of the content on the right. */ + layout = uiLayoutColumn(split_block, false); + + return layout; +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 0d1e2802242..e5aa0665a16 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1223,7 +1223,7 @@ typedef struct uiEditSourceStore { typedef struct uiEditSourceButStore { char py_dbg_fn[FILE_MAX]; - int py_dbg_ln; + int py_dbg_line_number; } uiEditSourceButStore; /* should only ever be set while the edit source operator is running */ @@ -1276,21 +1276,21 @@ void UI_editsource_active_but_test(uiBut *but) struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__); const char *fn; - int lineno = -1; + int line_number = -1; # if 0 printf("comparing buttons: '%s' == '%s'\n", but->drawstr, ui_editsource_info->but_orig.drawstr); # endif - PyC_FileAndNum_Safe(&fn, &lineno); + PyC_FileAndNum_Safe(&fn, &line_number); - if (lineno != -1) { + if (line_number != -1) { BLI_strncpy(but_store->py_dbg_fn, fn, sizeof(but_store->py_dbg_fn)); - but_store->py_dbg_ln = lineno; + but_store->py_dbg_line_number = line_number; } else { but_store->py_dbg_fn[0] = '\0'; - but_store->py_dbg_ln = -1; + but_store->py_dbg_line_number = -1; } BLI_ghash_insert(ui_editsource_info->hash, but, but_store); @@ -1375,8 +1375,8 @@ static int editsource_exec(bContext *C, wmOperator *op) } if (but_store) { - if (but_store->py_dbg_ln != -1) { - ret = editsource_text_edit(C, op, but_store->py_dbg_fn, but_store->py_dbg_ln); + if (but_store->py_dbg_line_number != -1) { + ret = editsource_text_edit(C, op, but_store->py_dbg_fn, but_store->py_dbg_line_number); } else { BKE_report( diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index b60fa40f39a..e96c0a25d6d 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -2452,11 +2452,12 @@ int ui_handler_panel_region(bContext *C, if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { /* All mouse clicks inside panel headers should return in break. */ - retval = WM_UI_HANDLER_BREAK; if (ELEM(event->type, EVT_RETKEY, EVT_PADENTER, LEFTMOUSE)) { + retval = WM_UI_HANDLER_BREAK; ui_handle_panel_header(C, block, mx, event->type, event->ctrl, event->shift); } else if (event->type == RIGHTMOUSE) { + retval = WM_UI_HANDLER_BREAK; ui_popup_context_menu_for_panel(C, region, block->panel); } break; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 4dd543e71a9..a2fe949b6c5 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -3574,7 +3574,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE /* To support redo. */ { - /* Note that the `base_index` can't be used as the index depends on the view-port + /* Note that the `base_index` can't be used as the index depends on the 3D Viewport * which might not be available on redo. */ BM_mesh_elem_index_ensure(bm, ele->head.htype); int object_index; diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 4e0f6211c18..bbfdfb2532d 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1618,6 +1618,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } Object *ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits); + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ob); /* to make it easier to start using this immediately in NLA, a default sound clip is created * ready to be moved around to retime the sound and/or make new sound clips @@ -1625,13 +1626,13 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) { /* create new data for NLA hierarchy */ AnimData *adt = BKE_animdata_add_id(&ob->id); - NlaTrack *nlt = BKE_nlatrack_add(adt, NULL); + NlaTrack *nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, ob->data); strip->start = CFRA; strip->end += strip->start; /* hook them up */ - BKE_nlatrack_add_strip(nlt, strip); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); /* auto-name the strip, and give the track an interesting name */ BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name)); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index fa8531dfb48..dd015f59e8d 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -706,11 +706,10 @@ static bool edit_constraint_poll_generic(bContext *C, return false; } - if (ID_IS_OVERRIDE_LIBRARY(ob) && !is_liboverride_allowed) { - if ((con == NULL) || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) == 0) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override"); - return false; - } + if (!is_liboverride_allowed && BKE_constraint_is_nonlocal_in_liboverride(ob, con)) { + CTX_wm_operator_poll_msg_set( + C, "Cannot edit constraints coming from linked data in a library override"); + return false; } return true; diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index eed3c7f419d..af95f5581bd 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -319,6 +319,8 @@ int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModi BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd); BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd); + nmd->flag |= eGpencilModifierFlag_OverrideLibrary_Local; + return 1; } @@ -422,7 +424,10 @@ void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot) /********** generic functions for operators using mod names and data context *********************/ -static bool gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag) +static bool gpencil_edit_modifier_poll_generic(bContext *C, + StructRNA *rna_type, + int obtype_flag, + const bool is_liboverride_allowed) { PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); @@ -438,11 +443,10 @@ static bool gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, return false; } - if (ID_IS_OVERRIDE_LIBRARY(ob)) { - if ((mod == NULL) || (mod->flag & eGpencilModifierFlag_OverrideLibrary_Local) == 0) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override"); - return false; - } + if (!is_liboverride_allowed && BKE_gpencil_modifier_is_nonlocal_in_liboverride(ob, mod)) { + CTX_wm_operator_poll_msg_set( + C, "Cannot edit modifiers coming from linked data in a library override"); + return false; } return true; @@ -450,7 +454,14 @@ static bool gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, static bool gpencil_edit_modifier_poll(bContext *C) { - return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0); + return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0, false); +} + +/* Used by operators performing actions allowed also on modifiers from the overridden linked object + * (not only from added 'local' ones). */ +static bool gpencil_edit_modifier_liboverride_allowed_poll(bContext *C) +{ + return gpencil_edit_modifier_poll_generic(C, &RNA_Modifier, 0, true); } static void gpencil_edit_modifier_properties(wmOperatorType *ot) @@ -669,11 +680,6 @@ void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot) /* ************************* Move to Index Gpencil Modifier Operator ************************* */ -static bool gpencil_modifier_move_to_index_poll(bContext *C) -{ - return gpencil_edit_modifier_poll(C); -} - static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_active_context(C); @@ -706,7 +712,7 @@ void OBJECT_OT_gpencil_modifier_move_to_index(wmOperatorType *ot) ot->invoke = gpencil_modifier_move_to_index_invoke; ot->exec = gpencil_modifier_move_to_index_exec; - ot->poll = gpencil_modifier_move_to_index_poll; + ot->poll = gpencil_edit_modifier_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; @@ -823,7 +829,7 @@ void OBJECT_OT_gpencil_modifier_copy(wmOperatorType *ot) ot->invoke = gpencil_modifier_copy_invoke; ot->exec = gpencil_modifier_copy_exec; - ot->poll = gpencil_edit_modifier_poll; + ot->poll = gpencil_edit_modifier_liboverride_allowed_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 7d12fa1805b..3111003703f 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1052,11 +1052,10 @@ bool edit_modifier_poll_generic(bContext *C, return false; } - if (ID_IS_OVERRIDE_LIBRARY(ob) && !is_liboverride_allowed) { - if ((mod == NULL) || (mod->flag & eModifierFlag_OverrideLibrary_Local) == 0) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override"); - return false; - } + if (!is_liboverride_allowed && BKE_modifier_is_nonlocal_in_liboverride(ob, mod)) { + CTX_wm_operator_poll_msg_set( + C, "Cannot edit modifiers coming from linked data in a library override"); + return false; } if (!is_editmode_allowed && CTX_data_edit_object(C) != NULL) { diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index d3a06f0fc2c..e1d03e6f3be 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -46,6 +46,8 @@ void MATERIAL_OT_paste(struct wmOperatorType *ot); void SCENE_OT_view_layer_add(struct wmOperatorType *ot); void SCENE_OT_view_layer_remove(struct wmOperatorType *ot); +void SCENE_OT_view_layer_add_aov(struct wmOperatorType *ot); +void SCENE_OT_view_layer_remove_aov(struct wmOperatorType *ot); void SCENE_OT_light_cache_bake(struct wmOperatorType *ot); void SCENE_OT_light_cache_free(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index 706249a3f8b..e0aa02b354d 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -53,6 +53,8 @@ void ED_operatortypes_render(void) WM_operatortype_append(SCENE_OT_view_layer_add); WM_operatortype_append(SCENE_OT_view_layer_remove); + WM_operatortype_append(SCENE_OT_view_layer_add_aov); + WM_operatortype_append(SCENE_OT_view_layer_remove_aov); WM_operatortype_append(SCENE_OT_render_view_add); WM_operatortype_append(SCENE_OT_render_view_remove); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 60e5c2081fd..b69337b1621 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -90,6 +90,7 @@ #include "UI_interface.h" +#include "RE_engine.h" #include "RE_pipeline.h" #include "engines/eevee/eevee_lightcache.h" @@ -1014,6 +1015,93 @@ void SCENE_OT_view_layer_remove(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name View Layer Add AOV Operator + * \{ */ + +static int view_layer_add_aov_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + BKE_view_layer_add_aov(view_layer); + + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + if (engine_type->update_render_passes) { + RenderEngine *engine = RE_engine_create(engine_type); + if (engine) { + BKE_view_layer_verify_aov(engine, scene, view_layer); + } + RE_engine_free(engine); + engine = NULL; + } + + DEG_id_tag_update(&scene->id, 0); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_view_layer_add_aov(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add AOV"; + ot->idname = "SCENE_OT_view_layer_add_aov"; + ot->description = "Add a Shader AOV"; + + /* api callbacks */ + ot->exec = view_layer_add_aov_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Layer Remove AOV Operator + * \{ */ + +static int view_layer_remove_aov_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + BKE_view_layer_remove_aov(view_layer, view_layer->active_aov); + + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + if (engine_type->update_render_passes) { + RenderEngine *engine = RE_engine_create(engine_type); + if (engine) { + BKE_view_layer_verify_aov(engine, scene, view_layer); + } + RE_engine_free(engine); + engine = NULL; + } + + DEG_id_tag_update(&scene->id, 0); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + + return OPERATOR_FINISHED; +} + +void SCENE_OT_view_layer_remove_aov(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove AOV"; + ot->idname = "SCENE_OT_view_layer_remove_aov"; + ot->description = "Remove Active AOV"; + + /* api callbacks */ + ot->exec = view_layer_remove_aov_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Light Cache Bake Operator * \{ */ diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index af09100b8e6..244ebea5bbe 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -1004,6 +1004,11 @@ static eContextResult screen_ctx_selected_editable_keyframes(const bContext *C, } fcurve = (FCurve *)ale->data; + if (fcurve->bezt == NULL) { + /* Skip baked FCurves. */ + continue; + } + for (i = 0, bezt = fcurve->bezt; i < fcurve->totvert; i++, bezt++) { if ((bezt->f2 & SELECT) == 0) { continue; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 8c16300a047..98f4b4013cb 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -6748,7 +6748,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot) "Generated Type", "Fill the image with a grid for UV map testing"); RNA_def_boolean( - ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); + ot->srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth"); } static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 11d897cf76f..17690757fa5 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -335,7 +335,7 @@ static void sculpt_gesture_operator_properties(wmOperatorType *ot) false, "Limit to Segment", "Apply the gesture action only to the area that is contained within the " - "segement without extending its effect to the entire line"); + "segment without extending its effect to the entire line"); } static void sculpt_gesture_context_init_common(bContext *C, diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index eea79bad789..8eb2ebd0f19 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -120,13 +120,8 @@ static int weight_from_bones_exec(bContext *C, wmOperator *op) Mesh *me = ob->data; int type = RNA_enum_get(op->ptr, "type"); - ED_object_vgroup_calc_from_armature(op->reports, - depsgraph, - scene, - ob, - armob, - type, - (me->editflag & ME_EDIT_VERTEX_GROUPS_X_SYMMETRY)); + ED_object_vgroup_calc_from_armature( + op->reports, depsgraph, scene, ob, armob, type, (me->symmetry & ME_SYMMETRY_X)); DEG_id_tag_update(&me->id, 0); DEG_relations_tag_update(CTX_data_main(C)); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index b9427677745..fd7ec1da497 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4232,6 +4232,8 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, (len_v3(grab_delta) / ss->cache->radius)) : 0.0f; + const bool do_elastic = brush->snake_hook_deform_type == BRUSH_SNAKE_HOOK_DEFORM_ELASTIC; + proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; SculptBrushTest test; @@ -4239,18 +4241,28 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const int thread_id = BLI_task_parallel_thread_id(tls); + KelvinletParams params; + BKE_kelvinlet_init_params(¶ms, ss->cache->radius, bstrength, 1.0f, 0.4f); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (do_elastic || sculpt_brush_test_sq_fn(&test, vd.co)) { + + float fade; + if (do_elastic) { + fade = 1.0f; + } + else { + fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + } mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -4289,6 +4301,17 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, add_v3_v3(proxy[vd.i], delta_rotate); } + if (do_elastic) { + float disp[3]; + BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); + mul_v3_fl(disp, bstrength * 20.0f); + if (vd.mask) { + mul_v3_fl(disp, 1.0f - *vd.mask); + } + mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); + copy_v3_v3(proxy[vd.i], disp); + } + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -5714,16 +5737,8 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe /* Build a list of all nodes that are potentially within the brush's area of influence */ - /* These brushes need to update all nodes as they are not constrained by the brush radius */ - /* Elastic deform needs all nodes to avoid artifacts as the effect of the brush is not - * constrained by the radius. */ - /* Pose needs all nodes because it applies all symmetry iterations at the same time and the IK - * chain can grow to any area of the model. */ - /* This can be optimized by filtering the nodes after calculating the chain. */ - if (ELEM(brush->sculpt_tool, - SCULPT_TOOL_ELASTIC_DEFORM, - SCULPT_TOOL_POSE, - SCULPT_TOOL_BOUNDARY)) { + if (SCULPT_tool_needs_all_pbvh_nodes(brush)) { + /* These brushes need to update all nodes as they are not constrained by the brush radius */ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); } else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) { diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 7c8a4c5a857..ad42750bb92 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -1307,8 +1307,8 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven SculptCursorGeometryInfo sgi; const float mouse[2] = {event->mval[0], event->mval[1]}; if (!SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) { - /* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */ - return OPERATOR_CANCELLED; + /* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */ + return OPERATOR_CANCELLED; } const int active_face_set = SCULPT_active_face_set_get(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 11af63c6e47..02d4be20e1b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -448,7 +448,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, mul_v3_v3fl(disp, ss->filter_cache->detail_directions[vd.index], -fabsf(fade)); } break; case MESH_FILTER_ERASE_DISPLACEMENT: { - fade = clamp_f(fade, 0.0f, 1.0f); + fade = clamp_f(fade, -1.0f, 1.0f); sub_v3_v3v3(disp, ss->filter_cache->limit_surface_co[vd.index], orig_co); mul_v3_fl(disp, fade); break; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 99ee22328ea..3b48207f461 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -434,6 +434,38 @@ BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush) brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM); } +BLI_INLINE bool SCULPT_tool_needs_all_pbvh_nodes(const Brush *brush) +{ + if (brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) { + /* Elastic deformations in any brush need all nodes to avoid artifacts as the effect + * of the Kelvinlet is not constrained by the radius. */ + return true; + } + + if (brush->sculpt_tool == SCULPT_TOOL_POSE) { + /* Pose needs all nodes because it applies all symmetry iterations at the same time + * and the IK chain can grow to any area of the model. */ + /* TODO: This can be optimized by filtering the nodes after calculating the chain. */ + return true; + } + + if (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) { + /* Boundary needs all nodes because it is not possible to know where the boundary + * deformation is going to be propagated before calculating it. */ + /* TODO: after calculating the boudnary info in the first iteration, it should be + * possible to get the nodes that have vertices included in any boundary deformation + * and cache them. */ + return true; + } + + if (brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK && + brush->snake_hook_deform_type == BRUSH_SNAKE_HOOK_DEFORM_ELASTIC) { + /* Snake hook in elastic deform type has same requirements as the elastic deform tool. */ + return true; + } + return false; +} + /* Pose Brush. */ void SCULPT_do_pose_brush(struct Sculpt *sd, struct Object *ob, diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c index f0047448a8d..39320f3f558 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -220,6 +220,9 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata, SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + test.radius *= data->brush->wet_paint_radius_factor; + test.radius_squared = test.radius * test.radius; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index 4b318a05591..1bf9ba60073 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -1197,7 +1197,7 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) quat_to_mat4(ik_chain->segments[i].trans_mat[symm_it], symm_rot); } - /* Apply segement scale to the transform. */ + /* Apply segment scale to the transform. */ for (int scale_i = 0; scale_i < 3; scale_i++) { mul_v3_fl(ik_chain->segments[i].trans_mat[symm_it][scale_i], ik_chain->segments[i].scale[scale_i]); diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index 88585745467..f74d59e1987 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -212,8 +212,8 @@ static void sculpt_transform_all_vertices(Sculpt *sd, Object *ob) sculpt_transform_matrices_init( ss, symm, ss->filter_cache->transform_displacement_mode, data.transform_mats); - /* Regular transform applies all symmetry passes at once as it is split by symmetry areas (each - * vertex can only be transformed once by the transform matix of its area). */ + /* Regular transform applies all symmetry passes at once as it is split by symmetry areas + * (each vertex can only be transformed once by the transform matrix of its area). */ TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode); BLI_task_parallel_range( diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index c6961cc9d4b..8dac90c2346 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -518,27 +518,27 @@ static bool sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), static void sound_mixdown_draw(bContext *C, wmOperator *op) { static const EnumPropertyItem pcm_format_items[] = { - {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"}, - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, + {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, # ifdef WITH_SNDFILE - {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"}, + {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"}, # endif - {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"}, - {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"}, - {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"}, + {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"}, + {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"}, + {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"}, {0, NULL, 0, NULL, NULL}, }; static const EnumPropertyItem mp3_format_items[] = { - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, - {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, + {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"}, {0, NULL, 0, NULL, NULL}, }; # ifdef WITH_SNDFILE static const EnumPropertyItem flac_format_items[] = { - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, - {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, + {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"}, {0, NULL, 0, NULL, NULL}, }; # endif @@ -672,12 +672,12 @@ static void SOUND_OT_mixdown(wmOperatorType *ot) { #ifdef WITH_AUDASPACE static const EnumPropertyItem format_items[] = { - {AUD_FORMAT_U8, "U8", 0, "U8", "8 bit unsigned"}, - {AUD_FORMAT_S16, "S16", 0, "S16", "16 bit signed"}, - {AUD_FORMAT_S24, "S24", 0, "S24", "24 bit signed"}, - {AUD_FORMAT_S32, "S32", 0, "S32", "32 bit signed"}, - {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32 bit floating point"}, - {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64 bit floating point"}, + {AUD_FORMAT_U8, "U8", 0, "U8", "8-bit unsigned"}, + {AUD_FORMAT_S16, "S16", 0, "S16", "16-bit signed"}, + {AUD_FORMAT_S24, "S24", 0, "S24", "24-bit signed"}, + {AUD_FORMAT_S32, "S32", 0, "S32", "32-bit signed"}, + {AUD_FORMAT_FLOAT32, "F32", 0, "F32", "32-bit floating-point"}, + {AUD_FORMAT_FLOAT64, "F64", 0, "F64", "64-bit floating-point"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index e20be9c8328..3a584a7f0cb 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -240,7 +240,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) /* Perform stashing operation - But only if there is an action */ if (adt && oldact) { /* stash the action */ - if (BKE_nla_action_stash(adt)) { + if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ptr.owner_id))) { /* The stash operation will remove the user already * (and unlink the action from the AnimData action slot). * Hence, we must unset the ref to the action in the @@ -339,7 +339,8 @@ static int action_pushdown_exec(bContext *C, wmOperator *op) } /* action can be safely added */ - BKE_nla_action_pushdown(adt); + const Object *ob = CTX_data_active_object(C); + BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ob)); /* Stop displaying this action in this editor * NOTE: The editor itself doesn't set a user... @@ -384,7 +385,8 @@ static int action_stash_exec(bContext *C, wmOperator *op) } /* stash the action */ - if (BKE_nla_action_stash(adt)) { + Object *ob = CTX_data_active_object(C); + if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) { /* The stash operation will remove the user already, * so the flushing step later shouldn't double up * the user-count fixes. Hence, we must unset this ref @@ -486,7 +488,8 @@ static int action_stash_create_exec(bContext *C, wmOperator *op) } /* stash the action */ - if (BKE_nla_action_stash(adt)) { + Object *ob = CTX_data_active_object(C); + if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) { bAction *new_action = NULL; /* Create new action not based on the old one diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 4b277435f63..e3bdda7c480 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -400,11 +400,12 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); ARegion *region = CTX_wm_region(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - BLI_join_dirfile(orgname, sizeof(orgname), sfile->params->dir, oldname); - BLI_strncpy(filename, sfile->params->renamefile, sizeof(filename)); + BLI_join_dirfile(orgname, sizeof(orgname), params->dir, oldname); + BLI_strncpy(filename, params->renamefile, sizeof(filename)); BLI_filename_make_safe(filename); - BLI_join_dirfile(newname, sizeof(newname), sfile->params->dir, filename); + BLI_join_dirfile(newname, sizeof(newname), params->dir, filename); if (!STREQ(orgname, newname)) { if (!BLI_exists(newname)) { @@ -415,8 +416,8 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) } else { /* If rename is successful, scroll to newly renamed entry. */ - BLI_strncpy(sfile->params->renamefile, filename, sizeof(sfile->params->renamefile)); - sfile->params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; + BLI_strncpy(params->renamefile, filename, sizeof(params->renamefile)); + params->rename_flag = FILE_PARAMS_RENAME_POSTSCROLL_PENDING; if (sfile->smoothscroll_timer != NULL) { WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer); @@ -688,7 +689,7 @@ static void draw_details_columns(const FileSelectParams *params, void file_draw_list(const bContext *C, ARegion *region) { SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileLayout *layout = ED_fileselect_get_layout(sfile, region); View2D *v2d = ®ion->v2d; struct FileList *files = sfile->files; @@ -847,26 +848,25 @@ void file_draw_list(const bContext *C, ARegion *region) } if (file_selflag & FILE_SEL_EDITING) { - uiBut *but; const short width = (params->display == FILE_IMGDISPLAY) ? textwidth : layout->attribute_columns[COLUMN_NAME].width - ATTRIBUTE_COLUMN_PADDING; - but = uiDefBut(block, - UI_BTYPE_TEXT, - 1, - "", - sx + icon_ofs, - sy - layout->tile_h - 0.15f * UI_UNIT_X, - width - icon_ofs, - textheight, - sfile->params->renamefile, - 1.0f, - (float)sizeof(sfile->params->renamefile), - 0, - 0, - ""); + uiBut *but = uiDefBut(block, + UI_BTYPE_TEXT, + 1, + "", + sx + icon_ofs, + sy - layout->tile_h - 0.15f * UI_UNIT_X, + width - icon_ofs, + textheight, + params->renamefile, + 1.0f, + (float)sizeof(params->renamefile), + 0, + 0, + ""); UI_but_func_rename_set(but, renamebutton_cb, file); UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ UI_but_flag_disable(but, UI_BUT_UNDO); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 93367ad3d3c..b98348307f3 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -188,7 +188,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen) Main *bmain = CTX_data_main(C); FileSelect retval = FILE_SELECT_NOTHING; SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); int numfiles = filelist_files_ensure(sfile->files); const FileDirEntry *file; @@ -302,10 +302,10 @@ static FileSelect file_select( bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen) { SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileSelect retval = FILE_SELECT_NOTHING; FileSelection sel = file_selection_get(C, rect, fill); /* get the selection */ - const FileCheckType check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : - CHECK_ALL; + const FileCheckType check_type = (params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL; /* flag the files as selected in the filelist */ filelist_entries_select_index_range_set( @@ -325,7 +325,7 @@ static FileSelect file_select( } if (select != FILE_SEL_ADD && !file_is_any_selected(sfile->files)) { - sfile->params->active_file = -1; + params->active_file = -1; } else if (sel.last >= 0) { ARegion *region = CTX_wm_region(C); @@ -390,7 +390,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve { ARegion *region = CTX_wm_region(C); SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileSelection sel; rcti rect; @@ -521,8 +521,9 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } - if (sfile && sfile->params) { - int idx = sfile->params->highlight_file; + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (sfile && params) { + int idx = params->highlight_file; int numfiles = filelist_files_ensure(sfile->files); if ((idx >= 0) && (idx < numfiles)) { @@ -613,7 +614,7 @@ static bool file_walk_select_selection_set(wmWindow *win, const bool extend, const bool fill) { - FileSelectParams *params = sfile->params; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); struct FileList *files = sfile->files; const int last_sel = params->active_file; /* store old value */ int active = active_old; /* could use active_old instead, just for readability */ @@ -804,7 +805,7 @@ static bool file_walk_select_do(bContext *C, static int file_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); - FileSelectParams *params = sfile->params; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); const int direction = RNA_enum_get(op->ptr, "direction"); const bool extend = RNA_boolean_get(op->ptr, "extend"); const bool fill = RNA_boolean_get(op->ptr, "fill"); @@ -853,6 +854,7 @@ static int file_select_all_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileSelection sel; const int numfiles = filelist_files_ensure(sfile->files); int action = RNA_enum_get(op->ptr, "action"); @@ -870,7 +872,7 @@ static int file_select_all_exec(bContext *C, wmOperator *op) switch (action) { case SEL_SELECT: case SEL_INVERT: { - check_type = (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES; + check_type = (params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES; filesel_type = (action == SEL_INVERT) ? FILE_SEL_TOGGLE : FILE_SEL_ADD; break; } @@ -888,11 +890,11 @@ static int file_select_all_exec(bContext *C, wmOperator *op) filelist_entries_select_index_range_set( sfile->files, &sel, filesel_type, FILE_SEL_SELECTED, check_type); - sfile->params->active_file = -1; + params->active_file = -1; if (action != SEL_DESELECT) { for (int i = 0; i < numfiles; i++) { if (filelist_entry_select_index_get(sfile->files, i, check_type)) { - sfile->params->active_file = i; + params->active_file = i; break; } } @@ -935,8 +937,8 @@ static int bookmark_select_exec(bContext *C, wmOperator *op) PropertyRNA *prop; if ((prop = RNA_struct_find_property(op->ptr, "dir"))) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); char entry[256]; - FileSelectParams *params = sfile->params; RNA_property_string_get(op->ptr, prop, entry); BLI_strncpy(params->dir, entry, sizeof(params->dir)); @@ -978,7 +980,7 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = CTX_wm_space_file(C); struct FSMenu *fsmenu = ED_fsmenu_get(); - struct FileSelectParams *params = ED_fileselect_get_params(sfile); + struct FileSelectParams *params = ED_fileselect_get_active_params(sfile); if (params->dir[0] != '\0') { char name[FILE_MAX]; @@ -1274,7 +1276,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *region, int mx, int my) } numfiles = filelist_files_ensure(sfile->files); - params = ED_fileselect_get_params(sfile); + params = ED_fileselect_get_active_params(sfile); origfile = params->highlight_file; @@ -1345,20 +1347,21 @@ static int file_column_sort_ui_context_invoke(bContext *C, if (file_attribute_column_header_is_inside( ®ion->v2d, sfile->layout, event->mval[0], event->mval[1])) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); const FileAttributeColumnType column_type = file_attribute_column_type_find_isect( - ®ion->v2d, sfile->params, sfile->layout, event->mval[0]); + ®ion->v2d, params, sfile->layout, event->mval[0]); if (column_type != COLUMN_NONE) { const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type]; BLI_assert(column->sort_type != FILE_SORT_DEFAULT); - if (sfile->params->sort == column->sort_type) { + if (params->sort == column->sort_type) { /* Already sorting by selected column -> toggle sort invert (three state logic). */ - sfile->params->flag ^= FILE_SORT_INVERT; + params->flag ^= FILE_SORT_INVERT; } else { - sfile->params->sort = column->sort_type; - sfile->params->flag &= ~FILE_SORT_INVERT; + params->sort = column->sort_type; + params->flag &= ~FILE_SORT_INVERT; } WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -1433,10 +1436,11 @@ void FILE_OT_cancel(struct wmOperatorType *ot) void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, char *filepath) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); PropertyRNA *prop; /* XXX, not real length */ - BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file); + BLI_join_dirfile(filepath, FILE_MAX, params->dir, params->file); if ((prop = RNA_struct_find_property(op->ptr, "relative_path"))) { if (RNA_property_boolean_get(op->ptr, prop)) { @@ -1445,10 +1449,10 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch } if ((prop = RNA_struct_find_property(op->ptr, "filename"))) { - RNA_property_string_set(op->ptr, prop, sfile->params->file); + RNA_property_string_set(op->ptr, prop, params->file); } if ((prop = RNA_struct_find_property(op->ptr, "directory"))) { - RNA_property_string_set(op->ptr, prop, sfile->params->dir); + RNA_property_string_set(op->ptr, prop, params->dir); } if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { RNA_property_string_set(op->ptr, prop, filepath); @@ -1479,7 +1483,7 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch * files selected */ if (0 == num_files) { RNA_property_collection_add(op->ptr, prop, &itemptr); - RNA_string_set(&itemptr, "name", sfile->params->file); + RNA_string_set(&itemptr, "name", params->file); } } @@ -1500,7 +1504,7 @@ void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, ch * directory selected */ if (0 == num_dirs) { RNA_property_collection_add(op->ptr, prop, &itemptr); - RNA_string_set(&itemptr, "name", sfile->params->dir); + RNA_string_set(&itemptr, "name", params->dir); } } } @@ -1514,30 +1518,28 @@ void file_sfile_to_operator(Main *bmain, wmOperator *op, SpaceFile *sfile) void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); PropertyRNA *prop; /* If neither of the above are set, split the filepath back */ if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) { char filepath[FILE_MAX]; RNA_property_string_get(op->ptr, prop, filepath); - BLI_split_dirfile(filepath, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + BLI_split_dirfile( + filepath, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } else { if ((prop = RNA_struct_find_property(op->ptr, "filename"))) { - RNA_property_string_get(op->ptr, prop, sfile->params->file); + RNA_property_string_get(op->ptr, prop, params->file); } if ((prop = RNA_struct_find_property(op->ptr, "directory"))) { - RNA_property_string_get(op->ptr, prop, sfile->params->dir); + RNA_property_string_get(op->ptr, prop, params->dir); } } /* we could check for relative_path property which is used when converting * in the other direction but doesn't hurt to do this every time */ - BLI_path_abs(sfile->params->dir, BKE_main_blendfile_path(bmain)); + BLI_path_abs(params->dir, BKE_main_blendfile_path(bmain)); /* XXX, files and dirs updates missing, not really so important though */ } @@ -1547,21 +1549,19 @@ void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op) */ void file_sfile_filepath_set(SpaceFile *sfile, const char *filepath) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); BLI_assert(BLI_exists(filepath)); if (BLI_is_dir(filepath)) { - BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, filepath, sizeof(params->dir)); } else { - if ((sfile->params->flag & FILE_DIRSEL_ONLY) == 0) { - BLI_split_dirfile(filepath, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + if ((params->flag & FILE_DIRSEL_ONLY) == 0) { + BLI_split_dirfile( + filepath, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } else { - BLI_split_dir_part(filepath, sfile->params->dir, sizeof(sfile->params->dir)); + BLI_split_dir_part(filepath, params->dir, sizeof(params->dir)); } } } @@ -1605,9 +1605,10 @@ void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) bool file_draw_check_exists(SpaceFile *sfile) { if (sfile->op) { /* fails on reload */ - if (sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING)) { + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (params && (params->flag & FILE_CHECK_EXISTING)) { char filepath[FILE_MAX]; - BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file); + BLI_join_dirfile(filepath, sizeof(filepath), params->dir, params->file); if (BLI_is_file(filepath)) { return true; } @@ -1628,21 +1629,22 @@ static int file_exec(bContext *C, wmOperator *exec_op) Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); - struct FileDirEntry *file = filelist_file(sfile->files, sfile->params->active_file); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + struct FileDirEntry *file = filelist_file(sfile->files, params->active_file); char filepath[FILE_MAX]; if (file && file->redirection_path) { /* redirection_path is an absolute path that takes precedence - * over using sfile->params->dir + sfile->params->file. */ + * over using params->dir + params->file. */ BLI_split_dirfile(file->redirection_path, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + params->dir, + params->file, + sizeof(params->dir), + sizeof(params->file)); /* Update relpath with redirected filename as well so that the alternative - * combination of sfile->params->dir + relpath remains valid as well. */ + * combination of params->dir + relpath remains valid as well. */ MEM_freeN(file->relpath); - file->relpath = BLI_strdup(sfile->params->file); + file->relpath = BLI_strdup(params->file); } /* directory change */ @@ -1652,12 +1654,12 @@ static int file_exec(bContext *C, wmOperator *exec_op) } if (FILENAME_IS_PARENT(file->relpath)) { - BLI_path_parent_dir(sfile->params->dir); + BLI_path_parent_dir(params->dir); } else { - BLI_path_normalize(BKE_main_blendfile_path(bmain), sfile->params->dir); - BLI_path_append(sfile->params->dir, sizeof(sfile->params->dir) - 1, file->relpath); - BLI_path_slash_ensure(sfile->params->dir); + BLI_path_normalize(BKE_main_blendfile_path(bmain), params->dir); + BLI_path_append(params->dir, sizeof(params->dir) - 1, file->relpath); + BLI_path_slash_ensure(params->dir); } ED_file_change_dir(C); } @@ -1685,10 +1687,10 @@ static int file_exec(bContext *C, wmOperator *exec_op) file_sfile_to_operator_ex(bmain, op, sfile, filepath); - if (BLI_exists(sfile->params->dir)) { + if (BLI_exists(params->dir)) { fsmenu_insert_entry(ED_fsmenu_get(), FS_CATEGORY_RECENT, - sfile->params->dir, + params->dir, NULL, ICON_FILE_FOLDER, FS_INSERT_SAVE | FS_INSERT_FIRST); @@ -1792,15 +1794,16 @@ static int file_parent_exec(bContext *C, wmOperator *UNUSED(unused)) { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - if (BLI_path_parent_dir(sfile->params->dir)) { - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir); + if (params) { + if (BLI_path_parent_dir(params->dir)) { + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); ED_file_change_dir(C); - if (sfile->params->recursion_level > 1) { + if (params->recursion_level > 1) { /* Disable 'dirtree' recursion when going up in tree. */ - sfile->params->recursion_level = 0; - filelist_setrecursion(sfile->files, sfile->params->recursion_level); + params->recursion_level = 0; + filelist_setrecursion(sfile->files, params->recursion_level); } WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -1830,15 +1833,16 @@ void FILE_OT_parent(struct wmOperatorType *ot) static int file_previous_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { + if (params) { if (!sfile->folders_next) { sfile->folders_next = folderlist_new(); } - folderlist_pushdir(sfile->folders_next, sfile->params->dir); - folderlist_popdir(sfile->folders_prev, sfile->params->dir); - folderlist_pushdir(sfile->folders_next, sfile->params->dir); + folderlist_pushdir(sfile->folders_next, params->dir); + folderlist_popdir(sfile->folders_prev, params->dir); + folderlist_pushdir(sfile->folders_next, params->dir); ED_file_change_dir(C); } @@ -1868,16 +1872,17 @@ void FILE_OT_previous(struct wmOperatorType *ot) static int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) { SpaceFile *sfile = CTX_wm_space_file(C); - if (sfile->params) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (params) { if (!sfile->folders_next) { sfile->folders_next = folderlist_new(); } - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - folderlist_popdir(sfile->folders_next, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); + folderlist_popdir(sfile->folders_next, params->dir); /* update folders_prev so we can check for it in #folderlist_clear_next() */ - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); ED_file_change_dir(C); } @@ -1923,7 +1928,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w /* Due to async nature of file listing, we may execute this code before `file_refresh()` * editing entry is available in our listing, * so we also have to handle switching to rename mode here. */ - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); if ((params->rename_flag & (FILE_PARAMS_RENAME_PENDING | FILE_PARAMS_RENAME_POSTSCROLL_PENDING)) != 0) { file_params_renamefile_activate(sfile, params); @@ -2175,9 +2180,10 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); const bool do_diropen = RNA_boolean_get(op->ptr, "open"); - if (!sfile->params) { + if (!params) { BKE_report(op->reports, RPT_WARNING, "No parent directory given"); return OPERATOR_CANCELLED; } @@ -2193,7 +2199,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) if (generate_name) { /* create a new, non-existing folder name */ - if (!new_folder_path(sfile->params->dir, path, name)) { + if (!new_folder_path(params->dir, path, name)) { BKE_report(op->reports, RPT_ERROR, "Could not create new folder name"); return OPERATOR_CANCELLED; } @@ -2226,8 +2232,8 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) /* If we don't enter the directory directly, remember file to jump into editing. */ if (do_diropen == false) { - BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE); - sfile->params->rename_flag = FILE_PARAMS_RENAME_PENDING; + BLI_strncpy(params->renamefile, name, FILE_MAXFILE); + params->rename_flag = FILE_PARAMS_RENAME_PENDING; } /* set timer to smoothly view newly generated file */ @@ -2242,7 +2248,7 @@ static int file_directory_new_exec(bContext *C, wmOperator *op) ED_fileselect_clear(wm, CTX_data_scene(C), sfile); if (do_diropen) { - BLI_strncpy(sfile->params->dir, path, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, path, sizeof(params->dir)); ED_file_change_dir(C); } @@ -2284,38 +2290,37 @@ static void file_expand_directory(bContext *C) { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - if (BLI_path_is_rel(sfile->params->dir)) { + if (params) { + if (BLI_path_is_rel(params->dir)) { /* Use of 'default' folder here is just to avoid an error message on '//' prefix. */ - BLI_path_abs(sfile->params->dir, + BLI_path_abs(params->dir, G.relbase_valid ? BKE_main_blendfile_path(bmain) : BKE_appdir_folder_default()); } - else if (sfile->params->dir[0] == '~') { - char tmpstr[sizeof(sfile->params->dir) - 1]; - BLI_strncpy(tmpstr, sfile->params->dir + 1, sizeof(tmpstr)); - BLI_join_dirfile( - sfile->params->dir, sizeof(sfile->params->dir), BKE_appdir_folder_default(), tmpstr); + else if (params->dir[0] == '~') { + char tmpstr[sizeof(params->dir) - 1]; + BLI_strncpy(tmpstr, params->dir + 1, sizeof(tmpstr)); + BLI_join_dirfile(params->dir, sizeof(params->dir), BKE_appdir_folder_default(), tmpstr); } - else if (sfile->params->dir[0] == '\0') + else if (params->dir[0] == '\0') #ifndef WIN32 { - sfile->params->dir[0] = '/'; - sfile->params->dir[1] = '\0'; + params->dir[0] = '/'; + params->dir[1] = '\0'; } #else { - BLI_windows_get_default_root_dir(sfile->params->dir); + BLI_windows_get_default_root_dir(params->dir); } /* change "C:" --> "C:\", T28102. */ - else if ((isalpha(sfile->params->dir[0]) && (sfile->params->dir[1] == ':')) && - (sfile->params->dir[2] == '\0')) { - sfile->params->dir[2] = '\\'; - sfile->params->dir[3] = '\0'; + else if ((isalpha(params->dir[0]) && (params->dir[1] == ':')) && (params->dir[2] == '\0')) { + params->dir[2] = '\\'; + params->dir[3] = '\0'; } - else if (BLI_path_is_unc(sfile->params->dir)) { - BLI_path_normalize_unc(sfile->params->dir, FILE_MAX_LIBEXTRA); + else if (BLI_path_is_unc(params->dir)) { + BLI_path_normalize_unc(params->dir, FILE_MAX_LIBEXTRA); } #endif } @@ -2343,46 +2348,44 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - char old_dir[sizeof(sfile->params->dir)]; + if (params) { + char old_dir[sizeof(params->dir)]; - BLI_strncpy(old_dir, sfile->params->dir, sizeof(old_dir)); + BLI_strncpy(old_dir, params->dir, sizeof(old_dir)); file_expand_directory(C); /* special case, user may have pasted a filepath into the directory */ - if (!filelist_is_dir(sfile->files, sfile->params->dir)) { + if (!filelist_is_dir(sfile->files, params->dir)) { char tdir[FILE_MAX_LIBEXTRA]; char *group, *name; - if (BLI_is_file(sfile->params->dir)) { - char path[sizeof(sfile->params->dir)]; - BLI_strncpy(path, sfile->params->dir, sizeof(path)); - BLI_split_dirfile(path, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + if (BLI_is_file(params->dir)) { + char path[sizeof(params->dir)]; + BLI_strncpy(path, params->dir, sizeof(path)); + BLI_split_dirfile( + path, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } - else if (BLO_library_path_explode(sfile->params->dir, tdir, &group, &name)) { + else if (BLO_library_path_explode(params->dir, tdir, &group, &name)) { if (group) { BLI_path_append(tdir, sizeof(tdir), group); } - BLI_strncpy(sfile->params->dir, tdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, tdir, sizeof(params->dir)); if (name) { - BLI_strncpy(sfile->params->file, name, sizeof(sfile->params->file)); + BLI_strncpy(params->file, name, sizeof(params->file)); } else { - sfile->params->file[0] = '\0'; + params->file[0] = '\0'; } } } - BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), sfile->params->dir); + BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), params->dir); - if (filelist_is_dir(sfile->files, sfile->params->dir)) { - if (!STREQ(sfile->params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */ + if (filelist_is_dir(sfile->files, params->dir)) { + if (!STREQ(params->dir, old_dir)) { /* Avoids flickering when nothing's changed. */ /* if directory exists, enter it immediately */ ED_file_change_dir(C); } @@ -2392,10 +2395,10 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN /* UI_textbutton_activate_but(C, but); */ } #if defined(WIN32) - else if (!can_create_dir(sfile->params->dir)) { + else if (!can_create_dir(params->dir)) { const char *lastdir = folderlist_peeklastdir(sfile->folders_prev); if (lastdir) { - BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } } #endif @@ -2405,21 +2408,21 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN /* If we are 'inside' a blend library, we cannot do anything... */ if (lastdir && BLO_library_path_explode(lastdir, tdir, NULL, NULL)) { - BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } else { /* if not, ask to create it and enter if confirmed */ wmOperatorType *ot = WM_operatortype_find("FILE_OT_directory_new", false); PointerRNA ptr; WM_operator_properties_create_ptr(&ptr, ot); - RNA_string_set(&ptr, "directory", sfile->params->dir); + RNA_string_set(&ptr, "directory", params->dir); RNA_boolean_set(&ptr, "open", true); /* Enable confirmation prompt, else it's too easy * to accidentally create new directories. */ RNA_boolean_set(&ptr, "confirm", true); if (lastdir) { - BLI_strncpy(sfile->params->dir, lastdir, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, lastdir, sizeof(params->dir)); } WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); @@ -2435,39 +2438,39 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); uiBut *but = arg_but; char matched_file[FILE_MAX]; - char filepath[sizeof(sfile->params->dir)]; - if (sfile->params) { + if (params) { + char filepath[sizeof(params->dir)]; int matches; matched_file[0] = '\0'; filepath[0] = '\0'; file_expand_directory(C); - matches = file_select_match(sfile, sfile->params->file, matched_file); + matches = file_select_match(sfile, params->file, matched_file); /* *After* file_select_match! */ - BLI_filename_make_safe(sfile->params->file); + BLI_filename_make_safe(params->file); if (matches) { /* replace the pattern (or filename that the user typed in, * with the first selected file of the match */ - BLI_strncpy(sfile->params->file, matched_file, sizeof(sfile->params->file)); + BLI_strncpy(params->file, matched_file, sizeof(params->file)); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } if (matches == 1) { - BLI_join_dirfile( - filepath, sizeof(sfile->params->dir), sfile->params->dir, sfile->params->file); + BLI_join_dirfile(filepath, sizeof(params->dir), params->dir, params->file); /* if directory, open it and empty filename field */ if (filelist_is_dir(sfile->files, filepath)) { BLI_path_normalize_dir(BKE_main_blendfile_path(bmain), filepath); - BLI_strncpy(sfile->params->dir, filepath, sizeof(sfile->params->dir)); - sfile->params->file[0] = '\0'; + BLI_strncpy(params->dir, filepath, sizeof(params->dir)); + params->file[0] = '\0'; ED_file_change_dir(C); UI_textbutton_activate_but(C, but); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); @@ -2489,9 +2492,10 @@ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused)) { wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - sfile->params->flag ^= FILE_HIDE_DOT; + if (params) { + params->flag ^= FILE_HIDE_DOT; ED_fileselect_clear(wm, CTX_data_scene(C), sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -2525,7 +2529,8 @@ static bool file_filenum_poll(bContext *C) return false; } - return sfile->params && (sfile->params->flag & FILE_CHECK_EXISTING); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + return params && (params->flag & FILE_CHECK_EXISTING); } /** @@ -2563,11 +2568,12 @@ static void filenum_newname(char *name, size_t name_size, int add) static int file_filenum_exec(bContext *C, wmOperator *op) { SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); ScrArea *area = CTX_wm_area(C); int inc = RNA_int_get(op->ptr, "increment"); - if (sfile->params && (inc != 0)) { - filenum_newname(sfile->params->file, sizeof(sfile->params->file), inc); + if (params && (inc != 0)) { + filenum_newname(params->file, sizeof(params->file), inc); ED_area_tag_redraw(area); file_draw_check(C); // WM_event_add_notifier(C, NC_WINDOW, NULL); @@ -2606,12 +2612,14 @@ static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool requ if ((require_selected == false) || (filelist_entry_select_get(sfile->files, file, CHECK_ALL) & FILE_SEL_SELECTED)) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + filelist_entry_select_index_set( sfile->files, file_idx, FILE_SEL_ADD, FILE_SEL_EDITING, CHECK_ALL); - BLI_strncpy(sfile->params->renamefile, file->relpath, FILE_MAXFILE); + BLI_strncpy(params->renamefile, file->relpath, FILE_MAXFILE); /* We can skip the pending state, * as we can directly set FILE_SEL_EDITING on the expected entry here. */ - sfile->params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; + params->rename_flag = FILE_PARAMS_RENAME_ACTIVE; } } } @@ -2620,9 +2628,10 @@ static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent { ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - file_rename_state_activate(sfile, sfile->params->active_file, true); + if (params) { + file_rename_state_activate(sfile, params->active_file, true); ED_area_tag_redraw(area); } @@ -2633,9 +2642,10 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *area = CTX_wm_area(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile->params) { - file_rename_state_activate(sfile, sfile->params->highlight_file, false); + if (params) { + file_rename_state_activate(sfile, params->highlight_file, false); ED_area_tag_redraw(area); } @@ -2665,8 +2675,9 @@ static bool file_delete_poll(bContext *C) { bool poll = ED_operator_file_active(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); - if (sfile && sfile->params) { + if (sfile && params) { char dir[FILE_MAX_LIBEXTRA]; int numfiles = filelist_files_ensure(sfile->files); int i; @@ -2695,6 +2706,7 @@ static int file_delete_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); int numfiles = filelist_files_ensure(sfile->files); const char *error_message = NULL; @@ -2704,7 +2716,7 @@ static int file_delete_exec(bContext *C, wmOperator *op) if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) { FileDirEntry *file = filelist_file(sfile->files, i); char str[FILE_MAX]; - BLI_join_dirfile(str, sizeof(str), sfile->params->dir, file->relpath); + BLI_join_dirfile(str, sizeof(str), params->dir, file->relpath); if (BLI_delete_soft(str, &error_message) != 0 || BLI_exists(str)) { report_error = true; } @@ -2752,11 +2764,12 @@ static int file_start_filter_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *area = CTX_wm_area(C); ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_UI); - SpaceFile *sf = CTX_wm_space_file(C); + SpaceFile *sfile = CTX_wm_space_file(C); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); ARegion *region_ctx = CTX_wm_region(C); CTX_wm_region_set(C, region); - UI_textbutton_activate_rna(C, region, sf->params, "filter_search"); + UI_textbutton_activate_rna(C, region, params, "filter_search"); CTX_wm_region_set(C, region_ctx); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 22d206c0a70..afa85d183d8 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -132,7 +132,7 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel) { bScreen *screen = CTX_wm_screen(C); SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); uiBlock *block = uiLayoutGetBlock(panel->layout); uiBut *but; uiLayout *row; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 9e51b6ca4ba..e87142a7096 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -149,6 +149,7 @@ const char *folderlist_peeklastdir(ListBase *folderlist) int folderlist_clear_next(struct SpaceFile *sfile) { + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); struct FolderList *folder; /* if there is no folder_next there is nothing we can clear */ @@ -159,7 +160,7 @@ int folderlist_clear_next(struct SpaceFile *sfile) /* if previous_folder, next_folder or refresh_folder operators are executed * it doesn't clear folder_next */ folder = sfile->folders_prev->last; - if ((!folder) || (BLI_path_cmp(folder->foldername, sfile->params->dir) == 0)) { + if ((!folder) || (BLI_path_cmp(folder->foldername, params->dir) == 0)) { return 0; } @@ -629,7 +630,7 @@ void filelist_setsorting(struct FileList *filelist, const short sort, bool inver /* ********** Filter helpers ********** */ /* True if filename is meant to be hidden, eg. starting with period. */ -static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *file) +static bool is_hidden_dot_filename(const char *filename, const FileListInternEntry *file) { if (filename[0] == '.' && !ELEM(filename[1], '.', '\0')) { return true; /* ignore .file */ @@ -670,8 +671,8 @@ static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *fi /* True if should be hidden, based on current filtering. */ static bool is_filtered_hidden(const char *filename, - FileListFilter *filter, - FileListInternEntry *file) + const FileListFilter *filter, + const FileListInternEntry *file) { if ((filename[0] == '.') && (filename[1] == '\0')) { return true; /* Ignore . */ @@ -2620,7 +2621,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const nbr_entries++; } - BLI_linklist_free(names, free); + BLI_linklist_freeN(names); return nbr_entries; } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 15c6972c5f5..6e933e53a8f 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -77,18 +77,20 @@ #define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X) -FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile) +FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile) { - if (!sfile->params) { - ED_fileselect_set_params(sfile); + if (!sfile) { + /* Sometimes called in poll before space type was checked. */ + return NULL; } + return sfile->params; } /** * \note RNA_struct_property_is_set_ex is used here because we want * the previously used settings to be used here rather than overriding them */ -short ED_fileselect_set_params(SpaceFile *sfile) +static FileSelectParams *fileselect_ensure_updated_file_params(SpaceFile *sfile) { FileSelectParams *params; wmOperator *op = sfile->op; @@ -136,20 +138,17 @@ short ED_fileselect_set_params(SpaceFile *sfile) RNA_string_get(op->ptr, "filepath", name); if (params->type == FILE_LOADLIB) { BLI_strncpy(params->dir, name, sizeof(params->dir)); - sfile->params->file[0] = '\0'; + params->file[0] = '\0'; } else { - BLI_split_dirfile(name, - sfile->params->dir, - sfile->params->file, - sizeof(sfile->params->dir), - sizeof(sfile->params->file)); + BLI_split_dirfile( + name, params->dir, params->file, sizeof(params->dir), sizeof(params->file)); } } else { if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", false)) { RNA_string_get(op->ptr, "directory", params->dir); - sfile->params->file[0] = '\0'; + params->file[0] = '\0'; } if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", false)) { @@ -306,26 +305,34 @@ short ED_fileselect_set_params(SpaceFile *sfile) sfile->folders_prev = folderlist_new(); } - if (!sfile->params->dir[0]) { + if (!params->dir[0]) { if (blendfile_path[0] != '\0') { - BLI_split_dir_part(blendfile_path, sfile->params->dir, sizeof(sfile->params->dir)); + BLI_split_dir_part(blendfile_path, params->dir, sizeof(params->dir)); } else { const char *doc_path = BKE_appdir_folder_default(); if (doc_path) { - BLI_strncpy(sfile->params->dir, doc_path, sizeof(sfile->params->dir)); + BLI_strncpy(params->dir, doc_path, sizeof(params->dir)); } } } - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); /* Switching thumbnails needs to recalc layout T28809. */ if (sfile->layout) { sfile->layout->dirty = true; } - return 1; + return params; +} + +FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile) +{ + if (!sfile->params) { + fileselect_ensure_updated_file_params(sfile); + } + return sfile->params; } /* The subset of FileSelectParams.flag items we store into preferences. Note that FILE_SORT_ALPHA @@ -364,28 +371,26 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) wmOperator *op = sfile->op; UserDef_FileSpaceData *sfile_udata = &U.file_space_data; - ED_fileselect_set_params(sfile); - + FileSelectParams *params = fileselect_ensure_updated_file_params(sfile); if (!op) { return; } - sfile->params->thumbnail_size = sfile_udata->thumbnail_size; - sfile->params->details_flags = sfile_udata->details_flags; - sfile->params->filter_id = sfile_udata->filter_id; + params->thumbnail_size = sfile_udata->thumbnail_size; + params->details_flags = sfile_udata->details_flags; + params->filter_id = sfile_udata->filter_id; /* Combine flags we take from params with the flags we take from userdef. */ - sfile->params->flag = (sfile->params->flag & ~PARAMS_FLAGS_REMEMBERED) | - (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED); + params->flag = (params->flag & ~PARAMS_FLAGS_REMEMBERED) | + (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED); if (file_select_use_default_display_type(sfile)) { - sfile->params->display = sfile_udata->display_type; + params->display = sfile_udata->display_type; } if (file_select_use_default_sort_type(sfile)) { - sfile->params->sort = sfile_udata->sort_type; + params->sort = sfile_udata->sort_type; /* For the default sorting, also take invert flag from userdef. */ - sfile->params->flag = (sfile->params->flag & ~FILE_SORT_INVERT) | - (sfile_udata->flag & FILE_SORT_INVERT); + params->flag = (params->flag & ~FILE_SORT_INVERT) | (sfile_udata->flag & FILE_SORT_INVERT); } } @@ -400,25 +405,26 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, const int temp_win_size[2], const bool is_maximized) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); UserDef_FileSpaceData *sfile_udata_new = &U.file_space_data; UserDef_FileSpaceData sfile_udata_old = U.file_space_data; - sfile_udata_new->thumbnail_size = sfile->params->thumbnail_size; - sfile_udata_new->details_flags = sfile->params->details_flags; - sfile_udata_new->flag = sfile->params->flag & PARAMS_FLAGS_REMEMBERED; - sfile_udata_new->filter_id = sfile->params->filter_id; + sfile_udata_new->thumbnail_size = params->thumbnail_size; + sfile_udata_new->details_flags = params->details_flags; + sfile_udata_new->flag = params->flag & PARAMS_FLAGS_REMEMBERED; + sfile_udata_new->filter_id = params->filter_id; /* In some rare cases, operators ask for a specific display or sort type (e.g. chronological * sorting for "Recover Auto Save"). So the settings are optimized for a specific operation. * Don't let that change the userdef memory for more general cases. */ if (file_select_use_default_display_type(sfile)) { - sfile_udata_new->display_type = sfile->params->display; + sfile_udata_new->display_type = params->display; } if (file_select_use_default_sort_type(sfile)) { - sfile_udata_new->sort_type = sfile->params->sort; + sfile_udata_new->sort_type = params->sort; /* In this case also remember the invert flag. */ sfile_udata_new->flag = (sfile_udata_new->flag & ~FILE_SORT_INVERT) | - (sfile->params->flag & FILE_SORT_INVERT); + (params->flag & FILE_SORT_INVERT); } if (temp_win_size && !is_maximized) { @@ -434,10 +440,11 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, void ED_fileselect_reset_params(SpaceFile *sfile) { - sfile->params->type = FILE_UNIX; - sfile->params->flag = 0; - sfile->params->title[0] = '\0'; - sfile->params->active_file = -1; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + params->type = FILE_UNIX; + params->flag = 0; + params->title[0] = '\0'; + params->active_file = -1; } /** @@ -447,7 +454,8 @@ void fileselect_file_set(SpaceFile *sfile, const int index) { const struct FileDirEntry *file = filelist_file(sfile->files, index); if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) { - BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + BLI_strncpy(params->file, file->relpath, FILE_MAXFILE); } } @@ -759,7 +767,7 @@ static void file_attribute_columns_init(const FileSelectParams *params, FileLayo void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *region) { - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_get_active_params(sfile); FileLayout *layout = NULL; View2D *v2d = ®ion->v2d; int numfiles; @@ -873,7 +881,8 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) return; } SpaceFile *sfile = area->spacedata.first; - if (sfile->params) { + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + if (params) { wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = WM_windows_scene_get_from_screen(wm, screen); if (LIKELY(scene != NULL)) { @@ -882,20 +891,20 @@ void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) /* Clear search string, it is very rare to want to keep that filter while changing dir, * and usually very annoying to keep it actually! */ - sfile->params->filter_search[0] = '\0'; - sfile->params->active_file = -1; + params->filter_search[0] = '\0'; + params->active_file = -1; - if (!filelist_is_dir(sfile->files, sfile->params->dir)) { - BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); + if (!filelist_is_dir(sfile->files, params->dir)) { + BLI_strncpy(params->dir, filelist_dir(sfile->files), sizeof(params->dir)); /* could return but just refresh the current dir */ } - filelist_setdir(sfile->files, sfile->params->dir); + filelist_setdir(sfile->files, params->dir); if (folderlist_clear_next(sfile)) { folderlist_free(sfile->folders_next); } - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, params->dir); file_draw_check_ex(C, area); } @@ -1010,7 +1019,8 @@ void ED_fileselect_clear(wmWindowManager *wm, Scene *owner_scene, SpaceFile *sfi filelist_clear(sfile->files); } - sfile->params->highlight_file = -1; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + params->highlight_file = -1; WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL); } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 6ffe553e076..c72ca58abba 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -270,7 +270,7 @@ static void file_refresh(const bContext *C, ScrArea *area) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); struct FSMenu *fsmenu = ED_fsmenu_get(); if (!sfile->folders_prev) { @@ -413,7 +413,7 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), struct wmMsgBus *mbus) { SpaceFile *sfile = area->spacedata.first; - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); /* This is a bit odd that a region owns the subscriber for an area, * keep for now since all subscribers for WM are regions. * May be worth re-visiting later. */ @@ -446,7 +446,7 @@ static void file_main_region_draw(const bContext *C, ARegion *region) { /* draw entirely, view changes should be handled here */ SpaceFile *sfile = CTX_wm_space_file(C); - FileSelectParams *params = ED_fileselect_get_params(sfile); + FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); View2D *v2d = ®ion->v2d; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 1647fd4a6a6..c3e4eceef6e 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -72,7 +72,9 @@ /* ************************************************************************** */ /* INSERT DUPLICATE AND BAKE KEYFRAMES */ -/* ******************** Insert Keyframes Operator ************************* */ +/* -------------------------------------------------------------------- */ +/** \name Insert Keyframes Operator + * \{ */ /* Mode defines for insert keyframes tool. */ typedef enum eGraphKeys_InsertKey_Types { @@ -290,7 +292,11 @@ void GRAPH_OT_keyframe_insert(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_insertkey_types, 0, "Type", ""); } -/* ******************** Click-Insert Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Click-Insert Keyframes Operator + * \{ */ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) { @@ -444,8 +450,13 @@ void GRAPH_OT_click_insert(wmOperatorType *ot) "Extend selection instead of deselecting everything first"); } -/* ******************** Copy/Paste Keyframes Operator ************************* */ -/* NOTE: the backend code for this is shared with the dopesheet editor */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy/Paste Keyframes Operator + * + * \note the back-end code for this is shared with the dope-sheet editor. + * \{ */ static short copy_graph_keys(bAnimContext *ac) { @@ -605,7 +616,11 @@ void GRAPH_OT_paste(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************** Duplicate Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Keyframes Operator + * \{ */ static void duplicate_graph_keys(bAnimContext *ac) { @@ -667,7 +682,11 @@ void GRAPH_OT_duplicate(wmOperatorType *ot) RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); } -/* ******************** Delete Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Keyframes Operator + * \{ */ static bool delete_graph_keys(bAnimContext *ac) { @@ -746,7 +765,11 @@ void GRAPH_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************** Clean Keyframes Operator ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clean Keyframes Operator + * \{ */ static void clean_graph_keys(bAnimContext *ac, float thresh, bool clean_chan) { @@ -816,8 +839,13 @@ void GRAPH_OT_clean(wmOperatorType *ot) RNA_def_boolean(ot->srna, "channels", false, "Channels", ""); } -/* ******************** Bake F-Curve Operator *********************** */ -/* This operator bakes the data of the selected F-Curves to F-Points */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Bake F-Curve Operator + * + * This operator bakes the data of the selected F-Curves to F-Points. + * \{ */ /* Bake each F-Curve into a set of samples. */ static void bake_graph_curves(bAnimContext *ac, int start, int end) @@ -899,8 +927,13 @@ void GRAPH_OT_bake(wmOperatorType *ot) /* TODO: add props for start/end frames (Joshua Leung 2009) */ } -/* ******************** Un-Bake F-Curve Operator *********************** */ -/* This operator unbakes the data of the selected F-Points to F-Curves. */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Un-Bake F-Curve Operator + * + * This operator un-bakes the data of the selected F-Points to F-Curves. + * \{ */ /* Un-Bake F-Points into F-Curves. */ static void unbake_graph_curves(bAnimContext *ac, int start, int end) @@ -970,8 +1003,13 @@ void GRAPH_OT_unbake(wmOperatorType *ot) #ifdef WITH_AUDASPACE -/* ******************** Sound Bake F-Curve Operator *********************** */ -/* This operator bakes the given sound to the selected F-Curves */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sound Bake F-Curve Operator + * + * This operator bakes the given sound to the selected F-Curves. + * \{ */ /* ------------------- */ @@ -1204,10 +1242,14 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot) 0.1); } -/* ******************** Sample Keyframes Operator *********************** */ -/* This operator 'bakes' the values of the curve into new keyframes between pairs +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sample Keyframes Operator + * + * This operator 'bakes' the values of the curve into new keyframes between pairs * of selected keyframes. It is useful for creating keyframes for tweaking overlap. - */ + * \{ */ /* Evaluates the curves between each selected keyframe on each frame, and keys the value. */ static void sample_graph_keys(bAnimContext *ac) @@ -1267,10 +1309,14 @@ void GRAPH_OT_sample(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + /* ************************************************************************** */ /* EXTRAPOLATION MODE AND KEYFRAME HANDLE SETTINGS */ -/* ******************** Set Extrapolation-Type Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Set Extrapolation-Type Operator + * \{ */ /* Defines for make/clear cyclic extrapolation tools. */ #define MAKE_CYCLIC_EXPO -1 @@ -1400,7 +1446,11 @@ void GRAPH_OT_extrapolation_type(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_expo_types, 0, "Type", ""); } -/* ******************** Set Interpolation-Type Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Interpolation-Type Operator + * \{ */ /* This function is responsible for setting interpolation mode for keyframes. */ static void setipo_graph_keys(bAnimContext *ac, short mode) @@ -1474,7 +1524,11 @@ void GRAPH_OT_interpolation_type(wmOperatorType *ot) ot->srna, "type", rna_enum_beztriple_interpolation_mode_items, 0, "Type", ""); } -/* ******************** Set Easing Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Easing Operator + * \{ */ static void seteasing_graph_keys(bAnimContext *ac, short mode) { @@ -1545,7 +1599,11 @@ void GRAPH_OT_easing_type(wmOperatorType *ot) ot->srna, "type", rna_enum_beztriple_interpolation_easing_items, 0, "Type", ""); } -/* ******************** Set Handle-Type Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Handle-Type Operator + * \{ */ /* This function is responsible for setting handle-type of selected keyframes. */ static void sethandles_graph_keys(bAnimContext *ac, short mode) @@ -1624,15 +1682,19 @@ void GRAPH_OT_handle_type(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_keyframe_handle_type_items, 0, "Type", ""); } +/** \} */ + /* ************************************************************************** */ /* EULER FILTER */ -/* ***************** 'Euler Filter' Operator **************************** */ -/* Euler filter tools (as seen in Maya), are necessary for working with 'baked' +/* -------------------------------------------------------------------- */ +/** \name 'Euler Filter' Operator + * + * Euler filter tools (as seen in Maya), are necessary for working with 'baked' * rotation curves (with Euler rotations). The main purpose of such tools is to * resolve any discontinuities that may arise in the curves due to the clamping * of values to -180 degrees to 180 degrees. - */ + * \{ */ /* Set of three euler-rotation F-Curves. */ typedef struct tEulerFilter { @@ -1903,7 +1965,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op) if (curves_seen < 3) { /* Showing the entire error message makes no sense when the artist is only trying to filter * one or two curves. */ - BKE_report(op->reports, RPT_WARNING, "No Euler Rotations could be corrected."); + BKE_report(op->reports, RPT_WARNING, "No Euler Rotations could be corrected"); } else { BKE_report(op->reports, @@ -1919,15 +1981,15 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op) BLI_assert(curves_filtered < curves_seen); BKE_reportf(op->reports, RPT_INFO, - "%d of %d rotation channels were filtered. See the Info window for details.", + "%d of %d rotation channels were filtered (see the Info window for details)", curves_filtered, curves_seen); } else if (curves_seen == 1) { - BKE_report(op->reports, RPT_INFO, "The rotation channel was filtered."); + BKE_report(op->reports, RPT_INFO, "The rotation channel was filtered"); } else { - BKE_reportf(op->reports, RPT_INFO, "All %d rotation channels were filtered.", curves_seen); + BKE_reportf(op->reports, RPT_INFO, "All %d rotation channels were filtered", curves_seen); } /* Set notifier that keyframes have changed. */ @@ -1955,10 +2017,14 @@ void GRAPH_OT_euler_filter(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + /* ************************************************************************** */ /* SNAPPING */ -/* ***************** Jump to Selected Frames Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Jump to Selected Frames Operator + * \{ */ static bool graphkeys_framejump_poll(bContext *C) { @@ -2110,7 +2176,11 @@ void GRAPH_OT_snap_cursor_value(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************** Snap Keyframes Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snap Keyframes Operator + * \{ */ /* Defines for snap keyframes tool. */ static const EnumPropertyItem prop_graphkeys_snap_types[] = { @@ -2262,7 +2332,11 @@ void GRAPH_OT_snap(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_snap_types, 0, "Type", ""); } -/* ******************** Mirror Keyframes Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mirror Keyframes Operator + * \{ */ /* Defines for mirror keyframes tool. */ static const EnumPropertyItem prop_graphkeys_mirror_types[] = { @@ -2421,7 +2495,11 @@ void GRAPH_OT_mirror(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_graphkeys_mirror_types, 0, "Type", ""); } -/* ******************** Smooth Keyframes Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Smooth Keyframes Operator + * \{ */ static int graphkeys_smooth_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2475,10 +2553,14 @@ void GRAPH_OT_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + /* ************************************************************************** */ /* F-CURVE MODIFIERS */ -/* ******************** Add F-Modifier Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Add F-Modifier Operator + * \{ */ static const EnumPropertyItem *graph_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), @@ -2596,7 +2678,11 @@ void GRAPH_OT_fmodifier_add(wmOperatorType *ot) ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve"); } -/* ******************** Copy F-Modifiers Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy F-Modifiers Operator + * \{ */ static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op) { @@ -2658,7 +2744,11 @@ void GRAPH_OT_fmodifier_copy(wmOperatorType *ot) #endif } -/* ******************** Paste F-Modifiers Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste F-Modifiers Operator + * \{ */ static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op) { @@ -2746,10 +2836,14 @@ void GRAPH_OT_fmodifier_paste(wmOperatorType *ot) "Replace existing F-Modifiers, instead of just appending to the end of the existing list"); } +/** \} */ + /* ************************************************************************** */ /* Drivers */ -/* ******************** Copy Driver Vars Operator *********************** */ +/* -------------------------------------------------------------------- */ +/** \name Copy Driver Variables Operator + * \{ */ static int graph_driver_vars_copy_exec(bContext *C, wmOperator *op) { @@ -2786,7 +2880,11 @@ void GRAPH_OT_driver_variables_copy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************** Paste Driver Vars Operator *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste Driver Variables Operator + * \{ */ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op) { @@ -2838,7 +2936,11 @@ void GRAPH_OT_driver_variables_paste(wmOperatorType *ot) "existing list"); } -/* ************************************************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Invalid Drivers Operator + * \{ */ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op) { @@ -2926,3 +3028,5 @@ void GRAPH_OT_driver_delete_invalid(wmOperatorType *ot) /* Flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 007f99e3ce5..12035ab6b61 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -501,7 +501,6 @@ void GRAPH_OT_select_all(wmOperatorType *ot) * The selection backend is also reused for the Lasso and Circle select operators. */ - static rctf initialize_box_select_coords(const bAnimContext *ac, const rctf *rectf_view) { const View2D *v2d = &ac->region->v2d; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 0fa48059cdc..a2c0819dc60 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2649,7 +2649,7 @@ void IMAGE_OT_new(wmOperatorType *ot) "Generated Type", "Fill the image with a grid for UV map testing"); RNA_def_boolean( - ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); + ot->srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth"); RNA_def_property_flag(prop, PROP_HIDDEN); prop = RNA_def_boolean( ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views"); @@ -3737,7 +3737,7 @@ static void def_fill_tile(StructOrFunctionRNA *srna) /* Only needed when filling the first tile. */ RNA_def_boolean( - srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); + srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth"); RNA_def_boolean(srna, "alpha", 1, "Alpha", "Create an image with an alpha channel"); } diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 890bb8a64bc..ffac5c982d6 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -559,12 +559,23 @@ static void get_stats_string( stats_fmt->totgpstroke, stats_fmt->totgppoint); } - else if (stats_is_object_dynamic_topology_sculpt(ob)) { - *ofs += BLI_snprintf(info + *ofs, - len - *ofs, - TIP_("Verts:%s | Tris:%s"), - stats_fmt->totvert, - stats_fmt->tottri); + else if (ob && (object_mode & OB_MODE_SCULPT)) { + if (stats_is_object_dynamic_topology_sculpt(ob)) { + *ofs += BLI_snprintf(info + *ofs, + len - *ofs, + TIP_("Verts:%s | Tris:%s"), + stats_fmt->totvert, + stats_fmt->tottri); + } + else { + *ofs += BLI_snprintf(info + *ofs, + len - *ofs, + TIP_("Verts:%s/%s | Faces:%s/%s"), + stats_fmt->totvertsculpt, + stats_fmt->totvert, + stats_fmt->totfacesculpt, + stats_fmt->totface); + } } else { *ofs += BLI_snprintf(info + *ofs, diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 561de5e82a6..9832ca975cf 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -292,7 +292,7 @@ static int mouse_nla_channels( /* TODO: make this use the operator instead of calling the function directly * however, calling the operator requires that we supply the args, * and that works with proper buttons only */ - BKE_nla_action_pushdown(adt); + BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ale->id)); } else { /* when in tweakmode, this button becomes the toggle for mapped editing */ @@ -516,7 +516,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op) } /* 'push-down' action - only usable when not in TweakMode */ - BKE_nla_action_pushdown(adt); + BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id)); struct Main *bmain = CTX_data_main(C); DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION); @@ -648,19 +648,21 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel) NlaTrack *nlt = (NlaTrack *)ale->data; AnimData *adt = ale->adt; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* check if just adding a new track above this one, * or whether we're adding a new one to the top of the stack that this one belongs to */ if (above_sel) { /* just add a new one above this one */ - BKE_nlatrack_add(adt, nlt); + BKE_nlatrack_add(adt, nlt, is_liboverride); ale->update = ANIM_UPDATE_DEPS; added = true; } else if ((lastAdt == NULL) || (adt != lastAdt)) { /* add one track to the top of the owning AnimData's stack, * then don't add anymore to this stack */ - BKE_nlatrack_add(adt, NULL); + BKE_nlatrack_add(adt, NULL, is_liboverride); lastAdt = adt; ale->update = ANIM_UPDATE_DEPS; added = true; @@ -698,7 +700,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac) /* ensure it is empty */ if (BLI_listbase_is_empty(&adt->nla_tracks)) { /* add new track to this AnimData block then */ - BKE_nlatrack_add(adt, NULL); + BKE_nlatrack_add(adt, NULL, ID_IS_OVERRIDE_LIBRARY(ale->id)); ale->update = ANIM_UPDATE_DEPS; added = true; } @@ -796,6 +798,11 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nlt = (NlaTrack *)ale->data; AnimData *adt = ale->adt; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No deletion of non-local tracks of override data. */ + continue; + } + /* if track is currently 'solo', then AnimData should have its * 'has solo' flag disabled */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index ed8e5ad76e9..3fa1b614a03 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -649,6 +649,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) NlaTrack *nlt = (NlaTrack *)ale->data; AnimData *adt = ale->adt; NlaStrip *strip = NULL; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); /* Sanity check: only apply actions of the right type for this ID. * NOTE: in the case that this hasn't been set, @@ -671,12 +672,12 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) strip->start = cfra; /* firstly try adding strip to our current track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) { /* trying to add to the current failed (no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); } /* auto-name it */ @@ -886,6 +887,7 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op)) AnimData *adt = ale->adt; NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); /* does this belong to speaker - assumed to live on Object level only */ if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER)) { @@ -899,12 +901,12 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op)) strip->end += cfra; /* firstly try adding strip to our current track, but if that fails, add to a new track */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) { /* trying to add to the current failed (no space), * so add a new track to the stack, and add to that... */ - nlt = BKE_nlatrack_add(adt, NULL); - BKE_nlatrack_add_strip(nlt, strip); + nlt = BKE_nlatrack_add(adt, NULL, is_liboverride); + BKE_nlatrack_add_strip(nlt, strip, is_liboverride); } /* auto-name it */ @@ -966,6 +968,11 @@ static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op)) AnimData *adt = ale->adt; NlaStrip *strip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No making metastrips in non-local tracks of override data. */ + continue; + } + /* create meta-strips from the continuous chains of selected strips */ BKE_nlastrips_make_metas(&nlt->strips, 0); @@ -1030,6 +1037,11 @@ static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op)) for (ale = anim_data.first; ale; ale = ale->next) { NlaTrack *nlt = (NlaTrack *)ale->data; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No removing metastrips from non-local tracks of override data. */ + continue; + } + /* clear all selected meta-strips, regardless of whether they are temporary or not */ BKE_nlastrips_clear_metas(&nlt->strips, 1, 0); @@ -1096,6 +1108,11 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) NlaStrip *strip, *nstrip, *next; NlaTrack *track; + /* Note: We allow this operator in override context because it is almost always (from possible + * default user interactions) paired with the transform one, which will ensure that the new + * strip ends up in a valid (local) track. */ + + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); for (strip = nlt->strips.first; strip; strip = next) { next = strip->next; @@ -1106,13 +1123,13 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op) /* in case there's no space in the track above, * or we haven't got a reference to it yet, try adding */ - if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) { + if (BKE_nlatrack_add_strip(nlt->next, nstrip, is_liboverride) == 0) { /* need to add a new track above the one above the current one * - if the current one is the last one, nlt->next will be NULL, which defaults to adding * at the top of the stack anyway... */ - track = BKE_nlatrack_add(adt, nlt->next); - BKE_nlatrack_add_strip(track, nstrip); + track = BKE_nlatrack_add(adt, nlt->next, is_liboverride); + BKE_nlatrack_add_strip(track, nstrip, is_liboverride); } /* deselect the original and the active flag */ @@ -1209,6 +1226,11 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip, *nstrip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No deletion of strips in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = nstrip) { nstrip = strip->next; @@ -1359,6 +1381,11 @@ static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op)) AnimData *adt = ale->adt; NlaStrip *strip, *next; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No splitting of strips in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = next) { next = strip->next; @@ -1502,6 +1529,12 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op) NlaStrip *strip, *stripN = NULL; NlaStrip *area = NULL, *sb = NULL; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No re-ordering of strips whithin non-local tracks of override data. */ + continue; + } /* make temporary metastrips so that entire islands of selections can be moved around */ BKE_nlastrips_make_metas(&nlt->strips, 1); @@ -1610,8 +1643,8 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op) } /* add strips back to track now */ - BKE_nlatrack_add_strip(nlt, area); - BKE_nlatrack_add_strip(nlt, sb); + BKE_nlatrack_add_strip(nlt, area, is_liboverride); + BKE_nlatrack_add_strip(nlt, sb, is_liboverride); } /* clear (temp) metastrips */ @@ -1674,11 +1707,19 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nltn = nlt->next; NlaStrip *strip, *stripn; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* if this track has no tracks after it, skip for now... */ if (nltn == NULL) { continue; } + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) || + BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltn)) { + /* No moving of strips in non-local tracks of override data. */ + continue; + } + /* for every selected strip, try to move */ for (strip = nlt->strips.first; strip; strip = stripn) { stripn = strip->next; @@ -1689,7 +1730,7 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op)) /* remove from its current track, and add to the one above * (it 'should' work, so no need to worry) */ BLI_remlink(&nlt->strips, strip); - BKE_nlatrack_add_strip(nltn, strip); + BKE_nlatrack_add_strip(nltn, strip, is_liboverride); } } } @@ -1751,11 +1792,19 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op)) NlaTrack *nltp = nlt->prev; NlaStrip *strip, *stripn; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* if this track has no tracks before it, skip for now... */ if (nltp == NULL) { continue; } + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) || + BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltp)) { + /* No moving of strips in non-local tracks of override data. */ + continue; + } + /* for every selected strip, try to move */ for (strip = nlt->strips.first; strip; strip = stripn) { stripn = strip->next; @@ -1766,7 +1815,7 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op)) /* remove from its current track, and add to the one above * (it 'should' work, so no need to worry) */ BLI_remlink(&nlt->strips, strip); - BKE_nlatrack_add_strip(nltp, strip); + BKE_nlatrack_add_strip(nltp, strip, is_liboverride); } } } @@ -2023,11 +2072,11 @@ static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op)) /* strip must be selected, and must be action-clip only * (transitions don't have scale) */ if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) { - /* if the referenced action is used by other strips, - * make this strip use its own copy */ - if (strip->act == NULL) { + if (strip->act == NULL || ID_IS_OVERRIDE_LIBRARY(strip->act) || ID_IS_LINKED(strip->act)) { continue; } + /* if the referenced action is used by other strips, + * make this strip use its own copy */ if (strip->act->id.us > 1) { /* make a copy of the Action to work on */ bAction *act = (bAction *)BKE_id_copy(bmain, &strip->act->id); @@ -2200,6 +2249,8 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op) NlaStrip *strip, *stripn; NlaTrack *track; + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); + /* create meta-strips from the continuous chains of selected strips */ BKE_nlastrips_make_metas(&nlt->strips, 1); @@ -2255,10 +2306,10 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op) BLI_remlink(&tmp_strips, strip); /* in case there's no space in the current track, try adding */ - if (BKE_nlatrack_add_strip(nlt, strip) == 0) { + if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) { /* need to add a new track above the current one */ - track = BKE_nlatrack_add(adt, nlt); - BKE_nlatrack_add_strip(track, strip); + track = BKE_nlatrack_add(adt, nlt, is_liboverride); + BKE_nlatrack_add_strip(track, strip, is_liboverride); /* clear temp meta-strips on this new track, * as we may not be able to get back to it */ @@ -2375,6 +2426,11 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No adding f-modifiers to strips in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = strip->next) { /* can F-Modifier be added to the current strip? */ if (active_only) { @@ -2552,6 +2608,11 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op) NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; + if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { + /* No pasting in non-local tracks of override data. */ + continue; + } + for (strip = nlt->strips.first; strip; strip = strip->next) { /* can F-Modifier be added to the current strip? */ if (active_only) { diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index 996570fae25..74f99540bee 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -48,10 +48,23 @@ set(SRC tree/tree_display.cc tree/tree_display_libraries.cc tree/tree_display_view_layer.cc + tree/tree_display_sequencer.cc + tree/tree_display_orphaned.cc + tree/tree_display_scenes.cc + tree/tree_display_data.cc + tree/tree_element.cc + tree/tree_element_anim_data.cc + tree/tree_element_driver_base.cc + tree/tree_element_nla.cc outliner_intern.h tree/tree_display.h tree/tree_display.hh + tree/tree_element.h + tree/tree_element.hh + tree/tree_element_anim_data.hh + tree/tree_element_driver_base.hh + tree/tree_element_nla.hh ) set(LIB diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 865e06bf0b6..d3da7b80765 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -854,7 +854,8 @@ static bool datastack_drop_poll(bContext *C, SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); ARegion *region = CTX_wm_region(C); - bool changed = outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false); + bool changed = outliner_flag_set( + &space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false); StackDropData *drop_data = drag->poin; if (!drop_data) { @@ -1173,7 +1174,8 @@ static bool collection_drop_poll(bContext *C, { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); ARegion *region = CTX_wm_region(C); - bool changed = outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false); + bool changed = outliner_flag_set( + &space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false); CollectionDrop data; if (!event->shift && collection_drop_init(C, drag, event, &data)) { diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index ea2e3ce2565..6364fbc0a87 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2782,7 +2782,7 @@ static void outliner_draw_iconrow_doit(uiBlock *block, icon_border); } - if (tselem->flag & TSE_HIGHLIGHTED) { + if (tselem->flag & TSE_HIGHLIGHTED_ICON) { alpha_fac += 0.5; } tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, alpha_fac, false); @@ -3078,8 +3078,14 @@ static void outliner_draw_tree_element(bContext *C, /* datatype icon */ if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) { - tselem_draw_icon( - block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true); + tselem_draw_icon(block, + xmax, + (float)startx + offsx, + (float)*starty, + tselem, + te, + (tselem->flag & TSE_HIGHLIGHTED_ICON) ? alpha_fac + 0.5f : alpha_fac, + true); offsx += UI_UNIT_X + 4 * ufac; } else { diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index bf94e9e04a4..a1ff6193cd0 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -117,19 +117,27 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const TreeElement *hovered_te = outliner_find_item_at_y( space_outliner, &space_outliner->tree, view_mval[1]); - bool is_over_icon; + TreeElement *icon_te = NULL; + bool is_over_icon = false; if (hovered_te) { - hovered_te = outliner_find_item_at_x_in_row( + icon_te = outliner_find_item_at_x_in_row( space_outliner, hovered_te, view_mval[0], NULL, &is_over_icon); } + bool changed = false; - if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) { - changed = outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false); + if (!hovered_te || !is_over_icon || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED) || + !(icon_te->store_elem->flag & TSE_HIGHLIGHTED_ICON)) { + /* Clear highlights when nothing is hovered or when a new item is hovered. */ + changed = outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false); if (hovered_te) { hovered_te->store_elem->flag |= TSE_HIGHLIGHTED; changed = true; } + if (is_over_icon) { + icon_te->store_elem->flag |= TSE_HIGHLIGHTED_ICON; + changed = true; + } } if (changed) { diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index aefba929c5e..0294b4836c8 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -47,10 +47,13 @@ struct wmKeyConfig; struct wmOperatorType; typedef struct SpaceOutliner_Runtime { - /** - * Internal C++ object to create and manage the tree for a specific display type (View Layers, - * Scenes, Blender File, etc.). */ + /** Internal C++ object to create and manage the tree for a specific display type (View Layers, + * Scenes, Blender File, etc.). */ struct TreeDisplay *tree_display; + + /** Pointers to tree-store elements, grouped by `(id, type, nr)` + * in hash-table for faster searching. */ + struct GHash *treehash; } SpaceOutliner_Runtime; typedef enum TreeElementInsertType { @@ -72,6 +75,14 @@ typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *c typedef struct TreeElement { struct TreeElement *next, *prev, *parent; + + /** + * Handle to the new C++ object (a derived type of base #AbstractTreeElement) that should replace + * #TreeElement. Step by step, data should be moved to it and operations based on the type should + * become virtual methods of the class hierarchy. + */ + struct TreeElementType *type; + ListBase subtree; int xs, ys; /* Do selection. */ TreeStoreElem *store_elem; /* Element in tree store. */ diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 159511546be..7308b161d18 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -80,12 +80,11 @@ #include "RNA_access.h" -#include "SEQ_sequencer.h" - #include "UI_interface.h" #include "outliner_intern.h" #include "tree/tree_display.h" +#include "tree/tree_element.h" #ifdef WIN32 # include "BLI_math_base.h" /* M_PI */ @@ -132,9 +131,9 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) if (BLI_mempool_len(ts) == unused) { BLI_mempool_destroy(ts); space_outliner->treestore = NULL; - if (space_outliner->treehash) { - BKE_outliner_treehash_free(space_outliner->treehash); - space_outliner->treehash = NULL; + if (space_outliner->runtime->treehash) { + BKE_outliner_treehash_free(space_outliner->runtime->treehash); + space_outliner->runtime->treehash = NULL; } } else { @@ -150,16 +149,16 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) } BLI_mempool_destroy(ts); space_outliner->treestore = new_ts; - if (space_outliner->treehash) { + if (space_outliner->runtime->treehash) { /* update hash table to fix broken pointers */ - BKE_outliner_treehash_rebuild_from_treestore(space_outliner->treehash, + BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash, space_outliner->treestore); } } } } - else if (space_outliner->treehash) { - BKE_outliner_treehash_clear_used(space_outliner->treehash); + else if (space_outliner->runtime->treehash) { + BKE_outliner_treehash_clear_used(space_outliner->runtime->treehash); } } } @@ -174,14 +173,14 @@ static void check_persistent( space_outliner->treestore = BLI_mempool_create( sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER); } - if (space_outliner->treehash == NULL) { - space_outliner->treehash = BKE_outliner_treehash_create_from_treestore( + if (space_outliner->runtime->treehash == NULL) { + space_outliner->runtime->treehash = BKE_outliner_treehash_create_from_treestore( space_outliner->treestore); } /* find any unused tree element in treestore and mark it as used * (note that there may be multiple unused elements in case of linked objects) */ - tselem = BKE_outliner_treehash_lookup_unused(space_outliner->treehash, type, nr, id); + tselem = BKE_outliner_treehash_lookup_unused(space_outliner->runtime->treehash, type, nr, id); if (tselem) { te->store_elem = tselem; tselem->used = 1; @@ -196,7 +195,7 @@ static void check_persistent( tselem->used = 0; tselem->flag = TSE_CLOSED; te->store_elem = tselem; - BKE_outliner_treehash_add_element(space_outliner->treehash, tselem); + BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem); } /* ********************************************************* */ @@ -232,6 +231,7 @@ void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree) if (element->flag & TE_FREE_NAME) { MEM_freeN((void *)element->name); } + outliner_tree_element_type_free(&element->type); MEM_freeN(element); } @@ -961,13 +961,18 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->parent = parent; te->index = index; /* For data arrays. */ + + /* New C++ based type handle (`TreeElementType` in C, `AbstractTreeElement` in C++). Only some + * support this, eventually this should replace `TreeElement` entirely. */ + te->type = outliner_tree_element_type_create(type, te, idv); + if (ELEM(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) { /* pass */ } else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { /* pass */ } - else if (type == TSE_ANIM_DATA) { + else if (ELEM(type, TSE_ANIM_DATA, TSE_NLA, TSE_NLA_TRACK, TSE_DRIVER_BASE)) { /* pass */ } else if (type == TSE_GP_LAYER) { @@ -979,7 +984,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, else if (type == TSE_ID_BASE) { /* pass */ } + else if (ELEM(type, TSE_KEYMAP, TSE_KEYMAP_ITEM)) { + /* pass */ + } else { + /* Other cases must be caught above. */ + BLI_assert(TSE_IS_REAL_ID(tselem)); + /* do here too, for blend file viewer, own ID_LI then shows file name */ if (GS(id->name) == ID_LI) { te->name = ((Library *)id)->filepath; @@ -990,7 +1001,10 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->idcode = GS(id->name); } - if (type == 0) { + if (te->type) { + outliner_tree_element_type_expand(te->type, space_outliner); + } + else if (type == 0) { TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL; /* ID data-block. */ @@ -998,73 +1012,9 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, outliner_add_id_contents(space_outliner, te, tselem, id); } } - else if (type == TSE_ANIM_DATA) { - IdAdtTemplate *iat = (IdAdtTemplate *)idv; - AnimData *adt = (AnimData *)iat->adt; - - /* this element's info */ - te->name = IFACE_("Animation"); - te->directdata = adt; - - /* Action */ - outliner_add_element(space_outliner, &te->subtree, adt->action, te, 0, 0); - - /* Drivers */ - if (adt->drivers.first) { - TreeElement *ted = outliner_add_element( - space_outliner, &te->subtree, adt, te, TSE_DRIVER_BASE, 0); - ID *lastadded = NULL; - FCurve *fcu; - - ted->name = IFACE_("Drivers"); - - for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { - if (fcu->driver && fcu->driver->variables.first) { - ChannelDriver *driver = fcu->driver; - DriverVar *dvar; - - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - /* loop over all targets used here */ - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - if (lastadded != dtar->id) { - /* XXX this lastadded check is rather lame, and also fails quite badly... */ - outliner_add_element( - space_outliner, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0); - lastadded = dtar->id; - } - } - DRIVER_TARGETS_LOOPER_END; - } - } - } - } - - /* NLA Data */ - if (adt->nla_tracks.first) { - TreeElement *tenla = outliner_add_element(space_outliner, &te->subtree, adt, te, TSE_NLA, 0); - NlaTrack *nlt; - int a = 0; - - tenla->name = IFACE_("NLA Tracks"); - - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { - TreeElement *tenlt = outliner_add_element( - space_outliner, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a); - NlaStrip *strip; - TreeElement *ten; - int b = 0; - - tenlt->name = nlt->name; - - for (strip = nlt->strips.first; strip; strip = strip->next, b++) { - ten = outliner_add_element( - space_outliner, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b); - if (ten) { - ten->directdata = strip; - } - } - } - } + else if (ELEM(type, TSE_ANIM_DATA, TSE_DRIVER_BASE, TSE_NLA, TSE_NLA_ACTION, TSE_NLA_TRACK)) { + /* Should already use new AbstractTreeElement design. */ + BLI_assert(0); } else if (type == TSE_GP_LAYER) { bGPDlayer *gpl = (bGPDlayer *)idv; @@ -1314,125 +1264,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } /* ======================================================= */ -/* Sequencer mode tree building */ - -/* Helped function to put duplicate sequence in the same tree. */ -static int need_add_seq_dup(Sequence *seq) -{ - Sequence *p; - - if ((!seq->strip) || (!seq->strip->stripdata)) { - return 1; - } - - /* - * First check backward, if we found a duplicate - * sequence before this, don't need it, just return. - */ - p = seq->prev; - while (p) { - if ((!p->strip) || (!p->strip->stripdata)) { - p = p->prev; - continue; - } - - if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { - return 2; - } - p = p->prev; - } - - p = seq->next; - while (p) { - if ((!p->strip) || (!p->strip->stripdata)) { - p = p->next; - continue; - } - - if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { - return 0; - } - p = p->next; - } - return 1; -} - -static void outliner_add_seq_dup(SpaceOutliner *space_outliner, - Sequence *seq, - TreeElement *te, - short index) -{ - /* TreeElement *ch; */ /* UNUSED */ - Sequence *p; - - p = seq; - while (p) { - if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) { - p = p->next; - continue; - } - - if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { - /* ch = */ /* UNUSED */ outliner_add_element( - space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); - } - p = p->next; - } -} - -/* ----------------------------------------------- */ - -static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOutliner *space_outliner) -{ - TreeElement *ten; - ListBase *lbarray[MAX_LIBARRAY]; - int a, tot; - short filter_id_type = (space_outliner->filter & SO_FILTER_ID_TYPE) ? - space_outliner->filter_id_type : - 0; - - if (filter_id_type) { - lbarray[0] = which_libbase(mainvar, space_outliner->filter_id_type); - tot = 1; - } - else { - tot = set_listbasepointers(mainvar, lbarray); - } - - for (a = 0; a < tot; a++) { - if (lbarray[a] && lbarray[a]->first) { - ID *id = lbarray[a]->first; - - /* check if there are any data-blocks of this type which are orphans */ - for (; id; id = id->next) { - if (ID_REAL_USERS(id) <= 0) { - break; - } - } - - if (id) { - /* header for this type of data-block */ - if (filter_id_type) { - ten = NULL; - } - else { - ten = outliner_add_element( - space_outliner, &space_outliner->tree, lbarray[a], NULL, TSE_ID_BASE, 0); - ten->directdata = lbarray[a]; - ten->name = outliner_idcode_to_plural(GS(id->name)); - } - - /* add the orphaned data-blocks - these will not be added with any subtrees attached */ - for (id = lbarray[a]->first; id; id = id->next) { - if (ID_REAL_USERS(id) <= 0) { - outliner_add_element( - space_outliner, (ten) ? &ten->subtree : &space_outliner->tree, id, ten, 0, 0); - } - } - } - } - } -} BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection) { @@ -2175,18 +2006,12 @@ static void outliner_filter_tree(SpaceOutliner *space_outliner, ViewLayer *view_ /* Main Tree Building API */ /* Main entry point for building the tree data-structure that the outliner represents. */ -/* TODO: split each mode into its own function? */ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, SpaceOutliner *space_outliner, ARegion *region) { - TreeElement *te = NULL, *ten; - TreeStoreElem *tselem; - /* on first view, we open scenes */ - int show_opened = !space_outliner->treestore || !BLI_mempool_len(space_outliner->treestore); - /* Are we looking for something - we want to tag parents to filter child matches * - NOT in data-blocks view - searching all data-blocks takes way too long to be useful * - this variable is only set once per tree build */ @@ -2197,12 +2022,12 @@ void outliner_build_tree(Main *mainvar, space_outliner->search_flags &= ~SO_SEARCH_RECURSIVE; } - if (space_outliner->treehash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) && + if (space_outliner->runtime->treehash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) && space_outliner->treestore) { - space_outliner->storeflag &= ~SO_TREESTORE_REBUILD; - BKE_outliner_treehash_rebuild_from_treestore(space_outliner->treehash, + BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash, space_outliner->treestore); } + space_outliner->storeflag &= ~SO_TREESTORE_REBUILD; if (region->do_draw & RGN_DRAW_NO_REBUILD) { return; @@ -2217,82 +2042,13 @@ void outliner_build_tree(Main *mainvar, space_outliner->runtime->tree_display = outliner_tree_display_create(space_outliner->outlinevis, space_outliner); - if (space_outliner->runtime->tree_display) { - TreeSourceData source_data = {.bmain = mainvar, .scene = scene, .view_layer = view_layer}; - space_outliner->tree = outliner_tree_display_build_tree(space_outliner->runtime->tree_display, - &source_data); - } - if (space_outliner->runtime->tree_display) { - /* Skip if there's a tree-display that's responsible for adding all elements. */ - } - /* options */ - else if (space_outliner->outlinevis == SO_LIBRARIES) { - /* Ported to new tree-display, should be built there already. */ - BLI_assert(false); - } - else if (space_outliner->outlinevis == SO_SCENES) { - Scene *sce; - for (sce = mainvar->scenes.first; sce; sce = sce->id.next) { - te = outliner_add_element(space_outliner, &space_outliner->tree, sce, NULL, 0, 0); - tselem = TREESTORE(te); - - /* New scene elements open by default */ - if ((sce == scene && show_opened) || !tselem->used) { - tselem->flag &= ~TSE_CLOSED; - } - - outliner_make_object_parent_hierarchy(&te->subtree); - } - } - else if (space_outliner->outlinevis == SO_SEQUENCE) { - Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); - int op; - - if (ed == NULL) { - return; - } - - seq = ed->seqbasep->first; - if (!seq) { - return; - } - - while (seq) { - op = need_add_seq_dup(seq); - if (op == 1) { - /* ten = */ outliner_add_element( - space_outliner, &space_outliner->tree, (void *)seq, NULL, TSE_SEQUENCE, 0); - } - else if (op == 0) { - ten = outliner_add_element( - space_outliner, &space_outliner->tree, (void *)seq, NULL, TSE_SEQUENCE_DUP, 0); - outliner_add_seq_dup(space_outliner, seq, ten, 0); - } - seq = seq->next; - } - } - else if (space_outliner->outlinevis == SO_DATA_API) { - PointerRNA mainptr; + /* All tree displays should be created as sub-classes of AbstractTreeDisplay. */ + BLI_assert(space_outliner->runtime->tree_display != NULL); - RNA_main_pointer_create(mainvar, &mainptr); - - ten = outliner_add_element( - space_outliner, &space_outliner->tree, (void *)&mainptr, NULL, TSE_RNA_STRUCT, -1); - - if (show_opened) { - tselem = TREESTORE(ten); - tselem->flag &= ~TSE_CLOSED; - } - } - else if (space_outliner->outlinevis == SO_ID_ORPHANS) { - outliner_add_orphaned_datablocks(mainvar, space_outliner); - } - else if (space_outliner->outlinevis == SO_VIEW_LAYER) { - /* Ported to new tree-display, should be built there already. */ - BLI_assert(false); - } + TreeSourceData source_data = {.bmain = mainvar, .scene = scene, .view_layer = view_layer}; + space_outliner->tree = outliner_tree_display_build_tree(space_outliner->runtime->tree_display, + &source_data); if ((space_outliner->flag & SO_SKIP_SORT_ALPHA) == 0) { outliner_sort(&space_outliner->tree); diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index 3328f3169c3..e0d63dfcf81 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -212,7 +212,8 @@ TreeElement *outliner_find_tse(SpaceOutliner *space_outliner, const TreeStoreEle } /* check if 'tse' is in treestore */ - tselem = BKE_outliner_treehash_lookup_any(space_outliner->treehash, tse->type, tse->nr, tse->id); + tselem = BKE_outliner_treehash_lookup_any( + space_outliner->runtime->treehash, tse->type, tse->nr, tse->id); if (tselem) { return outliner_find_tree_element(&space_outliner->tree, tselem); } @@ -509,7 +510,7 @@ Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2]) te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]); if (te) { TreeStoreElem *tselem = TREESTORE(te); - if (tselem->type == 0) { + if ((tselem->type == 0) && (te->idcode == ID_OB)) { Object *ob = (Object *)tselem->id; base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(view_layer, ob); } diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 5ec55eee7fb..3d675fdd9e4 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -349,12 +349,12 @@ static void outliner_free(SpaceLink *sl) if (space_outliner->treestore) { BLI_mempool_destroy(space_outliner->treestore); } - if (space_outliner->treehash) { - BKE_outliner_treehash_free(space_outliner->treehash); - } if (space_outliner->runtime) { outliner_tree_display_destroy(&space_outliner->runtime->tree_display); + if (space_outliner->runtime->treehash) { + BKE_outliner_treehash_free(space_outliner->runtime->treehash); + } MEM_freeN(space_outliner->runtime); } } @@ -377,13 +377,13 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl) BLI_listbase_clear(&space_outliner_new->tree); space_outliner_new->treestore = NULL; - space_outliner_new->treehash = NULL; space_outliner_new->sync_select_dirty = WM_OUTLINER_SYNC_SELECT_FROM_ALL; if (space_outliner->runtime) { space_outliner_new->runtime = MEM_dupallocN(space_outliner->runtime); space_outliner_new->runtime->tree_display = NULL; + space_outliner_new->runtime->treehash = NULL; } return (SpaceLink *)space_outliner_new; @@ -414,7 +414,10 @@ static void outliner_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_i changed = true; } } - if (space_outliner->treehash && changed) { + + /* Note that the Outliner may not be the active editor of the area, and hence not initialized. + * So runtime data might not have been created yet. */ + if (space_outliner->runtime && space_outliner->runtime->treehash && changed) { /* rebuild hash table, because it depends on ids too */ /* postpone a full rebuild because this can be called many times on-free */ space_outliner->storeflag |= SO_TREESTORE_REBUILD; @@ -426,7 +429,7 @@ static void outliner_deactivate(struct ScrArea *area) { /* Remove hover highlights */ SpaceOutliner *space_outliner = area->spacedata.first; - outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED, false); + outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED_ANY, false); ED_region_tag_redraw_no_rebuild(BKE_area_find_region_type(area, RGN_TYPE_WINDOW)); } diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index 12599733275..d2070fb9b1c 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -32,13 +32,19 @@ TreeDisplay *outliner_tree_display_create(eSpaceOutliner_Mode mode, SpaceOutline switch (mode) { case SO_SCENES: + tree_display = new TreeDisplayScenes(*space_outliner); break; case SO_LIBRARIES: tree_display = new TreeDisplayLibraries(*space_outliner); break; case SO_SEQUENCE: + tree_display = new TreeDisplaySequencer(*space_outliner); + break; case SO_DATA_API: + tree_display = new TreeDisplayDataAPI(*space_outliner); + break; case SO_ID_ORPHANS: + tree_display = new TreeDisplayIDOrphans(*space_outliner); break; case SO_VIEW_LAYER: tree_display = new TreeDisplayViewLayer(*space_outliner); diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index a3d9a626d1d..b6183050e82 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -110,4 +110,70 @@ class TreeDisplayLibraries final : public AbstractTreeDisplay { short id_filter_get() const; }; +/* -------------------------------------------------------------------- */ +/* Video Sequencer Tree-Display */ + +enum SequenceAddOp { + SEQUENCE_DUPLICATE_NOOP = 0, + SEQUENCE_DUPLICATE_ADD, + SEQUENCE_DUPLICATE_NONE +}; + +/** + * \brief Tree-Display for the Video Sequencer display mode + */ +class TreeDisplaySequencer final : public AbstractTreeDisplay { + public: + TreeDisplaySequencer(SpaceOutliner &space_outliner); + + ListBase buildTree(const TreeSourceData &source_data) override; + + private: + TreeElement *add_sequencer_contents() const; + SequenceAddOp need_add_seq_dup(Sequence *seq) const; + void add_seq_dup(Sequence *seq, TreeElement *te, short index) const; +}; + +/* -------------------------------------------------------------------- */ +/* Orphaned Data Tree-Display */ + +/** + * \brief Tree-Display for the Orphaned Data display mode + */ +class TreeDisplayIDOrphans final : public AbstractTreeDisplay { + public: + TreeDisplayIDOrphans(SpaceOutliner &space_outliner); + + ListBase buildTree(const TreeSourceData &source_data) override; + + private: + bool datablock_has_orphans(ListBase &) const; +}; + +/* -------------------------------------------------------------------- */ +/* Scenes Tree-Display */ + +/** + * \brief Tree-Display for the Scenes display mode + */ +class TreeDisplayScenes final : public AbstractTreeDisplay { + public: + TreeDisplayScenes(SpaceOutliner &space_outliner); + + ListBase buildTree(const TreeSourceData &source_data) override; +}; + +/* -------------------------------------------------------------------- */ +/* Data API Tree-Display */ + +/** + * \brief Tree-Display for the Scenes display mode + */ +class TreeDisplayDataAPI final : public AbstractTreeDisplay { + public: + TreeDisplayDataAPI(SpaceOutliner &space_outliner); + + ListBase buildTree(const TreeSourceData &source_data) override; +}; + } // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_data.cc b/source/blender/editors/space_outliner/tree/tree_display_data.cc new file mode 100644 index 00000000000..8a5c2e7d9f3 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_display_data.cc @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "BLI_listbase.h" +#include "BLI_mempool.h" + +#include "RNA_access.h" + +#include "../outliner_intern.h" +#include "tree_display.hh" + +namespace blender::ed::outliner { + +TreeDisplayDataAPI::TreeDisplayDataAPI(SpaceOutliner &space_outliner) + : AbstractTreeDisplay(space_outliner) +{ +} + +ListBase TreeDisplayDataAPI::buildTree(const TreeSourceData &source_data) +{ + ListBase tree = {nullptr}; + + PointerRNA mainptr; + RNA_main_pointer_create(source_data.bmain, &mainptr); + + TreeElement *te = outliner_add_element( + &space_outliner_, &tree, (void *)&mainptr, nullptr, TSE_RNA_STRUCT, -1); + + /* On first view open parent data elements */ + const int show_opened = !space_outliner_.treestore || + !BLI_mempool_len(space_outliner_.treestore); + if (show_opened) { + TreeStoreElem *tselem = TREESTORE(te); + tselem->flag &= ~TSE_CLOSED; + } + return tree; +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc new file mode 100644 index 00000000000..0b17ea98831 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_display_orphaned.cc @@ -0,0 +1,97 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "DNA_ID.h" + +#include "BLI_listbase.h" +#include "BLI_listbase_wrapper.hh" +#include "BLI_utildefines.h" + +#include "BKE_main.h" + +#include "../outliner_intern.h" +#include "tree_display.hh" + +namespace blender::ed::outliner { + +/* Convenience/readability. */ +template<typename T> using List = ListBaseWrapper<T>; + +TreeDisplayIDOrphans::TreeDisplayIDOrphans(SpaceOutliner &space_outliner) + : AbstractTreeDisplay(space_outliner) +{ +} + +ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data) +{ + ListBase tree = {nullptr}; + ListBase *lbarray[MAX_LIBARRAY]; + short filter_id_type = (space_outliner_.filter & SO_FILTER_ID_TYPE) ? + space_outliner_.filter_id_type : + 0; + + int tot; + if (filter_id_type) { + lbarray[0] = which_libbase(source_data.bmain, filter_id_type); + tot = 1; + } + else { + tot = set_listbasepointers(source_data.bmain, lbarray); + } + + for (int a = 0; a < tot; a++) { + if (BLI_listbase_is_empty(lbarray[a])) { + continue; + } + if (!datablock_has_orphans(*lbarray[a])) { + continue; + } + + /* Header for this type of data-block. */ + TreeElement *te = nullptr; + if (!filter_id_type) { + ID *id = (ID *)lbarray[a]->first; + te = outliner_add_element(&space_outliner_, &tree, lbarray[a], nullptr, TSE_ID_BASE, 0); + te->directdata = lbarray[a]; + te->name = outliner_idcode_to_plural(GS(id->name)); + } + + /* Add the orphaned data-blocks - these will not be added with any subtrees attached. */ + for (ID *id : List<ID>(lbarray[a])) { + if (ID_REAL_USERS(id) <= 0) { + outliner_add_element(&space_outliner_, (te) ? &te->subtree : &tree, id, te, 0, 0); + } + } + } + + return tree; +} + +bool TreeDisplayIDOrphans::datablock_has_orphans(ListBase &lb) const +{ + for (ID *id : List<ID>(lb)) { + if (ID_REAL_USERS(id) <= 0) { + return true; + } + } + return false; +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_scenes.cc b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc new file mode 100644 index 00000000000..f377512d81e --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_display_scenes.cc @@ -0,0 +1,63 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "BLI_listbase.h" +#include "BLI_listbase_wrapper.hh" +#include "BLI_mempool.h" + +#include "BKE_main.h" + +#include "../outliner_intern.h" +#include "tree_display.hh" + +namespace blender::ed::outliner { + +/* Convenience/readability. */ +template<typename T> using List = ListBaseWrapper<T>; + +TreeDisplayScenes::TreeDisplayScenes(SpaceOutliner &space_outliner) + : AbstractTreeDisplay(space_outliner) +{ +} + +ListBase TreeDisplayScenes::buildTree(const TreeSourceData &source_data) +{ + /* On first view we open scenes. */ + const int show_opened = !space_outliner_.treestore || + !BLI_mempool_len(space_outliner_.treestore); + ListBase tree = {nullptr}; + + for (ID *id : List<ID>(source_data.bmain->scenes)) { + Scene *scene = reinterpret_cast<Scene *>(id); + TreeElement *te = outliner_add_element(&space_outliner_, &tree, scene, nullptr, 0, 0); + TreeStoreElem *tselem = TREESTORE(te); + + /* New scene elements open by default */ + if ((scene == source_data.scene && show_opened) || !tselem->used) { + tselem->flag &= ~TSE_CLOSED; + } + + outliner_make_object_parent_hierarchy(&te->subtree); + } + + return tree; +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc new file mode 100644 index 00000000000..48f0322ccb9 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_display_sequencer.cc @@ -0,0 +1,122 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include <cstring> + +#include "BLI_listbase.h" +#include "BLI_listbase_wrapper.hh" +#include "BLI_utildefines.h" + +#include "SEQ_sequencer.h" + +#include "../outliner_intern.h" +#include "tree_display.hh" + +namespace blender::ed::outliner { + +/* Convenience/readability. */ +template<typename T> using List = ListBaseWrapper<T>; + +TreeDisplaySequencer::TreeDisplaySequencer(SpaceOutliner &space_outliner) + : AbstractTreeDisplay(space_outliner) +{ +} + +ListBase TreeDisplaySequencer::buildTree(const TreeSourceData &source_data) +{ + ListBase tree = {nullptr}; + + Editing *ed = BKE_sequencer_editing_get(source_data.scene, false); + if (ed == nullptr) { + return tree; + } + + for (Sequence *seq : List<Sequence>(ed->seqbasep)) { + SequenceAddOp op = need_add_seq_dup(seq); + if (op == SEQUENCE_DUPLICATE_NONE) { + outliner_add_element(&space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE, 0); + } + else if (op == SEQUENCE_DUPLICATE_ADD) { + TreeElement *te = outliner_add_element( + &space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE_DUP, 0); + add_seq_dup(seq, te, 0); + } + } + + return tree; +} + +/* Helped function to put duplicate sequence in the same tree. */ +SequenceAddOp TreeDisplaySequencer::need_add_seq_dup(Sequence *seq) const +{ + if ((!seq->strip) || (!seq->strip->stripdata)) { + return SEQUENCE_DUPLICATE_NONE; + } + + /* + * First check backward, if we found a duplicate + * sequence before this, don't need it, just return. + */ + Sequence *p = seq->prev; + while (p) { + if ((!p->strip) || (!p->strip->stripdata)) { + p = p->prev; + continue; + } + + if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { + return SEQUENCE_DUPLICATE_NOOP; + } + p = p->prev; + } + + p = seq->next; + while (p) { + if ((!p->strip) || (!p->strip->stripdata)) { + p = p->next; + continue; + } + + if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { + return SEQUENCE_DUPLICATE_ADD; + } + p = p->next; + } + + return SEQUENCE_DUPLICATE_NONE; +} + +void TreeDisplaySequencer::add_seq_dup(Sequence *seq, TreeElement *te, short index) const +{ + Sequence *p = seq; + while (p) { + if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) { + p = p->next; + continue; + } + + if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { + outliner_add_element(&space_outliner_, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); + } + p = p->next; + } +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc new file mode 100644 index 00000000000..ce2a8fa634d --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element.cc @@ -0,0 +1,88 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "DNA_listBase.h" + +#include "../outliner_intern.h" + +#include "tree_element_anim_data.hh" +#include "tree_element_driver_base.hh" +#include "tree_element_nla.hh" + +#include "tree_element.h" +#include "tree_element.hh" + +namespace blender::ed::outliner { + +static AbstractTreeElement *tree_element_create(int type, TreeElement &legacy_te, void *idv) +{ + /* Would be nice to get rid of void * here, can we somehow expect the right type right away? + * Perfect forwarding maybe, once the API is C++ only? */ + ID &id = *static_cast<ID *>(idv); + + switch (type) { + case TSE_ANIM_DATA: + return new TreeElementAnimData(legacy_te, id); + case TSE_DRIVER_BASE: + return new TreeElementDriverBase(legacy_te, *static_cast<AnimData *>(idv)); + case TSE_NLA: + return new TreeElementNLA(legacy_te, *static_cast<AnimData *>(idv)); + case TSE_NLA_TRACK: + return new TreeElementNLATrack(legacy_te, *static_cast<NlaTrack *>(idv)); + case TSE_NLA_ACTION: + return new TreeElementNLAAction(legacy_te); + default: + break; + } + + return nullptr; +} + +static void tree_element_free(AbstractTreeElement **tree_element) +{ + delete *tree_element; + *tree_element = nullptr; +} + +static void tree_element_expand(AbstractTreeElement &tree_element, SpaceOutliner &space_outliner) +{ + tree_element.expand(space_outliner); +} + +} // namespace blender::ed::outliner + +namespace outliner = blender::ed::outliner; + +TreeElementType *outliner_tree_element_type_create(int type, TreeElement *legacy_te, void *idv) +{ + outliner::AbstractTreeElement *element = outliner::tree_element_create(type, *legacy_te, idv); + return reinterpret_cast<TreeElementType *>(element); +} + +void outliner_tree_element_type_expand(TreeElementType *type, SpaceOutliner *space_outliner) +{ + outliner::tree_element_expand(reinterpret_cast<outliner::AbstractTreeElement &>(*type), + *space_outliner); +} + +void outliner_tree_element_type_free(TreeElementType **type) +{ + outliner::tree_element_free(reinterpret_cast<outliner::AbstractTreeElement **>(type)); +} diff --git a/source/blender/editors/space_outliner/tree/tree_element.h b/source/blender/editors/space_outliner/tree/tree_element.h new file mode 100644 index 00000000000..d88c37180b3 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element.h @@ -0,0 +1,45 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + * + * C-API for the Tree-Element types. + * This API shouldn't stay for long. All tree building should eventually be done through C++ types, + * with more type safety and an easier to reason about design. + */ + +#pragma once + +#include "DNA_space_types.h" + +struct TreeElement; + +#ifdef __cplusplus +extern "C" { +#endif + +/** C alias for an #AbstractTreeElement handle. */ +typedef struct TreeElementType TreeElementType; + +TreeElementType *outliner_tree_element_type_create(int type, TreeElement *legacy_te, void *idv); +void outliner_tree_element_type_free(TreeElementType **type); + +void outliner_tree_element_type_expand(TreeElementType *type, SpaceOutliner *space_outliner); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/editors/space_outliner/tree/tree_element.hh b/source/blender/editors/space_outliner/tree/tree_element.hh new file mode 100644 index 00000000000..8a1ebb51eae --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element.hh @@ -0,0 +1,53 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#pragma once + +#include "tree_element.h" + +namespace blender::ed::outliner { + +/* -------------------------------------------------------------------- */ +/* Tree-Display Interface */ + +class AbstractTreeElement { + protected: + /** + * Reference back to the owning legacy TreeElement. + * Most concrete types need access to this, so storing here. Eventually the type should be + * replaced by AbstractTreeElement and derived types. + */ + TreeElement &legacy_te_; + + public: + AbstractTreeElement(TreeElement &legacy_te) : legacy_te_(legacy_te) + { + } + virtual ~AbstractTreeElement() = default; + + /** + * Let the type add its own children. + */ + virtual void expand(SpaceOutliner &) const + { + } +}; + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_anim_data.cc b/source/blender/editors/space_outliner/tree/tree_element_anim_data.cc new file mode 100644 index 00000000000..13a25800800 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_anim_data.cc @@ -0,0 +1,70 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "BLI_listbase_wrapper.hh" + +#include "DNA_anim_types.h" +#include "DNA_listBase.h" + +#include "BLT_translation.h" + +#include "../outliner_intern.h" +#include "tree_display.h" + +#include "tree_element_anim_data.hh" + +namespace blender::ed::outliner { + +TreeElementAnimData::TreeElementAnimData(TreeElement &legacy_te, ID &id) + : AbstractTreeElement(legacy_te), anim_data_(*reinterpret_cast<IdAdtTemplate &>(id).adt) +{ + BLI_assert(legacy_te.store_elem->type == TSE_ANIM_DATA); + /* this element's info */ + legacy_te.name = IFACE_("Animation"); + legacy_te.directdata = &anim_data_; +} + +void TreeElementAnimData::expand(SpaceOutliner &space_outliner) const +{ + /* Animation data-block itself. */ + outliner_add_element(&space_outliner, &legacy_te_.subtree, anim_data_.action, &legacy_te_, 0, 0); + + expand_drivers(space_outliner); + expand_NLA_tracks(space_outliner); +} + +void TreeElementAnimData::expand_drivers(SpaceOutliner &space_outliner) const +{ + if (BLI_listbase_is_empty(&anim_data_.drivers)) { + return; + } + outliner_add_element( + &space_outliner, &legacy_te_.subtree, &anim_data_, &legacy_te_, TSE_DRIVER_BASE, 0); +} + +void TreeElementAnimData::expand_NLA_tracks(SpaceOutliner &space_outliner) const +{ + if (BLI_listbase_is_empty(&anim_data_.nla_tracks)) { + return; + } + outliner_add_element(&space_outliner, &legacy_te_.subtree, &anim_data_, &legacy_te_, TSE_NLA, 0); +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_anim_data.hh b/source/blender/editors/space_outliner/tree/tree_element_anim_data.hh new file mode 100644 index 00000000000..8114277b6d6 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_anim_data.hh @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#pragma once + +#include "tree_element.hh" + +struct TreeElement; + +namespace blender::ed::outliner { + +class TreeElementAnimData final : public AbstractTreeElement { + AnimData &anim_data_; + + public: + TreeElementAnimData(TreeElement &legacy_te, ID &id); + + void expand(SpaceOutliner &space_outliner) const override; + + private: + void expand_drivers(SpaceOutliner &space_outliner) const; + void expand_NLA_tracks(SpaceOutliner &space_outliner) const; +}; + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_driver_base.cc b/source/blender/editors/space_outliner/tree/tree_element_driver_base.cc new file mode 100644 index 00000000000..a01a3c42531 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_driver_base.cc @@ -0,0 +1,68 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "BLI_listbase_wrapper.hh" + +#include "BKE_fcurve_driver.h" + +#include "DNA_anim_types.h" +#include "DNA_listBase.h" + +#include "BLT_translation.h" + +#include "../outliner_intern.h" +#include "tree_display.h" + +#include "tree_element_driver_base.hh" + +namespace blender::ed::outliner { + +TreeElementDriverBase::TreeElementDriverBase(TreeElement &legacy_te, AnimData &anim_data) + : AbstractTreeElement(legacy_te), anim_data_(anim_data) +{ + BLI_assert(legacy_te.store_elem->type == TSE_DRIVER_BASE); + legacy_te.name = IFACE_("Drivers"); +} + +void TreeElementDriverBase::expand(SpaceOutliner &space_outliner) const +{ + ID *lastadded = nullptr; + + for (FCurve *fcu : blender::ListBaseWrapper<FCurve>(anim_data_.drivers)) { + if (fcu->driver && fcu->driver->variables.first) { + ChannelDriver *driver = fcu->driver; + + for (DriverVar *dvar : blender::ListBaseWrapper<DriverVar>(driver->variables)) { + /* loop over all targets used here */ + DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { + if (lastadded != dtar->id) { + /* XXX this lastadded check is rather lame, and also fails quite badly... */ + outliner_add_element( + &space_outliner, &legacy_te_.subtree, dtar->id, &legacy_te_, TSE_LINKED_OB, 0); + lastadded = dtar->id; + } + } + DRIVER_TARGETS_LOOPER_END; + } + } + } +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_driver_base.hh b/source/blender/editors/space_outliner/tree/tree_element_driver_base.hh new file mode 100644 index 00000000000..1925e3570be --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_driver_base.hh @@ -0,0 +1,38 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#pragma once + +#include "tree_element.hh" + +struct TreeElement; + +namespace blender::ed::outliner { + +class TreeElementDriverBase final : public AbstractTreeElement { + AnimData &anim_data_; + + public: + TreeElementDriverBase(TreeElement &legacy_te, AnimData &anim_data); + + void expand(SpaceOutliner &space_outliner) const override; +}; + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_nla.cc b/source/blender/editors/space_outliner/tree/tree_element_nla.cc new file mode 100644 index 00000000000..5d4ec53e60c --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_nla.cc @@ -0,0 +1,78 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "BLI_listbase_wrapper.hh" + +#include "DNA_anim_types.h" +#include "DNA_listBase.h" + +#include "BLT_translation.h" + +#include "../outliner_intern.h" +#include "tree_display.h" + +#include "tree_element_nla.hh" + +namespace blender::ed::outliner { + +TreeElementNLA::TreeElementNLA(TreeElement &legacy_te, AnimData &anim_data) + : AbstractTreeElement(legacy_te), anim_data_(anim_data) +{ + BLI_assert(legacy_te.store_elem->type == TSE_NLA); + legacy_te.name = IFACE_("NLA Tracks"); + legacy_te.directdata = &anim_data; +} + +void TreeElementNLA::expand(SpaceOutliner &space_outliner) const +{ + int a = 0; + for (NlaTrack *nlt : ListBaseWrapper<NlaTrack>(anim_data_.nla_tracks)) { + outliner_add_element(&space_outliner, &legacy_te_.subtree, nlt, &legacy_te_, TSE_NLA_TRACK, a); + a++; + } +} + +/* -------------------------------------------------------------------- */ + +TreeElementNLATrack::TreeElementNLATrack(TreeElement &legacy_te, NlaTrack &track) + : AbstractTreeElement(legacy_te), track_(track) +{ + BLI_assert(legacy_te.store_elem->type == TSE_NLA_TRACK); + legacy_te.name = track.name; +} + +void TreeElementNLATrack::expand(SpaceOutliner &space_outliner) const +{ + int a = 0; + for (NlaStrip *strip : ListBaseWrapper<NlaStrip>(track_.strips)) { + outliner_add_element( + &space_outliner, &legacy_te_.subtree, strip->act, &legacy_te_, TSE_NLA_ACTION, a); + a++; + } +} + +/* -------------------------------------------------------------------- */ + +TreeElementNLAAction::TreeElementNLAAction(TreeElement &legacy_te) : AbstractTreeElement(legacy_te) +{ + BLI_assert(legacy_te.store_elem->type == TSE_NLA_ACTION); +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_nla.hh b/source/blender/editors/space_outliner/tree/tree_element_nla.hh new file mode 100644 index 00000000000..3ca62b13bd8 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_nla.hh @@ -0,0 +1,53 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#pragma once + +#include "tree_element.hh" + +struct NlaTrack; +struct NlaStrip; + +namespace blender::ed::outliner { + +class TreeElementNLA final : public AbstractTreeElement { + AnimData &anim_data_; + + public: + TreeElementNLA(TreeElement &legacy_te, AnimData &anim_data); + + void expand(SpaceOutliner &space_outliner) const override; +}; + +class TreeElementNLATrack final : public AbstractTreeElement { + NlaTrack &track_; + + public: + TreeElementNLATrack(TreeElement &legacy_te, NlaTrack &track); + + void expand(SpaceOutliner &space_outliner) const override; +}; + +class TreeElementNLAAction final : public AbstractTreeElement { + public: + TreeElementNLAAction(TreeElement &legacy_te); +}; + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 2c9ea1d6afa..849766851aa 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -886,7 +886,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *b scroll->ymin = pix_top_margin; scroll->ymax = pix_available; - /* when re-sizing a view-port with the bar at the bottom to a greater height + /* when re-sizing a 2D Viewport with the bar at the bottom to a greater height * more blank lines will be added */ if (ltexth + blank_lines < st->top + st->runtime.viewlines) { blank_lines = st->top + st->runtime.viewlines - ltexth; diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c index c583634f440..84b7a6f6831 100644 --- a/source/blender/editors/space_text/text_header.c +++ b/source/blender/editors/space_text/text_header.c @@ -108,101 +108,3 @@ void TEXT_OT_start_find(wmOperatorType *ot) ot->exec = text_text_search_exec; ot->poll = text_properties_poll; } - -/******************** XXX popup menus *******************/ - -#if 0 -{ - /* RMB */ - - uiPopupMenu *pup; - - if (text) { - pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE); - if (txt_has_sel(text)) { - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy"); - } - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script"); - UI_popup_menu_end(C, pup); - } - else { - pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - UI_popup_menu_end(C, pup); - } -} - -{ - /* Alt+Shift+E */ - - uiPopupMenu *pup; - - pup = UI_popup_menu_begin(C, IFACE_("Edit"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_cut"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_copy"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_paste"); - UI_popup_menu_end(C, pup); -} - -{ - /* Alt+Shift+F */ - - uiPopupMenu *pup; - - if (text) { - pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_save_as"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_run_script"); - UI_popup_menu_end(C, pup); - } - else { - pup = UI_popup_menu_begin(C, IFACE_("File"), ICON_NONE); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new"); - uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open"); - UI_popup_menu_end(C, pup); - } -} - -{ - /* Alt+Shift+V */ - - uiPopupMenu *pup; - - pup = UI_popup_menu_begin(C, IFACE_("Text"), ICON_NONE); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"), - 0, - "type", - FILE_TOP); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Bottom of File"), - 0, - "type", - FILE_BOTTOM); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Up"), - 0, - "type", - PREV_PAGE); - uiItemEnumO(layout, - "TEXT_OT_move", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Page Down"), - 0, - "type", - NEXT_PAGE); - UI_popup_menu_end(C, pup); -} -#endif diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 3b5dc3f57b9..797c7d73df3 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -848,7 +848,7 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bo /* get surface depth without bias */ rv3d->rflag |= RV3D_ZOFFSET_DISABLED; - /* Needed in cases the view-port isn't already setup. */ + /* Needed in cases the 3D Viewport isn't already setup. */ WM_draw_region_viewport_ensure(region, SPACE_VIEW3D); WM_draw_region_viewport_bind(region); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index f9de462813f..9429da342a6 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -222,7 +222,7 @@ typedef struct ViewOpsData { /** Current state. */ struct { /** Working copy of #RegionView3D.viewquat, needed for rotation calculation - * so we can apply snap to the view-port while keeping the unsnapped rotation + * so we can apply snap to the 3D Viewport while keeping the unsnapped rotation * here to use when snap is disabled and for continued calculation. */ float viewquat[4]; } curr; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index fdba74ed3a6..9b0ce27b1e3 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -315,8 +315,6 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph, const float eps_bias = 0.0002f; float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */ - WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, true); - if (ruler_item) { RulerInteraction *inter = ruler_item->gz.interaction_data; float *co = ruler_item->co[inter->co_index]; @@ -388,12 +386,8 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph, snap_gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point); } - short snap_elem = ED_gizmotypes_snap_3d_update( + ED_gizmotypes_snap_3d_update( snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl, co, NULL); - - if (snap_elem) { - WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, false); - } } return true; } @@ -1074,7 +1068,6 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel) if (!cancel) { if (ruler_info->state == RULER_STATE_DRAG) { - WM_gizmo_set_flag(ruler_info->snap_data.gizmo, WM_GIZMO_HIDDEN, false); RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint); ruler_state_set(ruler_info, RULER_STATE_NORMAL); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 0815850d694..118ec2425fc 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -171,7 +171,7 @@ bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb); /** - * Parameters for setting the new view-port state. + * Parameters for setting the new 3D Viewport state. * * Each of the struct members may be NULL to signify they aren't to be adjusted. */ diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index 6d10aa5f957..bd71a768c0f 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -72,7 +72,7 @@ static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw * In this case we can't usefully project the mouse cursor onto the plane, * so use a fall-back plane instead. */ -const float eps_view_align = 1e-2f; +static const float eps_view_align = 1e-2f; /* -------------------------------------------------------------------- */ /** \name Local Types @@ -1357,7 +1357,6 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve const float mval_fl[2] = {UNPACK2(event->mval)}; /* Calculate the snap location on mouse-move or when toggling snap. */ - bool is_snap_found_prev = ipd->is_snap_found; ipd->is_snap_found = false; if (ipd->use_snap) { if (ipd->snap_gizmo != NULL) { @@ -1366,7 +1365,7 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve CTX_data_ensure_evaluated_depsgraph(C), ipd->region, ipd->v3d, - NULL, + G_MAIN->wm.first, mval_fl, ipd->snap_co, NULL)) { @@ -1376,12 +1375,6 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve } } - /* Workaround because test_select doesn't run at the same time as the modal operator. */ - if (is_snap_found_prev != ipd->is_snap_found) { - wmGizmoMap *gzmap = ipd->region->gizmo_map; - WM_gizmo_highlight_set(gzmap, ipd->is_snap_found ? ipd->snap_gizmo : NULL); - } - if (ipd->step_index == STEP_BASE) { if (ipd->is_snap_found) { closest_to_plane_normalized_v3( diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index a70e74665c5..1be9bd27c7a 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -574,11 +574,11 @@ bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *re /* -------------------------------------------------------------------- */ /** \name Camera Lock API * - * Lock the camera to the view-port, allowing view manipulation to transform the camera. + * Lock the camera to the 3D Viewport, allowing view manipulation to transform the camera. * \{ */ /** - * \return true when the view-port is locked to its camera. + * \return true when the 3D Viewport is locked to its camera. */ bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d) { @@ -587,8 +587,8 @@ bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d) } /** - * Apply the camera object transformation to the view-port. - * (needed so we can use regular view-port manipulation operators, that sync back to the camera). + * Apply the camera object transformation to the 3D Viewport. + * (needed so we can use regular 3D Viewport manipulation operators, that sync back to the camera). */ void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, View3D *v3d, @@ -612,7 +612,7 @@ void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionV } /** - * Apply the view-port transformation back to the camera object. + * Apply the 3D Viewport transformation back to the camera object. * * \return true if the camera is moved. */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 356ad8643f8..2b56b30be90 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -599,7 +599,8 @@ static bool transform_modal_item_poll(const wmOperator *op, int value) case TFM_MODAL_AXIS_Z: case TFM_MODAL_PLANE_X: case TFM_MODAL_PLANE_Y: - case TFM_MODAL_PLANE_Z: { + case TFM_MODAL_PLANE_Z: + case TFM_MODAL_AUTOCONSTRAINTPLANE: { if (t->flag & T_NO_CONSTRAINT) { return false; } @@ -636,6 +637,14 @@ static bool transform_modal_item_poll(const wmOperator *op, int value) } break; } + case TFM_MODAL_TRANSLATE: + case TFM_MODAL_ROTATE: + case TFM_MODAL_RESIZE: { + if (!transform_mode_is_changeable(t->mode)) { + return false; + } + break; + } } return true; } @@ -713,55 +722,67 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) return keymap; } -static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is_plane) +static bool transform_event_modal_constraint(TransInfo *t, short modal_type) { if (!(t->flag & T_NO_CONSTRAINT)) { - char cmode = constraintModeToChar(t); - int constraint_axis, constraint_plane; - const bool edit_2d = (t->flag & T_2D_EDIT) != 0; - const char *msg1 = "", *msg2 = "", *msg3 = ""; - char axis; + if (t->flag & T_2D_EDIT && ELEM(modal_type, TFM_MODAL_AXIS_Z, TFM_MODAL_PLANE_Z)) { + return false; + } + int constraint_curr = (t->con.mode & CON_APPLY) ? + t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2) : + -1; + int constraint_new; + const char *msg_2d = "", *msg_3d = ""; /* Initialize */ - switch (key_type) { - case EVT_XKEY: - msg1 = TIP_("along X"); - msg2 = TIP_("along %s X"); - msg3 = TIP_("locking %s X"); - axis = 'X'; - constraint_axis = CON_AXIS0; + switch (modal_type) { + case TFM_MODAL_AXIS_X: + msg_2d = TIP_("along X"); + msg_3d = TIP_("along %s X"); + constraint_new = CON_AXIS0; + break; + case TFM_MODAL_AXIS_Y: + msg_2d = TIP_("along Y"); + msg_3d = TIP_("along %s Y"); + constraint_new = CON_AXIS1; + break; + case TFM_MODAL_AXIS_Z: + msg_2d = TIP_("along Z"); + msg_3d = TIP_("along %s Z"); + constraint_new = CON_AXIS2; break; - case EVT_YKEY: - msg1 = TIP_("along Y"); - msg2 = TIP_("along %s Y"); - msg3 = TIP_("locking %s Y"); - axis = 'Y'; - constraint_axis = CON_AXIS1; + case TFM_MODAL_PLANE_X: + msg_3d = TIP_("locking %s X"); + constraint_new = CON_AXIS1 | CON_AXIS2; break; - case EVT_ZKEY: - msg1 = TIP_("along Z"); - msg2 = TIP_("along %s Z"); - msg3 = TIP_("locking %s Z"); - axis = 'Z'; - constraint_axis = CON_AXIS2; + case TFM_MODAL_PLANE_Y: + msg_3d = TIP_("locking %s Y"); + constraint_new = CON_AXIS0 | CON_AXIS2; + break; + case TFM_MODAL_PLANE_Z: + msg_3d = TIP_("locking %s Z"); + constraint_new = CON_AXIS0 | CON_AXIS1; break; default: /* Invalid key */ - return; + return false; } - constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis)); - if (edit_2d && (key_type != EVT_ZKEY)) { - if (cmode == axis) { + if (t->flag & T_2D_EDIT) { + BLI_assert(modal_type < TFM_MODAL_PLANE_X); + if (constraint_new == CON_AXIS2) { + return false; + } + if (constraint_curr == constraint_new) { stopConstraint(t); } else { - setUserConstraint(t, constraint_axis, msg1); + setUserConstraint(t, constraint_new, msg_2d); } } - else if (!edit_2d) { + else { short orient_index = 1; - if (t->orient_curr == 0 || ELEM(cmode, '\0', axis)) { + if (t->orient_curr == 0 || ELEM(constraint_curr, -1, constraint_new)) { /* Successive presses on existing axis, cycle orientation modes. */ orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient)); } @@ -771,16 +792,13 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is stopConstraint(t); } else { - if (is_plane == false) { - setUserConstraint(t, constraint_axis, msg2); - } - else { - setUserConstraint(t, constraint_plane, msg3); - } + setUserConstraint(t, constraint_new, msg_3d); } } t->redraw |= TREDRAW_HARD; + return true; } + return false; } int transformEvent(TransInfo *t, const wmEvent *event) @@ -818,15 +836,9 @@ int transformEvent(TransInfo *t, const wmEvent *event) t->redraw |= handleSnapping(t, event); handled = true; } - else if (event->val == t->release_confirm_event_val && - event->type == t->release_confirm_event_type) { - /* Confirm transform if launch key is released after mouse move. */ - BLI_assert(t->flag & T_RELEASE_CONFIRM); - t->state = TRANS_CONFIRM; - } + /* handle modal keymap first */ + /* enforce redraw of transform when modifiers are used */ else if (event->type == EVT_MODAL_MAP) { - /* Handle modal keymap first. */ - /* Enforce redraw of transform when modifiers are used */ switch (event->val) { case TFM_MODAL_CANCEL: t->state = TRANS_CANCEL; @@ -872,11 +884,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } } - else if (t->mode == TFM_SEQ_SLIDE) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } else if (transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); @@ -918,11 +925,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } } - else if (t->mode == TFM_SHRINKFATTEN) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } else if (transform_mode_is_changeable(t->mode)) { /* Scale isn't normally very useful after extrude along normals, see T39756 */ if ((t->con.mode & CON_APPLY) && (t->orient[t->orient_curr].type == V3D_ORIENT_NORMAL)) { @@ -955,44 +957,12 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; break; case TFM_MODAL_AXIS_X: - if (!(t->flag & T_NO_CONSTRAINT)) { - transform_event_xyz_constraint(t, EVT_XKEY, false); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; case TFM_MODAL_AXIS_Y: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - transform_event_xyz_constraint(t, EVT_YKEY, false); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; case TFM_MODAL_AXIS_Z: - if ((t->flag & (T_NO_CONSTRAINT)) == 0) { - transform_event_xyz_constraint(t, EVT_ZKEY, false); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; case TFM_MODAL_PLANE_X: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_XKEY, true); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; case TFM_MODAL_PLANE_Y: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_YKEY, true); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; case TFM_MODAL_PLANE_Z: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_ZKEY, true); - t->redraw |= TREDRAW_HARD; + if (transform_event_modal_constraint(t, event->val)) { handled = true; } break; @@ -1088,7 +1058,12 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_AUTOCONSTRAINT: case TFM_MODAL_AUTOCONSTRAINTPLANE: - if ((t->flag & T_NO_CONSTRAINT) == 0) { + if ((t->flag & T_RELEASE_CONFIRM) && (event->prevval == KM_RELEASE) && + event->prevtype == t->launch_event) { + /* Confirm transform if launch key is released after mouse move. */ + t->state = TRANS_CONFIRM; + } + else if ((t->flag & T_NO_CONSTRAINT) == 0) { if (t->modifiers & (MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE)) { /* Confirm. */ postSelectConstraint(t); @@ -1128,8 +1103,8 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; } } + /* Else do non-mapped events. */ else if (event->val == KM_PRESS) { - /* Do non-mapped events. */ switch (event->type) { case EVT_CKEY: if (event->is_repeat) { @@ -1217,6 +1192,11 @@ int transformEvent(TransInfo *t, const wmEvent *event) } break; } + + /* confirm transform if launch key is released after mouse move */ + if ((t->flag & T_RELEASE_CONFIRM) && event->type == t->launch_event) { + t->state = TRANS_CONFIRM; + } } /* if we change snap options, get the unsnapped values back */ @@ -1688,6 +1668,17 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->mode = mode; + /* Needed to translate tweak events to mouse buttons. */ + t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1; + t->is_launch_event_tweak = event ? ISTWEAK(event->type) : false; + + /* XXX Remove this when wm_operator_call_internal doesn't use window->eventstate + * (which can have type = 0) */ + /* For gizmo only, so assume LEFTMOUSE. */ + if (t->launch_event == 0) { + t->launch_event = LEFTMOUSE; + } + unit_m3(t->spacemtx); initTransInfo(C, t, op, event); @@ -1761,6 +1752,37 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } } + if (event) { + /* keymap for shortcut header prints */ + t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); + + /* Stupid code to have Ctrl-Click on gizmo work ok. + * + * Do this only for translation/rotation/resize because only these + * modes are available from gizmo and doing such check could + * lead to keymap conflicts for other modes (see T31584) + */ + if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { + wmKeyMapItem *kmi; + + for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) { + if (kmi->flag & KMI_INACTIVE) { + continue; + } + + if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) { + if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) || + (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) || + (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && event->alt) || + ((kmi->type == EVT_OSKEY) && event->oskey)) { + t->modifiers |= MOD_SNAP_INVERT; + } + break; + } + } + } + } + initSnapping(t, op); /* Initialize snapping data AFTER mode flags */ initSnapSpatial(t, t->snap_spatial); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 485d5282a62..227330e8524 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -351,8 +351,7 @@ typedef struct TransInfo { /*************** NEW STUFF *********************/ /** event type used to launch transform. */ - short release_confirm_event_type; - short release_confirm_event_val; + short launch_event; /** Is the actual launch event a tweak event? (launch_event above is set to the corresponding * mouse button then.) */ bool is_launch_event_tweak; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 5e2a8be8db0..54533bf43e5 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -1127,16 +1127,6 @@ int constraintModeToIndex(const TransInfo *t) } } -char constraintModeToChar(const TransInfo *t) -{ - int index = constraintModeToIndex(t); - if (index == -1) { - return '\0'; - } - BLI_assert((uint)index < 3); - return 'X' + index; -} - bool isLockConstraint(TransInfo *t) { int mode = t->con.mode; diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index c23ee5b771c..c81c954bd0a 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1438,7 +1438,7 @@ void animrecord_check_state(TransInfo *t, struct Object *ob) /* only push down if action is more than 1-2 frames long */ calc_action_range(adt->action, &astart, &aend, 1); if (aend > astart + 2.0f) { - NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action); + NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action, ID_IS_OVERRIDE_LIBRARY(id)); /* clear reference to action now that we've pushed it onto the stack */ id_us_min(&adt->action->id); diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index a7301161570..e9b2273b343 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -164,21 +164,21 @@ static void autokeyframe_pose( /* only if bone name matches too... * NOTE: this will do constraints too, but those are ok to do here too? */ - if (pchanName && STREQ(pchanName, pchan->name)) { - insert_keyframe(bmain, - reports, - id, - act, - ((fcu->grp) ? (fcu->grp->name) : (NULL)), - fcu->rna_path, - fcu->array_index, - &anim_eval_context, - ts->keyframe_type, - &nla_cache, - flag); - } - if (pchanName) { + if (STREQ(pchanName, pchan->name)) { + insert_keyframe(bmain, + reports, + id, + act, + ((fcu->grp) ? (fcu->grp->name) : (NULL)), + fcu->rna_path, + fcu->array_index, + &anim_eval_context, + ts->keyframe_type, + &nla_cache, + flag); + } + MEM_freeN(pchanName); } } diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index 8f18f6a8c96..fa60a88a45b 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -462,6 +462,12 @@ void recalcData_nla(TransInfo *t) * - we need to calculate both, * as only one may have been altered by transform if only 1 handle moved. */ + /* In LibOverride case, we cannot move strips across tracks that come from the linked data. */ + const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(tdn->id); + if (BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) { + continue; + } + delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex); delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex); @@ -477,10 +483,11 @@ void recalcData_nla(TransInfo *t) if (delta > 0) { for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) { /* check if space in this track for the strip */ - if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + if (BKE_nlatrack_has_space(track, strip->start, strip->end) && + !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) { /* move strip to this track */ BLI_remlink(&tdn->nlt->strips, strip); - BKE_nlatrack_add_strip(track, strip); + BKE_nlatrack_add_strip(track, strip, is_liboverride); tdn->nlt = track; tdn->trackIndex++; @@ -496,10 +503,11 @@ void recalcData_nla(TransInfo *t) for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) { /* check if space in this track for the strip */ - if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { + if (BKE_nlatrack_has_space(track, strip->start, strip->end) && + !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) { /* move strip to this track */ BLI_remlink(&tdn->nlt->strips, strip); - BKE_nlatrack_add_strip(track, strip); + BKE_nlatrack_add_strip(track, strip, is_liboverride); tdn->nlt = track; tdn->trackIndex--; diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c index 38db8708d0c..58ff4db324e 100644 --- a/source/blender/editors/transform/transform_convert_node.c +++ b/source/blender/editors/transform/transform_convert_node.c @@ -25,6 +25,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_context.h" @@ -70,8 +71,6 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node, const td2d->loc[2] = 0.0f; td2d->loc2d = td2d->loc; /* current location */ - td->flag = 0; - td->loc = td2d->loc; copy_v3_v3(td->iloc, td->loc); /* use node center instead of origin (top-left corner) */ @@ -85,8 +84,8 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node, const td->ext = NULL; td->val = NULL; - td->flag |= TD_SELECTED; - td->dist = 0.0; + td->flag = TD_SELECTED; + td->dist = 0.0f; unit_m3(td->mtx); unit_m3(td->smtx); @@ -107,10 +106,7 @@ static bool is_node_parent_select(bNode *node) void createTransNodeData(TransInfo *t) { const float dpi_fac = UI_DPI_FAC; - TransData *td; - TransData2D *td2d; SpaceNode *snode = t->area->spacedata.first; - bNode *node; TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); @@ -124,7 +120,7 @@ void createTransNodeData(TransInfo *t) t->flag &= ~T_PROP_EDIT_ALL; /* set transform flags on nodes */ - for (node = snode->edittree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (node->flag & NODE_SELECT && is_node_parent_select(node) == false) { node->flag |= NODE_TRANSFORM; tc->data_len++; @@ -134,10 +130,11 @@ void createTransNodeData(TransInfo *t) } } - td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData"); - td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransNode TransData2D"); + TransData *td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData"); + TransData2D *td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), + "TransNode TransData2D"); - for (node = snode->edittree->nodes.first; node; node = node->next) { + LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) { if (node->flag & NODE_TRANSFORM) { NodeToTransData(td++, td2d++, node, dpi_fac); } @@ -156,24 +153,21 @@ void flushTransNodes(TransInfo *t) const float dpi_fac = UI_DPI_FAC; FOREACH_TRANS_DATA_CONTAINER (t, tc) { - int a; - TransData *td; - TransData2D *td2d; - applyGridAbsolute(t); /* flush to 2d vector from internally used 3d vector */ - for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) { + for (int i = 0; i < tc->data_len; i++) { + TransData *td = &tc->data[i]; + TransData2D *td2d = &tc->data_2d[i]; bNode *node = td->extra; - float locx, locy; /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */ #ifdef USE_NODE_CENTER - locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac; - locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac; + float locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac; + float locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac; #else - locx = td2d->loc[0] / dpi_fac; - locy = td2d->loc[1] / dpi_fac; + float locx = td2d->loc[0] / dpi_fac; + float locy = td2d->loc[1] / dpi_fac; #endif /* account for parents (nested nodes) */ @@ -209,9 +203,7 @@ void special_aftertrans_update__node(bContext *C, TransInfo *t) /* remove selected nodes on cancel */ bNodeTree *ntree = snode->edittree; if (ntree) { - bNode *node, *node_next; - for (node = ntree->nodes.first; node; node = node_next) { - node_next = node->next; + LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { if (node->flag & NODE_SELECT) { nodeRemoveNode(bmain, ntree, node, true); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 27346c9e974..5b41f6b51bf 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -593,60 +593,18 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve transform_orientations_current_set(t, (t->con.mode & CON_APPLY) ? 2 : 0); } - if (event) { - t->release_confirm_event_type = WM_userdef_event_type_from_keymap_type(event->type); - t->is_launch_event_tweak = ISTWEAK(event->type); - - /* XXX Remove this when wm_operator_call_internal doesn't use window->eventstate - * (which can have type = 0) */ - /* For gizmo only, so assume LEFTMOUSE. */ - if (t->release_confirm_event_type == 0) { - t->release_confirm_event_type = LEFTMOUSE; - } - } - else { - /* Needed to translate tweak events to mouse buttons. */ - t->release_confirm_event_type = -1; - } - - t->release_confirm_event_val = -2; - if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && RNA_property_is_set(op->ptr, prop))) { if (RNA_property_boolean_get(op->ptr, prop)) { t->flag |= T_RELEASE_CONFIRM; - t->release_confirm_event_val = KM_RELEASE; } } else { /* Release confirms preference should not affect node editor (T69288, T70504). */ - if (ISMOUSE(t->release_confirm_event_type) && + if (ISMOUSE(t->launch_event) && ((U.flag & USER_RELEASECONFIRM) || (t->spacetype == SPACE_NODE))) { /* Global "release confirm" on mouse bindings */ t->flag |= T_RELEASE_CONFIRM; - t->release_confirm_event_val = KM_RELEASE; - } - } - - if (op && event) { - /* Keymap for shortcut header prints. */ - t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); - - /* Stupid code to have Relase confirm and Ctrl-Click on gizmo work ok. */ - wmKeyMapItem *kmi = WM_event_match_modal_keymap_item(t->keymap, op, event); - if (kmi) { - if ((t->flag & T_RELEASE_CONFIRM) && (event->val == KM_PRESS) && (kmi->val != KM_PRESS)) { - t->release_confirm_event_type = EVT_MODAL_MAP; - t->release_confirm_event_val = kmi->propvalue; - } - - if ((kmi->propvalue == TFM_MODAL_SNAP_INV_ON) && - ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { - /* Do this only for translation/rotation/resize because only these - * modes are available from gizmo and doing such check could - * lead to keymap conflicts for other modes (see T31584) */ - t->modifiers |= MOD_SNAP_INVERT; - } } } diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index dfa5c164acf..7ccfd0149bd 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -32,6 +32,7 @@ #include "ED_screen.h" #include "WM_api.h" +#include "WM_types.h" #include "UI_interface.h" @@ -45,6 +46,18 @@ /** \name Transform (Sequencer Slide) * \{ */ +static eRedrawFlag seq_slide_handleEvent(struct TransInfo *t, const wmEvent *event) +{ + BLI_assert(t->mode == TFM_SEQ_SLIDE); + wmKeyMapItem *kmi = t->custom.mode.data; + if (kmi && event->type == kmi->type && event->val == kmi->val) { + /* Allows the 'Expand to fit' effect to be enabled as a toogle. */ + t->flag ^= T_ALT_TRANSFORM; + return TREDRAW_HARD; + } + return TREDRAW_NOTHING; +} + static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR]) { char tvec[NUM_STR_REP_LEN * 3]; @@ -60,12 +73,11 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA ofs += BLI_snprintf( str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); - if (t->keymap) { - wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); - if (kmi) { - ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); - } + wmKeyMapItem *kmi = t->custom.mode.data; + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); } + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, TIP_(" or Alt) Expand to fit %s"), @@ -91,7 +103,7 @@ static void applySeqSlideValue(TransInfo *t, const float val[2]) static void applySeqSlide(TransInfo *t, const int mval[2]) { char str[UI_MAX_DRAW_STR]; - float values_final[2] = {0.0f}; + float values_final[3] = {0.0f}; snapSequenceBounds(t, mval); if (applyNumInput(&t->num, values_final)) { @@ -126,6 +138,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) void initSeqSlide(TransInfo *t) { t->transform = applySeqSlide; + t->handleEvent = seq_slide_handleEvent; initMouseInputMode(t, &t->mouse, INPUT_VECTOR); @@ -142,5 +155,10 @@ void initSeqSlide(TransInfo *t) * (supporting frames in addition to "natural" time...). */ t->num.unit_type[0] = B_UNIT_NONE; t->num.unit_type[1] = B_UNIT_NONE; + + if (t->keymap) { + /* Workaround to use the same key as the modal keymap. */ + t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + } } /** \} */ diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index cdea388529f..2a5c631df41 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -32,6 +32,7 @@ #include "ED_screen.h" #include "WM_api.h" +#include "WM_types.h" #include "UI_interface.h" @@ -45,6 +46,18 @@ /** \name Transform (Shrink-Fatten) * \{ */ +static eRedrawFlag shrinkfatten_handleEvent(struct TransInfo *t, const wmEvent *event) +{ + BLI_assert(t->mode == TFM_SHRINKFATTEN); + wmKeyMapItem *kmi = t->custom.mode.data; + if (kmi && event->type == kmi->type && event->val == kmi->val) { + /* Allows the 'Even Thickness' effect to be enabled as a toogle. */ + t->flag ^= T_ALT_TRANSFORM; + return TREDRAW_HARD; + } + return TREDRAW_NOTHING; +} + static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { float distance; @@ -77,12 +90,11 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); - if (t->keymap) { - wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); - if (kmi) { - ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); - } + wmKeyMapItem *kmi = t->custom.mode.data; + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); } + BLI_snprintf(str + ofs, sizeof(str) - ofs, TIP_(" or Alt) Even Thickness %s"), @@ -121,6 +133,7 @@ void initShrinkFatten(TransInfo *t) else { t->mode = TFM_SHRINKFATTEN; t->transform = applyShrinkFatten; + t->handleEvent = shrinkfatten_handleEvent; initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); @@ -134,6 +147,11 @@ void initShrinkFatten(TransInfo *t) t->num.unit_type[0] = B_UNIT_LENGTH; t->flag |= T_NO_CONSTRAINT; + + if (t->keymap) { + /* Workaround to use the same key as the modal keymap. */ + t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + } } } /** \} */ diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index a54de102966..90c1f241338 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -60,13 +60,18 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ char autoik[NUM_STR_REP_LEN]; float dist; + UnitSettings *unit = NULL; + if (!(t->flag & T_2D_EDIT)) { + unit = &t->scene->unit; + } + if (hasNumInput(&t->num)) { outputNumInput(&(t->num), tvec, &t->scene->unit); dist = len_v3(t->num.val); } else { float dvec[3]; - if (!(t->flag & T_2D_EDIT) && t->con.mode & CON_APPLY) { + if (t->con.mode & CON_APPLY) { int i = 0; zero_v3(dvec); if (t->con.mode & CON_AXIS0) { @@ -81,18 +86,22 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ } else { copy_v3_v3(dvec, vec); + } + + if (t->flag & T_2D_EDIT) { applyAspectRatio(t, dvec); } - dist = len_v3(vec); - if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { + dist = len_v3(dvec); + + if (unit) { for (int i = 0; i < 3; i++) { BKE_unit_value_as_string(&tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, - dvec[i] * t->scene->unit.scale_length, + dvec[i] * unit->scale_length, 4, B_UNIT_LENGTH, - &t->scene->unit, + unit, true); } } @@ -103,14 +112,9 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ } } - if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { - BKE_unit_value_as_string(distvec, - sizeof(distvec), - dist * t->scene->unit.scale_length, - 4, - B_UNIT_LENGTH, - &t->scene->unit, - false); + if (unit) { + BKE_unit_value_as_string( + distvec, sizeof(distvec), dist * unit->scale_length, 4, B_UNIT_LENGTH, unit, false); } else if (dist > 1e10f || dist < -1e10f) { /* prevent string buffer overflow */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 7282c35ea0f..5153fdedcae 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -376,7 +376,7 @@ static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event) { int retval = 1; if (op->customdata == NULL) { - TransInfo *t = op->customdata = MEM_callocN(sizeof(TransInfo), "TransInfo data2"); + TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2"); TransformModeItem *tmode; int mode = -1; @@ -396,10 +396,10 @@ static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event) /* store data */ if (retval) { G.moving = special_transform_moving(t); + op->customdata = t; } else { MEM_freeN(t); - op->customdata = NULL; } } diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c index 8a8259d335a..93948b5ae1b 100644 --- a/source/blender/editors/uvedit/uvedit_islands.c +++ b/source/blender/editors/uvedit/uvedit_islands.c @@ -144,18 +144,20 @@ static float (*bm_face_array_calc_unique_uv_coords( BMEdge *e_first = v_pivot->e; const BMEdge *e = e_first; do { - const BMLoop *l_radial = e->l; - do { - if (l_radial->v == l_iter->v) { - if (BM_elem_flag_test(l_radial, BM_ELEM_TAG)) { - const MLoopUV *luv_radial = BM_ELEM_CD_GET_VOID_P(l_radial, cd_loop_uv_offset); - if (equals_v2v2(luv->uv, luv_radial->uv)) { - /* Don't add this UV when met in another face in `faces`. */ - BM_elem_flag_disable(l_iter, BM_ELEM_TAG); + if (e->l != NULL) { + const BMLoop *l_radial = e->l; + do { + if (l_radial->v == l_iter->v) { + if (BM_elem_flag_test(l_radial, BM_ELEM_TAG)) { + const MLoopUV *luv_radial = BM_ELEM_CD_GET_VOID_P(l_radial, cd_loop_uv_offset); + if (equals_v2v2(luv->uv, luv_radial->uv)) { + /* Don't add this UV when met in another face in `faces`. */ + BM_elem_flag_disable(l_iter, BM_ELEM_TAG); + } } } - } - } while ((l_radial = l_radial->radial_next) != e->l); + } while ((l_radial = l_radial->radial_next) != e->l); + } } while ((e = BM_DISK_EDGE_NEXT(e, v_pivot)) != e_first); } while ((l_iter = l_iter->next) != l_first); } diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index 63612694e65..ddd11729e67 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -22,7 +22,7 @@ extern "C" { #include <Python.h> } -#include <float.h> +#include <cfloat> #include <fstream> #include <string> @@ -1067,7 +1067,7 @@ void Controller::displayDensityCurves(int x, int y) } unsigned int i, j; - typedef vector<Vec3r> densityCurve; + using densityCurve = vector<Vec3r>; vector<densityCurve> curves(svm->getNumberOfOrientations() + 1); vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels()); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 8aaffd4dde8..f761b1f6243 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -64,7 +64,7 @@ #include "render_types.h" -#include <limits.h> +#include <climits> namespace Freestyle { diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp index 5682ccc9298..5768f88e95f 100644 --- a/source/blender/freestyle/intern/geometry/FitCurve.cpp +++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp @@ -20,9 +20,9 @@ * \brief from "Graphics Gems", Academic Press, 1990 */ +#include <cmath> +#include <cstdio> #include <cstdlib> // for malloc and free -#include <math.h> -#include <stdio.h> #include "FitCurve.h" @@ -30,7 +30,7 @@ using namespace std; namespace Freestyle { -typedef Vector2 *BezierCurve; +using BezierCurve = Vector2 *; /* Forward declarations */ static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve); diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp index b1d0a6c7e2a..7ec18fb2801 100644 --- a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp +++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp @@ -29,9 +29,9 @@ # endif #endif +#include <cstdio> #include <list> #include <map> -#include <stdio.h> #include "GeomCleaner.h" @@ -202,7 +202,7 @@ void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned *oVSize, unsigned **oIndices) { - typedef map<Vec3f, unsigned> cleanHashTable; + using cleanHashTable = map<Vec3f, unsigned>; vector<Vec3f> vertices; unsigned i; for (i = 0; i < iVSize; i += 3) { diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp index 7c42c332370..e3ea2ac154f 100644 --- a/source/blender/freestyle/intern/geometry/Noise.cpp +++ b/source/blender/freestyle/intern/geometry/Noise.cpp @@ -19,10 +19,10 @@ * \brief Class to define Perlin noise */ -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <time.h> +#include <cmath> +#include <cstdio> +#include <cstdlib> +#include <ctime> #include "BLI_compiler_attrs.h" #include "BLI_rand.h" diff --git a/source/blender/freestyle/intern/image/GaussianFilter.cpp b/source/blender/freestyle/intern/image/GaussianFilter.cpp index 3bbe86ee986..3c8bf5bd3a1 100644 --- a/source/blender/freestyle/intern/image/GaussianFilter.cpp +++ b/source/blender/freestyle/intern/image/GaussianFilter.cpp @@ -19,7 +19,7 @@ * \brief Class to perform gaussian filtering operations on an image */ -#include <stdlib.h> +#include <cstdlib> #include "GaussianFilter.h" diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp index 052ae73da43..4fc1f227172 100644 --- a/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp +++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp @@ -19,8 +19,8 @@ * \brief Class to represent a light node */ -#include <math.h> -#include <string.h> // for memcpy +#include <cmath> +#include <cstring> // for memcpy #include "NodeCamera.h" diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp index c3dac81477d..768e9efa15d 100644 --- a/source/blender/freestyle/intern/stroke/Curve.cpp +++ b/source/blender/freestyle/intern/stroke/Curve.cpp @@ -19,7 +19,7 @@ * \brief Class to define a container for curves */ -#include <stdio.h> /* printf */ +#include <cstdio> /* printf */ #include "Curve.h" #include "CurveAdvancedIterators.h" diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp index 7e8937bfe80..9bf00ed7092 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp @@ -19,7 +19,7 @@ * \brief Detects/flags/builds extended features edges on the WXEdge structure */ -#include <float.h> +#include <cfloat> #include "FEdgeXDetector.h" diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp index 60d0e45b9fb..d304c3616d7 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp @@ -19,7 +19,7 @@ * \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.) */ -#include <float.h> +#include <cfloat> #include "ViewMap.h" #include "ViewMapAdvancedIterators.h" diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index de30ee0460a..cbb5c730b2b 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -2299,8 +2299,8 @@ struct less_SVertex2D { } }; -typedef Segment<FEdge *, Vec3r> segment; -typedef Intersection<segment> intersection; +using segment = Segment<FEdge *, Vec3r>; +using intersection = Intersection<segment>; struct less_Intersection { segment *edge; @@ -2326,7 +2326,7 @@ struct silhouette_binary_rule : public binary_rule<segment, segment> { { } - virtual bool operator()(segment &s1, segment &s2) + bool operator()(segment &s1, segment &s2) override { FEdge *f1 = s1.edge(); FEdge *f2 = s2.edge(); diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp index aed5d6b5adc..774751a2589 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp @@ -19,7 +19,7 @@ * \brief Functions to manage I/O for the view map */ -#include <limits.h> +#include <climits> #include "ViewMapIO.h" diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp index 1702a22c678..0ee491a071c 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -33,7 +33,7 @@ * \brief OGF/Graphite: Geometry and Graphics Programming Library + Utilities */ -#include <assert.h> +#include <cassert> #include <cstdlib> // for malloc and free #include <set> #include <stack> diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 7e2fe753b7b..69a79e2f2ce 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -313,6 +313,7 @@ data_to_c_simple(shaders/material/gpu_shader_material_noise.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_normal.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_normal_map.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_object_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_output_aov.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_output_material.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_output_world.glsl SRC) data_to_c_simple(shaders/material/gpu_shader_material_particle_info.glsl SRC) diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 67cd1a61aed..312da491a36 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -173,6 +173,7 @@ GPUNodeLink *GPU_uniformbuf_link_out(struct GPUMaterial *mat, const int index); void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); +void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link, int hash); void GPU_material_sss_profile_create(GPUMaterial *material, float radii[3], diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc index 3bf1233c000..9dc24c59e22 100644 --- a/source/blender/gpu/intern/gpu_batch.cc +++ b/source/blender/gpu/intern/gpu_batch.cc @@ -42,7 +42,7 @@ #include "gpu_batch_private.hh" -#include <string.h> +#include <cstring> using namespace blender::gpu; @@ -81,8 +81,8 @@ void GPU_batch_init_ex(GPUBatch *batch, for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; v++) { batch->verts[v] = nullptr; } - for (int v = 0; v < GPU_BATCH_INST_VBO_MAX_LEN; v++) { - batch->inst[v] = nullptr; + for (auto &v : batch->inst) { + v = nullptr; } batch->elem = elem; batch->prim_type = prim_type; diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 3ebe2edc89e..84da95f6fee 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -411,7 +411,7 @@ static void codegen_declare_tmps(DynStr *ds, GPUNodeGraph *graph) BLI_dynstr_append(ds, "\n"); } -static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *finaloutput) +static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph) { LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) { BLI_dynstr_appendf(ds, " %s(", node->name); @@ -509,8 +509,11 @@ static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *f BLI_dynstr_append(ds, ");\n"); } +} - BLI_dynstr_appendf(ds, "\n return tmp%d;\n", finaloutput->id); +static void codegen_final_output(DynStr *ds, GPUOutput *finaloutput) +{ + BLI_dynstr_appendf(ds, "return tmp%d;\n", finaloutput->id); } static char *code_generate_fragment(GPUMaterial *material, @@ -593,7 +596,35 @@ static char *code_generate_fragment(GPUMaterial *material, } codegen_declare_tmps(ds, graph); - codegen_call_functions(ds, graph, graph->outlink->output); + codegen_call_functions(ds, graph); + + BLI_dynstr_append(ds, " #ifndef VOLUMETRICS\n"); + BLI_dynstr_append(ds, " if (renderPassAOV) {\n"); + BLI_dynstr_append(ds, " switch (render_pass_aov_hash()) {\n"); + GSet *aovhashes_added = BLI_gset_int_new(__func__); + LISTBASE_FOREACH (GPUNodeGraphOutputLink *, aovlink, &graph->outlink_aovs) { + void *aov_key = POINTER_FROM_INT(aovlink->hash); + if (BLI_gset_haskey(aovhashes_added, aov_key)) { + continue; + } + BLI_dynstr_appendf(ds, " case %d: {\n ", aovlink->hash); + codegen_final_output(ds, aovlink->outlink->output); + BLI_dynstr_append(ds, " }\n"); + BLI_gset_add(aovhashes_added, aov_key); + } + BLI_gset_free(aovhashes_added, NULL); + BLI_dynstr_append(ds, " default: {\n"); + BLI_dynstr_append(ds, " Closure no_aov = CLOSURE_DEFAULT;\n"); + BLI_dynstr_append(ds, " no_aov.holdout = 1.0;\n"); + BLI_dynstr_append(ds, " return no_aov;\n"); + BLI_dynstr_append(ds, " }\n"); + BLI_dynstr_append(ds, " }\n"); + BLI_dynstr_append(ds, " } else {\n"); + BLI_dynstr_append(ds, " #else /* VOLUMETRICS */\n"); + BLI_dynstr_append(ds, " {\n"); + BLI_dynstr_append(ds, " #endif /* VOLUMETRICS */\n "); + codegen_final_output(ds, graph->outlink->output); + BLI_dynstr_append(ds, " }\n"); BLI_dynstr_append(ds, "}\n"); diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index f11f1cea753..d5d7994a154 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -57,18 +57,18 @@ FrameBuffer::FrameBuffer(const char *name) dirty_attachments_ = true; dirty_state_ = true; - for (int i = 0; i < ARRAY_SIZE(attachments_); i++) { - attachments_[i].tex = nullptr; - attachments_[i].mip = -1; - attachments_[i].layer = -1; + for (GPUAttachment &attachment : attachments_) { + attachment.tex = nullptr; + attachment.mip = -1; + attachment.layer = -1; } } FrameBuffer::~FrameBuffer() { - for (int i = 0; i < ARRAY_SIZE(attachments_); i++) { - if (attachments_[i].tex != nullptr) { - reinterpret_cast<Texture *>(attachments_[i].tex)->detach_from(this); + for (GPUAttachment &attachment : attachments_) { + if (attachment.tex != nullptr) { + reinterpret_cast<Texture *>(attachment.tex)->detach_from(this); } } } @@ -148,8 +148,8 @@ void FrameBuffer::recursive_downsample(int max_lvl, for (int mip_lvl = 1; mip_lvl <= max_lvl; mip_lvl++) { /* Replace attached mip-level for each attachment. */ - for (int att = 0; att < ARRAY_SIZE(attachments_); att++) { - Texture *tex = reinterpret_cast<Texture *>(attachments_[att].tex); + for (GPUAttachment &attachment : attachments_) { + Texture *tex = reinterpret_cast<Texture *>(attachment.tex); if (tex != nullptr) { /* Some Intel HDXXX have issue with rendering to a mipmap that is below * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case @@ -158,7 +158,7 @@ void FrameBuffer::recursive_downsample(int max_lvl, /* Restrict fetches only to previous level. */ tex->mip_range_set(mip_lvl - 1, mip_max); /* Bind next level. */ - attachments_[att].mip = mip_lvl; + attachment.mip = mip_lvl; } } /* Update the internal attachments and viewport size. */ @@ -168,12 +168,12 @@ void FrameBuffer::recursive_downsample(int max_lvl, callback(userData, mip_lvl); } - for (int att = 0; att < ARRAY_SIZE(attachments_); att++) { - if (attachments_[att].tex != nullptr) { + for (GPUAttachment &attachment : attachments_) { + if (attachment.tex != nullptr) { /* Reset mipmap level range. */ - reinterpret_cast<Texture *>(attachments_[att].tex)->mip_range_set(0, max_lvl); + reinterpret_cast<Texture *>(attachment.tex)->mip_range_set(0, max_lvl); /* Reset base level. NOTE: might not be the one bound at the start of this function. */ - attachments_[att].mip = 0; + attachment.mip = 0; } } dirty_attachments_ = true; @@ -525,18 +525,18 @@ static GPUFrameBuffer *gpu_offscreen_fb_get(GPUOffScreen *ofs) Context *ctx = Context::get(); BLI_assert(ctx); - for (int i = 0; i < MAX_CTX_FB_LEN; i++) { - if (ofs->framebuffers[i].fb == nullptr) { - ofs->framebuffers[i].ctx = ctx; - GPU_framebuffer_ensure_config(&ofs->framebuffers[i].fb, + for (auto &framebuffer : ofs->framebuffers) { + if (framebuffer.fb == nullptr) { + framebuffer.ctx = ctx; + GPU_framebuffer_ensure_config(&framebuffer.fb, { GPU_ATTACHMENT_TEXTURE(ofs->depth), GPU_ATTACHMENT_TEXTURE(ofs->color), }); } - if (ofs->framebuffers[i].ctx == ctx) { - return ofs->framebuffers[i].fb; + if (framebuffer.ctx == ctx) { + return framebuffer.fb; } } @@ -550,9 +550,9 @@ static GPUFrameBuffer *gpu_offscreen_fb_get(GPUOffScreen *ofs) "Warning: GPUOffscreen used in more than 3 GPUContext. " "This may create performance drop.\n"); - for (int i = 0; i < MAX_CTX_FB_LEN; i++) { - GPU_framebuffer_free(ofs->framebuffers[i].fb); - ofs->framebuffers[i].fb = nullptr; + for (auto &framebuffer : ofs->framebuffers) { + GPU_framebuffer_free(framebuffer.fb); + framebuffer.fb = nullptr; } return gpu_offscreen_fb_get(ofs); @@ -595,9 +595,9 @@ GPUOffScreen *GPU_offscreen_create( void GPU_offscreen_free(GPUOffScreen *ofs) { - for (int i = 0; i < MAX_CTX_FB_LEN; i++) { - if (ofs->framebuffers[i].fb) { - GPU_framebuffer_free(ofs->framebuffers[i].fb); + for (auto &framebuffer : ofs->framebuffers) { + if (framebuffer.fb) { + GPU_framebuffer_free(framebuffer.fb); } } if (ofs->color) { diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index a0fe77598f2..3f22424c7c9 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -597,6 +597,14 @@ void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) } } +void GPU_material_add_output_link_aov(GPUMaterial *material, GPUNodeLink *link, int hash) +{ + GPUNodeGraphOutputLink *aov_link = MEM_callocN(sizeof(GPUNodeGraphOutputLink), __func__); + aov_link->outlink = link; + aov_link->hash = hash; + BLI_addtail(&material->graph.outlink_aovs, aov_link); +} + GPUNodeGraph *gpu_material_node_graph(GPUMaterial *material) { return &material->graph; diff --git a/source/blender/gpu/intern/gpu_material_library.c b/source/blender/gpu/intern/gpu_material_library.c index e0165e1fa83..496988c4ba9 100644 --- a/source/blender/gpu/intern/gpu_material_library.c +++ b/source/blender/gpu/intern/gpu_material_library.c @@ -84,6 +84,7 @@ extern char datatoc_gpu_shader_material_noise_glsl[]; extern char datatoc_gpu_shader_material_normal_glsl[]; extern char datatoc_gpu_shader_material_normal_map_glsl[]; extern char datatoc_gpu_shader_material_object_info_glsl[]; +extern char datatoc_gpu_shader_material_output_aov_glsl[]; extern char datatoc_gpu_shader_material_output_material_glsl[]; extern char datatoc_gpu_shader_material_output_world_glsl[]; extern char datatoc_gpu_shader_material_particle_info_glsl[]; @@ -354,6 +355,11 @@ static GPUMaterialLibrary gpu_shader_material_object_info_library = { .dependencies = {NULL}, }; +static GPUMaterialLibrary gpu_shader_material_output_aov_library = { + .code = datatoc_gpu_shader_material_output_aov_glsl, + .dependencies = {NULL}, +}; + static GPUMaterialLibrary gpu_shader_material_output_material_library = { .code = datatoc_gpu_shader_material_output_material_glsl, .dependencies = {NULL}, @@ -619,6 +625,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = { &gpu_shader_material_normal_library, &gpu_shader_material_normal_map_library, &gpu_shader_material_object_info_library, + &gpu_shader_material_output_aov_library, &gpu_shader_material_output_material_library, &gpu_shader_material_output_world_library, &gpu_shader_material_particle_info_library, diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc index dae56e39db6..4ccb28fedbd 100644 --- a/source/blender/gpu/intern/gpu_matrix.cc +++ b/source/blender/gpu/intern/gpu_matrix.cc @@ -39,15 +39,15 @@ using namespace blender::gpu; #define MATRIX_STACK_DEPTH 32 -typedef float Mat4[4][4]; -typedef float Mat3[3][3]; +using Mat4 = float[4][4]; +using Mat3 = float[3][3]; -typedef struct MatrixStack { +struct MatrixStack { Mat4 stack[MATRIX_STACK_DEPTH]; uint top; -} MatrixStack; +}; -typedef struct GPUMatrixState { +struct GPUMatrixState { MatrixStack model_view_stack; MatrixStack projection_stack; @@ -59,7 +59,7 @@ typedef struct GPUMatrixState { * TODO: separate Model from View transform? Batches/objects have model, * camera/eye has view & projection */ -} GPUMatrixState; +}; #define ModelViewStack Context::get()->matrix_state->model_view_stack #define ModelView ModelViewStack.stack[ModelViewStack.top] diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index 2a2a51e32b3..08da49c3475 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -805,6 +805,7 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph) /* Free both node graph and requested attributes and textures. */ void gpu_node_graph_free(GPUNodeGraph *graph) { + BLI_freelistN(&graph->outlink_aovs); gpu_node_graph_free_nodes(graph); LISTBASE_FOREACH (GPUMaterialVolumeGrid *, grid, &graph->volume_grids) { @@ -847,6 +848,9 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph) } gpu_nodes_tag(graph->outlink); + LISTBASE_FOREACH (GPUNodeGraphOutputLink *, aovlink, &graph->outlink_aovs) { + gpu_nodes_tag(aovlink->outlink); + } for (GPUNode *node = graph->nodes.first, *next = NULL; node; node = next) { next = node->next; diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h index a0e6298cd92..0ef95d94c0d 100644 --- a/source/blender/gpu/intern/gpu_node_graph.h +++ b/source/blender/gpu/intern/gpu_node_graph.h @@ -141,12 +141,20 @@ typedef struct GPUInput { }; } GPUInput; +typedef struct GPUNodeGraphOutputLink { + struct GPUNodeGraphOutputLink *next, *prev; + int hash; + GPUNodeLink *outlink; +} GPUNodeGraphOutputLink; + typedef struct GPUNodeGraph { /* Nodes */ ListBase nodes; - /* Output. */ + /* Main Output. */ GPUNodeLink *outlink; + /* List of GPUNodeGraphOutputLink */ + ListBase outlink_aovs; /* Requested attributes and textures. */ ListBase attributes; diff --git a/source/blender/gpu/intern/gpu_select_sample_query.cc b/source/blender/gpu/intern/gpu_select_sample_query.cc index 6ca811895a5..5d8689c0d6a 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.cc +++ b/source/blender/gpu/intern/gpu_select_sample_query.cc @@ -24,7 +24,7 @@ * similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility. */ -#include <stdlib.h> +#include <cstdlib> #include "GPU_debug.h" #include "GPU_framebuffer.h" @@ -47,7 +47,7 @@ using namespace blender; using namespace blender::gpu; -typedef struct GPUSelectQueryState { +struct GPUSelectQueryState { /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */ bool query_issued; /* GPU queries abstraction. Contains an array of queries. */ @@ -68,7 +68,7 @@ typedef struct GPUSelectQueryState { int scissor[4]; eGPUWriteMask write_mask; eGPUDepthTest depth_test; -} GPUSelectQueryState; +}; static GPUSelectQueryState g_query_state = {false}; diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 827ea06686f..d47ad5e0100 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -470,9 +470,9 @@ struct GPUShader *GPU_shader_create_from_arrays_impl( GPUShader *sh = GPU_shader_create( str_dst[0].str, str_dst[1].str, str_dst[2].str, nullptr, str_dst[3].str, name); - for (int i = 0; i < ARRAY_SIZE(str_dst); i++) { - if (str_dst[i].is_alloc) { - MEM_freeN((void *)str_dst[i].str); + for (auto &i : str_dst) { + if (i.is_alloc) { + MEM_freeN((void *)i.str); } } return sh; diff --git a/source/blender/gpu/intern/gpu_uniform_buffer.cc b/source/blender/gpu/intern/gpu_uniform_buffer.cc index 89c70c47e4a..3edb090d81c 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer.cc +++ b/source/blender/gpu/intern/gpu_uniform_buffer.cc @@ -22,7 +22,7 @@ */ #include "MEM_guardedalloc.h" -#include <string.h> +#include <cstring> #include "BLI_blenlib.h" #include "BLI_math_base.h" diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index 3b0aa055588..cd6d78a185d 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -27,8 +27,8 @@ #include "gpu_shader_private.hh" #include "gpu_vertex_format_private.h" -#include <stddef.h> -#include <string.h> +#include <cstddef> +#include <cstring> #include "BLI_ghash.h" #include "BLI_string.h" diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 7e948149a7f..f683a70b4e6 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -131,19 +131,11 @@ void GLBackend::platform_init() } } - /* Since Blender 2.91 AMD TeraScale 2 GPUs crashes during startup. */ - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY)) { - if (strstr(renderer, "Radeon HD 4") || strstr(renderer, "Radeon HD 5") || - strstr(renderer, "Radeon HD 6") || strstr(renderer, "ATI FirePro V4") || - strstr(renderer, "AMD Radeon R5 2")) { - GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED; - } - } - /* Driver 20.11.2 fixes a lot of issues for the Navi cards, but introduces new ones + /* Driver 20.11.2/3 fixes a lot of issues for the Navi cards, but introduces new ones * for Polaris based cards cards. The viewport has glitches but doesn't crash. - * See T82856 */ + * See T82856,T83574. */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && - strstr(version, " 20.11.2 ")) { + (strstr(version, " 20.11.2 ") || strstr(version, " 20.11.3 "))) { if (strstr(renderer, "Radeon RX 460 ") || strstr(renderer, "Radeon RX 470 ") || strstr(renderer, "Radeon RX 480 ") || strstr(renderer, "Radeon RX 490 ") || strstr(renderer, "Radeon RX 560 ") || strstr(renderer, "Radeon RX 570 ") || @@ -152,8 +144,10 @@ void GLBackend::platform_init() } } if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_ANY)) { + /* Platform seems to work when SB backend is disabled. This can be done + * by adding the environment variable `R600_DEBUG=nosb`. */ if (strstr(renderer, "AMD CEDAR")) { - GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED; + GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED; } } } @@ -253,10 +247,6 @@ static void detect_workarounds() return; } - /* Some Intel drivers have issues with using mips as framebuffer targets if - * GL_TEXTURE_MAX_LEVEL is higher than the target mip. - * Only check at the end after all other workarounds because this uses the drawing code. */ - GCaps.mip_render_workaround = detect_mip_render_workaround(); /* Limit support for GLEW_ARB_base_instance to OpenGL 4.0 and higher. NVIDIA Quadro FX 4800 * (TeraScale) report that they support GLEW_ARB_base_instance, but the driver does not support * GLEW_ARB_draw_indirect as it has an OpenGL3 context what also matches the minimum needed @@ -277,6 +267,7 @@ static void detect_workarounds() (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") || strstr(version, "4.5.13422"))) { GLContext::unused_fb_slot_workaround = true; + GCaps.mip_render_workaround = true; GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; } @@ -368,6 +359,13 @@ static void detect_workarounds() } } + /* Some Intel drivers have issues with using mips as framebuffer targets if + * GL_TEXTURE_MAX_LEVEL is higher than the target mip. + * Only check at the end after all other workarounds because this uses the drawing code. + * Also after device/driver flags to avoid the check that causes pre GCN Radeon to crash. */ + if (GCaps.mip_render_workaround == false) { + GCaps.mip_render_workaround = detect_mip_render_workaround(); + } /* Disable multidraw if the base instance cannot be read. */ if (GLContext::shader_draw_parameters_support == false) { GLContext::multi_draw_indirect_support = false; diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index 4e45ff11fc7..0914c117241 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -42,7 +42,7 @@ #include "gl_debug.hh" -#include <stdio.h> +#include <cstdio> static CLG_LogRef LOG = {"gpu.debug"}; diff --git a/source/blender/gpu/opengl/gl_debug_layer.cc b/source/blender/gpu/opengl/gl_debug_layer.cc index 9c2b6c0e547..7d2abfb2cff 100644 --- a/source/blender/gpu/opengl/gl_debug_layer.cc +++ b/source/blender/gpu/opengl/gl_debug_layer.cc @@ -30,7 +30,7 @@ #include "gl_debug.hh" -typedef void *GPUvoidptr; +using GPUvoidptr = void *; #define GPUvoidptr_set void *ret = #define GPUvoidptr_ret return ret diff --git a/source/blender/gpu/opengl/gl_drawlist.cc b/source/blender/gpu/opengl/gl_drawlist.cc index aecadc4d14a..f0a18deafd3 100644 --- a/source/blender/gpu/opengl/gl_drawlist.cc +++ b/source/blender/gpu/opengl/gl_drawlist.cc @@ -39,24 +39,24 @@ #include "gl_drawlist.hh" #include "gl_primitive.hh" -#include <limits.h> +#include <climits> using namespace blender::gpu; -typedef struct GLDrawCommand { +struct GLDrawCommand { GLuint v_count; GLuint i_count; GLuint v_first; GLuint i_first; -} GLDrawCommand; +}; -typedef struct GLDrawCommandIndexed { +struct GLDrawCommandIndexed { GLuint v_count; GLuint i_count; GLuint v_first; GLuint base_index; GLuint i_first; -} GLDrawCommandIndexed; +}; #define MDI_ENABLED (buffer_size_ != 0) #define MDI_DISABLED (buffer_size_ == 0) diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_aov.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_aov.glsl new file mode 100644 index 00000000000..648994739bf --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_aov.glsl @@ -0,0 +1,13 @@ + +void node_output_aov(vec4 color, float value, out Closure result) +{ + result = CLOSURE_DEFAULT; +#ifndef VOLUMETRICS + if (render_pass_aov_is_color()) { + result.radiance = color.rgb; + } + else { + result.radiance = vec3(value); + } +#endif +} diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 61f2153cf6c..9512bce1914 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -23,8 +23,8 @@ */ #include <cmath> -#include <stdlib.h> -#include <string.h> +#include <cstdlib> +#include <cstring> #include <vector> /* iTaSC headers */ @@ -73,12 +73,12 @@ struct IK_Data { struct IK_Scene *first; }; -typedef float Vector3[3]; -typedef float Vector4[4]; +using Vector3 = float[3]; +using Vector4 = float[4]; struct IK_Target; -typedef void (*ErrorCallback)(const iTaSC::ConstraintValues *values, - unsigned int nvalues, - IK_Target *iktarget); +using ErrorCallback = void (*)(const iTaSC::ConstraintValues *values, + unsigned int nvalues, + IK_Target *iktarget); /* one structure for each target in the scene */ struct IK_Target { @@ -194,8 +194,8 @@ struct IK_Scene { { /* delete scene first */ delete scene; - for (std::vector<IK_Target *>::iterator it = targets.begin(); it != targets.end(); ++it) { - delete (*it); + for (IK_Target *target : targets) { + delete target; } targets.clear(); delete[] channels; diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index b7a15812547..4580bfd2cbf 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -123,16 +123,16 @@ static void fillDpxMainHeader(LogImageFile *dpx, header->televisionHeader.field_number = DPX_UNDEFINED_U8; header->televisionHeader.video_signal = DPX_UNDEFINED_U8; header->televisionHeader.padding = DPX_UNDEFINED_U8; - header->televisionHeader.horizontal_sample_rate = DPX_UNDEFINED_R32; - header->televisionHeader.vertical_sample_rate = DPX_UNDEFINED_R32; - header->televisionHeader.frame_rate = DPX_UNDEFINED_R32; - header->televisionHeader.time_offset = DPX_UNDEFINED_R32; + header->televisionHeader.horizontal_sample_rate = swap_float(DPX_UNDEFINED_R32, dpx->isMSB); + header->televisionHeader.vertical_sample_rate = swap_float(DPX_UNDEFINED_R32, dpx->isMSB); + header->televisionHeader.frame_rate = swap_float(DPX_UNDEFINED_R32, dpx->isMSB); + header->televisionHeader.time_offset = swap_float(DPX_UNDEFINED_R32, dpx->isMSB); header->televisionHeader.gamma = swap_float(dpx->gamma, dpx->isMSB); header->televisionHeader.black_level = swap_float(dpx->referenceBlack, dpx->isMSB); - header->televisionHeader.black_gain = DPX_UNDEFINED_R32; - header->televisionHeader.breakpoint = DPX_UNDEFINED_R32; + header->televisionHeader.black_gain = swap_float(DPX_UNDEFINED_R32, dpx->isMSB); + header->televisionHeader.breakpoint = swap_float(DPX_UNDEFINED_R32, dpx->isMSB); header->televisionHeader.white_level = swap_float(dpx->referenceWhite, dpx->isMSB); - header->televisionHeader.integration_times = DPX_UNDEFINED_R32; + header->televisionHeader.integration_times = swap_float(DPX_UNDEFINED_R32, dpx->isMSB); } LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) @@ -339,13 +339,11 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue; } - if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || - isnan(dpx->element[i].refLowQuantity)) { + if (IS_DPX_UNDEFINED_R32(dpx->element[i].refLowQuantity)) { dpx->element[i].refLowQuantity = 0.0f; } - if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || - isnan(dpx->element[i].refHighQuantity)) { + if (IS_DPX_UNDEFINED_R32(dpx->element[i].refHighQuantity)) { if (ELEM(dpx->element[i].transfer, transfer_PrintingDensity, transfer_Logarithmic)) { dpx->element[i].refHighQuantity = 2.048f; } @@ -370,13 +368,11 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue; } - if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || - isnan(dpx->element[i].refLowQuantity)) { + if (IS_DPX_UNDEFINED_R32(dpx->element[i].refLowQuantity)) { dpx->element[i].refLowQuantity = 0.0f; } - if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || - isnan(dpx->element[i].refHighQuantity)) { + if (IS_DPX_UNDEFINED_R32(dpx->element[i].refHighQuantity)) { dpx->element[i].refHighQuantity = 0.7f; } @@ -391,10 +387,9 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB); dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB); - if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) || - (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || - isnan(dpx->referenceWhite)) || - (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma))) { + if (IS_DPX_UNDEFINED_R32(dpx->referenceBlack) || + (dpx->referenceWhite <= dpx->referenceBlack || IS_DPX_UNDEFINED_R32(dpx->referenceWhite)) || + (dpx->gamma <= 0 || IS_DPX_UNDEFINED_R32(dpx->gamma))) { dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; dpx->gamma = 1.7f; diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h index 6b729dba59a..1228ac4ee66 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.h +++ b/source/blender/imbuf/intern/cineon/dpxlib.h @@ -24,6 +24,8 @@ #pragma once +#include <math.h> + #include "logImageCore.h" #ifdef __cplusplus @@ -34,7 +36,8 @@ extern "C" { #define DPX_UNDEFINED_U8 0xFF #define DPX_UNDEFINED_U16 0xFFFF #define DPX_UNDEFINED_U32 0xFFFFFFFF -#define DPX_UNDEFINED_R32 0xFFFFFFFF +#define DPX_UNDEFINED_R32 NAN +#define IS_DPX_UNDEFINED_R32(x) isnan(x) #define DPX_UNDEFINED_CHAR 0 typedef struct { diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index 2d9c300a147..4e4fca864a0 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -608,8 +608,8 @@ void mem_read(Stream &mem, BlockDXT1 &block) void mem_read(Stream &mem, AlphaBlockDXT3 &block) { - for (unsigned int i = 0; i < 4; i++) { - mem_read(mem, block.row[i]); + for (unsigned short &alpha : block.row) { + mem_read(mem, alpha); } } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 7c8b7c1d345..00fa0111d1c 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -150,12 +150,12 @@ static inline uint8 component(Color32 c, uint i) void ColorBlock::swizzle(uint x, uint y, uint z, uint w) { - for (int i = 0; i < 16; i++) { - Color32 c = m_color[i]; - m_color[i].r = component(c, x); - m_color[i].g = component(c, y); - m_color[i].b = component(c, z); - m_color[i].a = component(c, w); + for (Color32 &color : m_color) { + const Color32 c = color; + color.r = component(c, x); + color.g = component(c, y); + color.b = component(c, z); + color.a = component(c, w); } } @@ -243,8 +243,8 @@ Color32 ColorBlock::averageColor() const /** Return true if the block is not fully opaque. */ bool ColorBlock::hasAlpha() const { - for (uint i = 0; i < 16; i++) { - if (m_color[i].a != 255) { + for (const auto &i : m_color) { + if (i.a != 255) { return true; } } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 37e30d30e2c..2a36946df8f 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -52,9 +52,9 @@ #include <DirectDrawSurface.h> #include <PixelFormat.h> -#include <math.h> /* sqrt */ -#include <stdio.h> /* printf */ -#include <stdlib.h> /* malloc */ +#include <cmath> /* sqrt */ +#include <cstdio> /* printf */ +#include <cstdlib> /* malloc */ #include <sys/types.h> /*** declarations ***/ diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index 9b07084bf81..2acf072556a 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -36,7 +36,7 @@ #include "IMB_imbuf_types.h" -#include <string.h> +#include <cstring> #include <BlockDXT.h> #include <ColorBlock.h> @@ -45,7 +45,7 @@ #include <Stream.h> /* A function that flips a DXTC block. */ -typedef void (*FlipBlockFunction)(uint8_t *block); +using FlipBlockFunction = void (*)(uint8_t *block); /* Flips a full DXT1 block in the y direction. */ static void FlipDXT1BlockFull(uint8_t *block) diff --git a/source/blender/imbuf/intern/dds/Image.cpp b/source/blender/imbuf/intern/dds/Image.cpp index 7958a586c7d..9dfa5dd2621 100644 --- a/source/blender/imbuf/intern/dds/Image.cpp +++ b/source/blender/imbuf/intern/dds/Image.cpp @@ -30,7 +30,7 @@ #include <Color.h> #include <Image.h> -#include <stdio.h> /* printf */ +#include <cstdio> /* printf */ Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(nullptr) { diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp index 59892a0a228..3dab3c35675 100644 --- a/source/blender/imbuf/intern/dds/Stream.cpp +++ b/source/blender/imbuf/intern/dds/Stream.cpp @@ -20,8 +20,8 @@ #include <Stream.h> -#include <stdio.h> /* printf */ -#include <string.h> /* memcpy */ +#include <cstdio> /* printf */ +#include <cstring> /* memcpy */ static const char *msg_error_seek = "DDS: trying to seek beyond end of stream (corrupt file?)"; static const char *msg_error_read = "DDS: trying to read beyond end of stream (corrupt file?)"; diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 804d8130b4c..e767cb14b1a 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -23,10 +23,10 @@ #include <DirectDrawSurface.h> #include <FlipDXT.h> #include <Stream.h> +#include <cstddef> +#include <cstdio> /* printf */ #include <dds_api.h> #include <fstream> -#include <stddef.h> -#include <stdio.h> /* printf */ #if defined(WIN32) # include "utfconv.h" diff --git a/source/blender/imbuf/intern/oiio/CMakeLists.txt b/source/blender/imbuf/intern/oiio/CMakeLists.txt index 211b6a0b40e..ee5848dec36 100644 --- a/source/blender/imbuf/intern/oiio/CMakeLists.txt +++ b/source/blender/imbuf/intern/oiio/CMakeLists.txt @@ -49,6 +49,7 @@ if(WITH_OPENIMAGEIO) ) list(APPEND LIB ${OPENIMAGEIO_LIBRARIES} + ${PUGIXML_LIBRARIES} ) if(WITH_IMAGE_OPENEXR) list(APPEND INC_SYS diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 1e8c3c25778..65c25194477 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -48,7 +48,7 @@ OIIO_NAMESPACE_USING using std::string; using std::unique_ptr; -typedef unsigned char uchar; +using uchar = unsigned char; template<class T, class Q> static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 56188fbe98a..9726eaeed2c 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -22,14 +22,14 @@ */ #include <algorithm> -#include <errno.h> +#include <cerrno> +#include <cstddef> +#include <cstdio> +#include <cstdlib> #include <fstream> #include <iostream> #include <set> -#include <stddef.h> #include <stdexcept> -#include <stdio.h> -#include <stdlib.h> #include <string> #include <Iex.h> @@ -120,11 +120,11 @@ class IMemStream : public Imf::IStream { _exrbuf = exrbuf; } - virtual ~IMemStream() + ~IMemStream() override { } - virtual bool read(char c[], int n) + bool read(char c[], int n) override { if (n + _exrpos <= _exrsize) { memcpy(c, (void *)(&_exrbuf[_exrpos]), n); @@ -135,17 +135,17 @@ class IMemStream : public Imf::IStream { return false; } - virtual Int64 tellg() + Int64 tellg() override { return _exrpos; } - virtual void seekg(Int64 pos) + void seekg(Int64 pos) override { _exrpos = pos; } - virtual void clear() + void clear() override { } @@ -175,7 +175,7 @@ class IFileStream : public Imf::IStream { } } - virtual bool read(char c[], int n) + bool read(char c[], int n) override { if (!ifs) { throw Iex::InputExc("Unexpected end of file."); @@ -186,18 +186,18 @@ class IFileStream : public Imf::IStream { return check_error(); } - virtual Int64 tellg() + Int64 tellg() override { return std::streamoff(ifs.tellg()); } - virtual void seekg(Int64 pos) + void seekg(Int64 pos) override { ifs.seekg(pos); check_error(); } - virtual void clear() + void clear() override { ifs.clear(); } @@ -227,7 +227,7 @@ class OMemStream : public OStream { { } - virtual void write(const char c[], int n) + void write(const char c[], int n) override { ensure_size(offset + n); memcpy(ibuf->encodedbuffer + offset, c, n); @@ -235,12 +235,12 @@ class OMemStream : public OStream { ibuf->encodedsize += n; } - virtual Int64 tellp() + Int64 tellp() override { return offset; } - virtual void seekp(Int64 pos) + void seekp(Int64 pos) override { offset = pos; ensure_size(offset); @@ -281,19 +281,19 @@ class OFileStream : public OStream { } } - virtual void write(const char c[], int n) + void write(const char c[], int n) override { errno = 0; ofs.write(c, n); check_error(); } - virtual Int64 tellp() + Int64 tellp() override { return std::streamoff(ofs.tellp()); } - virtual void seekp(Int64 pos) + void seekp(Int64 pos) override { ofs.seekp(pos); check_error(); @@ -322,7 +322,7 @@ struct _RGBAZ { half z; }; -typedef struct _RGBAZ RGBAZ; +using RGBAZ = _RGBAZ; extern "C" { @@ -620,7 +620,7 @@ bool imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags) static ListBase exrhandles = {nullptr, nullptr}; -typedef struct ExrHandle { +struct ExrHandle { struct ExrHandle *next, *prev; char name[FILE_MAX]; @@ -645,10 +645,10 @@ typedef struct ExrHandle { ListBase layers; /* hierarchical, pointing in end to ExrChannel */ int num_half_channels; /* used during filr save, allows faster temporary buffers allocation */ -} ExrHandle; +}; /* flattened out channel */ -typedef struct ExrChannel { +struct ExrChannel { struct ExrChannel *next, *prev; char name[EXR_TOT_MAXNAME + 1]; /* full name with everything */ @@ -658,10 +658,10 @@ typedef struct ExrChannel { char chan_id; /* quick lookup of channel char */ int view_id; /* quick lookup of channel view */ bool use_half_float; /* when saving use half float for file storage */ -} ExrChannel; +}; /* hierarchical; layers -> passes -> channels[] */ -typedef struct ExrPass { +struct ExrPass { struct ExrPass *next, *prev; char name[EXR_PASS_MAXNAME]; int totchan; @@ -672,13 +672,13 @@ typedef struct ExrPass { char internal_name[EXR_PASS_MAXNAME]; /* name with no view */ char view[EXR_VIEW_MAXNAME]; int view_id; -} ExrPass; +}; -typedef struct ExrLayer { +struct ExrLayer { struct ExrLayer *next, *prev; char name[EXR_LAY_MAXNAME + 1]; ListBase passes; -} ExrLayer; +}; /* ********************** */ @@ -733,8 +733,8 @@ static void imb_exr_get_views(MultiPartInputFile &file, StringVector &views) if (exr_has_multipart_file(file) == false) { if (exr_has_multiview(file)) { StringVector sv = multiView(file.header(0)); - for (StringVector::const_iterator i = sv.begin(); i != sv.end(); ++i) { - views.push_back(*i); + for (const std::string &view_name : sv) { + views.push_back(view_name); } } } @@ -991,21 +991,15 @@ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *heig std::vector<MultiViewChannelName> channels; GetChannelsInMultiPartFile(*data->ifile, channels); - for (size_t i = 0; i < channels.size(); i++) { - IMB_exr_add_channel(data, - nullptr, - channels[i].name.c_str(), - channels[i].view.c_str(), - 0, - 0, - nullptr, - false); + for (const MultiViewChannelName &channel : channels) { + IMB_exr_add_channel( + data, nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0, nullptr, false); echan = (ExrChannel *)data->channels.last; - echan->m->name = channels[i].name; - echan->m->view = channels[i].view; - echan->m->part_number = channels[i].part_number; - echan->m->internal_name = channels[i].internal_name; + echan->m->name = channel.name; + echan->m->view = channel.view; + echan->m->part_number = channel.part_number; + echan->m->internal_name = channel.internal_name; } return 1; @@ -1311,9 +1305,8 @@ void IMB_exr_multilayer_convert(void *handle, } else { /* add views to RenderResult */ - for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); - ++i) { - addview(base, (*i).c_str()); + for (const std::string &view_name : *data->multiView) { + addview(base, view_name.c_str()); } } @@ -1554,15 +1547,15 @@ static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream, imb_exr_get_views(*data->ifile, *data->multiView); - for (size_t i = 0; i < channels.size(); i++) { + for (const MultiViewChannelName &channel : channels) { IMB_exr_add_channel( - data, nullptr, channels[i].name.c_str(), channels[i].view.c_str(), 0, 0, nullptr, false); + data, nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0, nullptr, false); echan = (ExrChannel *)data->channels.last; - echan->m->name = channels[i].name; - echan->m->view = channels[i].view; - echan->m->part_number = channels[i].part_number; - echan->m->internal_name = channels[i].internal_name; + echan->m->name = channel.name; + echan->m->view = channel.view; + echan->m->part_number = channel.part_number; + echan->m->internal_name = channel.internal_name; } /* now try to sort out how to assign memory to the channels */ @@ -1689,8 +1682,8 @@ static void exr_print_filecontents(MultiPartInputFile &file) const StringVector views = multiView(file.header(0)); printf("OpenEXR-load: MultiView file\n"); printf("OpenEXR-load: Default view: %s\n", defaultViewName(views).c_str()); - for (StringVector::const_iterator i = views.begin(); i != views.end(); ++i) { - printf("OpenEXR-load: Found view %s\n", (*i).c_str()); + for (const std::string &view : views) { + printf("OpenEXR-load: Found view %s\n", view.c_str()); } } else if (numparts > 1) { @@ -1835,10 +1828,10 @@ static void imb_exr_type_by_channels(ChannelList &channels, * with non-empty ones in the file. */ for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) { - for (std::set<string>::iterator i = layerNames.begin(); i != layerNames.end(); i++) { + for (const std::string &layer_name : layerNames) { /* see if any layername differs from a viewname */ - if (imb_exr_get_multiView_id(views, *i) == -1) { - std::string layerName = *i; + if (imb_exr_get_multiView_id(views, layer_name) == -1) { + std::string layerName = layer_name; size_t pos = layerName.rfind('.'); if (pos == std::string::npos) { diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index 1d0964ebb62..d5ded02be62 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -68,7 +68,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const printf("%s: error, found %d items, %d previews\n", __func__, nnames, nprevs); } BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, free); + BLI_linklist_freeN(names); return ima; } @@ -93,7 +93,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const } BLI_linklist_free(previews, BKE_previewimg_freefunc); - BLI_linklist_free(names, free); + BLI_linklist_freeN(names); } else { BlendThumbnail *data; diff --git a/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc b/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc index 334a26df784..8073e157c13 100644 --- a/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc +++ b/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc @@ -18,7 +18,7 @@ */ #include "abc_subdiv_disabler.h" -#include <stdio.h> +#include <cstdio> #include "BLI_listbase.h" diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 14c3d756d56..0b9636ffb70 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -724,9 +724,7 @@ void AbcMeshReader::assign_facesets_to_mpoly(const ISampleSelector &sample_sel, int current_mat = 0; - for (int i = 0; i < face_sets.size(); i++) { - const std::string &grp_name = face_sets[i]; - + for (const std::string &grp_name : face_sets) { if (r_mat_map.find(grp_name) == r_mat_map.end()) { r_mat_map[grp_name] = ++current_mat; } diff --git a/source/blender/io/alembic/tests/abc_export_test.cc b/source/blender/io/alembic/tests/abc_export_test.cc index e1a9bd34f6b..e20fe2ff492 100644 --- a/source/blender/io/alembic/tests/abc_export_test.cc +++ b/source/blender/io/alembic/tests/abc_export_test.cc @@ -23,7 +23,7 @@ class AlembicExportTest : public testing::Test { Depsgraph *depsgraph; Main *bmain; - virtual void SetUp() + void SetUp() override { abc_archive = nullptr; @@ -41,7 +41,7 @@ class AlembicExportTest : public testing::Test { depsgraph = DEG_graph_new(bmain, &scene, view_layer, DAG_EVAL_RENDER); } - virtual void TearDown() + void TearDown() override { BKE_main_free(bmain); DEG_graph_free(depsgraph); diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index 2e7977d89bb..77ccdeae28d 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -18,7 +18,7 @@ * \ingroup collada */ -#include <stddef.h> +#include <cstddef> /* COLLADABU_ASSERT, may be able to remove later */ #include "COLLADABUPlatform.h" @@ -272,9 +272,8 @@ void AnimationImporter::add_fcurves_to_object(Main *bmain, AnimationImporter::~AnimationImporter() { /* free unused FCurves */ - for (std::vector<FCurve *>::iterator it = unused_curves.begin(); it != unused_curves.end(); - it++) { - BKE_fcurve_free(*it); + for (FCurve *unused_curve : unused_curves) { + BKE_fcurve_free(unused_curve); } if (!unused_curves.empty()) { @@ -2035,8 +2034,8 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, COLLADABU::Math::Matrix4 matrix; int mi = 0, mj = 0; - for (std::vector<FCurve *>::iterator it = curves.begin(); it != curves.end(); it++) { - matrix.setElement(mi, mj, evaluate_fcurve(*it, fra)); + for (FCurve *curve : curves) { + matrix.setElement(mi, mj, evaluate_fcurve(curve, fra)); mj++; if (mj == 4) { mi++; diff --git a/source/blender/io/collada/BCAnimationCurve.cpp b/source/blender/io/collada/BCAnimationCurve.cpp index 33eaf3376cd..5065accf554 100644 --- a/source/blender/io/collada/BCAnimationCurve.cpp +++ b/source/blender/io/collada/BCAnimationCurve.cpp @@ -173,8 +173,14 @@ std::string BCAnimationCurve::get_animation_name(Object *ob) const name = ""; } else { - const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones["); - name = (boneName) ? id_name(ob) + "_" + std::string(boneName) : ""; + char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones["); + if (boneName) { + name = id_name(ob) + "_" + std::string(boneName); + MEM_freeN(boneName); + } + else { + name = ""; + } } } break; diff --git a/source/blender/io/collada/BCAnimationSampler.cpp b/source/blender/io/collada/BCAnimationSampler.cpp index abc770ceef5..a6ee0b8bee6 100644 --- a/source/blender/io/collada/BCAnimationSampler.cpp +++ b/source/blender/io/collada/BCAnimationSampler.cpp @@ -448,6 +448,7 @@ void BCAnimationSampler::initialize_curves(BCAnimationCurveMap &curves, Object * char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); if (boneName) { object_type = BC_ANIMATION_TYPE_BONE; + MEM_freeN(boneName); } } diff --git a/source/blender/io/collada/BCMath.cpp b/source/blender/io/collada/BCMath.cpp index 8a3fbf3c92c..0521fda5fb1 100644 --- a/source/blender/io/collada/BCMath.cpp +++ b/source/blender/io/collada/BCMath.cpp @@ -157,20 +157,20 @@ void BCMatrix::transpose(Matrix &mat) void BCMatrix::sanitize(Matrix &mat, int precision) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - double val = (double)mat[i][j]; + for (auto &row : mat) { + for (float &cell : row) { + double val = (double)cell; val = double_round(val, precision); - mat[i][j] = (float)val; + cell = (float)val; } } } void BCMatrix::sanitize(DMatrix &mat, int precision) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - mat[i][j] = double_round(mat[i][j], precision); + for (auto &row : mat) { + for (double &cell : row) { + cell = double_round(cell, precision); } } } diff --git a/source/blender/io/collada/BlenderContext.cpp b/source/blender/io/collada/BlenderContext.cpp index 8009f10aa03..ab420e79ba7 100644 --- a/source/blender/io/collada/BlenderContext.cpp +++ b/source/blender/io/collada/BlenderContext.cpp @@ -81,8 +81,8 @@ bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer std::vector<Object *> children; bc_get_children(children, ob, view_layer); - for (int i = 0; i < children.size(); i++) { - if (bc_is_in_Export_set(export_set, children[i], view_layer)) { + for (Object *child : children) { + if (bc_is_in_Export_set(export_set, child, view_layer)) { to_export = true; break; } diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp index 52d4bbf122e..6f0d422dbe2 100644 --- a/source/blender/io/collada/ControllerExporter.cpp +++ b/source/blender/io/collada/ControllerExporter.cpp @@ -245,9 +245,9 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) if (sumw > 0.0f) { float invsumw = 1.0f / sumw; vcounts.push_back(jw.size()); - for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) { - joints.push_back((*m).first); - weights.push_back(invsumw * (*m).second); + for (auto &index_and_weight : jw) { + joints.push_back(index_and_weight.first); + weights.push_back(invsumw * index_and_weight.second); } } else { @@ -596,8 +596,8 @@ std::string ControllerExporter::add_weights_source(Mesh *me, source.prepareToAppendValues(); - for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) { - source.appendValues(*i); + for (float weight : weights) { + source.appendValues(weight); } source.finish(); @@ -638,8 +638,8 @@ void ControllerExporter::add_vertex_weights_element(const std::string &weights_s /* write deformer index - weight index pairs */ int weight_index = 0; - for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) { - weightselem.appendValues(*i, weight_index++); + for (int joint_index : joints) { + weightselem.appendValues(joint_index, weight_index++); } weightselem.finish(); diff --git a/source/blender/io/collada/DocumentExporter.cpp b/source/blender/io/collada/DocumentExporter.cpp index 241afbd4034..46dfdda4ede 100644 --- a/source/blender/io/collada/DocumentExporter.cpp +++ b/source/blender/io/collada/DocumentExporter.cpp @@ -19,9 +19,9 @@ */ #include <algorithm> /* std::find */ -#include <math.h> -#include <stdio.h> -#include <stdlib.h> +#include <cmath> +#include <cstdio> +#include <cstdlib> #include <vector> #include "COLLADASWAsset.h" @@ -121,7 +121,7 @@ extern "C" char build_hash[]; #include "MaterialExporter.h" #include "SceneExporter.h" -#include <errno.h> +#include <cerrno> char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n) { diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index b85a96d89de..10c1a90576c 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -241,10 +241,8 @@ void DocumentImporter::finish() armature_importer.fix_animation(); #endif - for (std::vector<const COLLADAFW::VisualScene *>::iterator vsit = vscenes.begin(); - vsit != vscenes.end(); - vsit++) { - const COLLADAFW::NodePointerArray &roots = (*vsit)->getRootNodes(); + for (const COLLADAFW::VisualScene *vscene : vscenes) { + const COLLADAFW::NodePointerArray &roots = vscene->getRootNodes(); for (unsigned int i = 0; i < roots.getCount(); i++) { translate_anim_recursive(roots[i], nullptr, nullptr); @@ -665,9 +663,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, goto finally; } - for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); - ++it) { - ob = *it; + for (Object *ob : *objects_done) { std::string nodename = node->getName().empty() ? node->getOriginalId() : node->getName(); BKE_libblock_rename(bmain, &ob->id, (char *)nodename.c_str()); object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob)); @@ -681,10 +677,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, /* create_constraints(et,ob); */ } - for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); - ++it) { - ob = *it; - + for (Object *ob : *objects_done) { if (read_transform) { anim_importer.read_node_transform(node, ob); /* overwrites location set earlier */ } diff --git a/source/blender/io/collada/ErrorHandler.cpp b/source/blender/io/collada/ErrorHandler.cpp index 7467d519f28..844065e3ba3 100644 --- a/source/blender/io/collada/ErrorHandler.cpp +++ b/source/blender/io/collada/ErrorHandler.cpp @@ -26,7 +26,7 @@ #include "GeneratedSaxParserParserError.h" -#include <string.h> +#include <cstring> #include "BLI_utildefines.h" diff --git a/source/blender/io/collada/ExtraHandler.cpp b/source/blender/io/collada/ExtraHandler.cpp index 8aefb321dd6..11cb75fb5e9 100644 --- a/source/blender/io/collada/ExtraHandler.cpp +++ b/source/blender/io/collada/ExtraHandler.cpp @@ -19,7 +19,7 @@ */ #include "BLI_string.h" -#include <stddef.h> +#include <cstddef> #include "ExtraHandler.h" diff --git a/source/blender/io/collada/ExtraTags.cpp b/source/blender/io/collada/ExtraTags.cpp index d8fbf96db51..8c63a21f88a 100644 --- a/source/blender/io/collada/ExtraTags.cpp +++ b/source/blender/io/collada/ExtraTags.cpp @@ -19,8 +19,8 @@ */ #include "BLI_string.h" -#include <stddef.h> -#include <stdlib.h> +#include <cstddef> +#include <cstdlib> #include <iostream> diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index bb2aabb0598..2934ea1caa6 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -973,9 +973,7 @@ static void bc_remove_materials_from_object(Object *ob, Mesh *me) std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) { std::vector<Object *> mesh_users; - for (std::vector<Object *>::iterator it = imported_objects.begin(); it != imported_objects.end(); - ++it) { - Object *ob = (*it); + for (Object *ob : imported_objects) { if (bc_is_marked(ob)) { bc_remove_mark(ob); Mesh *me = (Mesh *)ob->data; @@ -1007,9 +1005,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) */ void MeshImporter::optimize_material_assignements() { - for (std::vector<Object *>::iterator it = imported_objects.begin(); it != imported_objects.end(); - ++it) { - Object *ob = (*it); + for (Object *ob : imported_objects) { Mesh *me = (Mesh *)ob->data; if (ID_REAL_USERS(&me->id) == 1) { bc_copy_materials_to_data(ob, me); @@ -1029,8 +1025,7 @@ void MeshImporter::optimize_material_assignements() } if (can_move) { bc_copy_materials_to_data(ref_ob, me); - for (int index = 0; index < mesh_users.size(); index++) { - Object *object = mesh_users[index]; + for (Object *object : mesh_users) { bc_remove_materials_from_object(object, me); bc_remove_mark(object); } diff --git a/source/blender/io/collada/SceneExporter.cpp b/source/blender/io/collada/SceneExporter.cpp index 01c270518e9..5bbd22b8275 100644 --- a/source/blender/io/collada/SceneExporter.cpp +++ b/source/blender/io/collada/SceneExporter.cpp @@ -86,8 +86,7 @@ void SceneExporter::writeNodeList(std::vector<Object *> &child_objects, Object * * I really prefer to enforce the export of hidden * elements in an object hierarchy. When the children of * the hidden elements are exported as well. */ - for (int i = 0; i < child_objects.size(); i++) { - Object *child = child_objects[i]; + for (auto *child : child_objects) { writeNode(child); if (bc_is_marked(child)) { bc_remove_mark(child); diff --git a/source/blender/io/collada/SkinInfo.cpp b/source/blender/io/collada/SkinInfo.cpp index 19a4a4f61c2..8f6f1e467d9 100644 --- a/source/blender/io/collada/SkinInfo.cpp +++ b/source/blender/io/collada/SkinInfo.cpp @@ -21,7 +21,7 @@ #include <algorithm> #if !defined(WIN32) -# include <stdint.h> +# include <cstdint> #endif /* COLLADABU_ASSERT, may be able to remove later */ diff --git a/source/blender/io/collada/collada_internal.cpp b/source/blender/io/collada/collada_internal.cpp index 096f6a678ac..787af933e8f 100644 --- a/source/blender/io/collada/collada_internal.cpp +++ b/source/blender/io/collada/collada_internal.cpp @@ -205,7 +205,7 @@ const unsigned char translate_name_map[256] = { 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, }; -typedef std::map<std::string, std::vector<std::string>> map_string_list; +using map_string_list = std::map<std::string, std::vector<std::string>>; map_string_list global_id_map; void clear_global_id_map() @@ -280,8 +280,7 @@ std::string encode_xml(std::string xml) std::map<char, std::string>::const_iterator it; std::string encoded_xml; - for (unsigned int i = 0; i < xml.size(); i++) { - char c = xml.at(i); + for (char c : xml) { it = escape.find(c); if (it == escape.end()) { diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index c57952afcc8..ad1cc1035fb 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -379,11 +379,9 @@ void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &bc_unit, bool scale_to_scene) { - for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); - ++it) { - Object *ob = *it; + for (Object *ob : *objects_done) { if (ob->parent == nullptr) { - bc_match_scale(*it, bc_unit, scale_to_scene); + bc_match_scale(ob, bc_unit, scale_to_scene); } } } @@ -524,10 +522,8 @@ BoneExtensionManager::~BoneExtensionManager() std::map<std::string, BoneExtensionMap *>::iterator map_it; for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it) { BoneExtensionMap *extended_bones = map_it->second; - for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); - ext_it != extended_bones->end(); - ++ext_it) { - delete ext_it->second; + for (auto &extended_bone : *extended_bones) { + delete extended_bone.second; } extended_bones->clear(); delete extended_bones; @@ -1180,17 +1176,6 @@ static std::string bc_get_uvlayer_name(Mesh *me, int layer) return ""; } -std::string bc_find_bonename_in_path(std::string path, std::string probe) -{ - std::string result; - char *boneName = BLI_str_quoted_substrN(path.c_str(), probe.c_str()); - if (boneName) { - result = std::string(boneName); - MEM_freeN(boneName); - } - return result; -} - static bNodeTree *prepare_material_nodetree(Material *ma) { if (ma->nodetree == nullptr) { diff --git a/source/blender/io/collada/collada_utils.h b/source/blender/io/collada/collada_utils.h index fa65d398954..d0a5d37d6d2 100644 --- a/source/blender/io/collada/collada_utils.h +++ b/source/blender/io/collada/collada_utils.h @@ -146,8 +146,6 @@ extern void bc_bubble_sort_by_Object_name(LinkNode *export_set); extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only); extern int bc_get_active_UVLayer(Object *ob); -std::string bc_find_bonename_in_path(std::string path, std::string probe); - inline std::string bc_string_after(const std::string &s, const std::string probe) { size_t i = s.rfind(probe); diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc index fc47b024be1..eaa4d2fdde7 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc @@ -19,10 +19,10 @@ #include "IO_abstract_hierarchy_iterator.h" #include "dupli_parent_finder.hh" +#include <climits> +#include <cstdio> #include <iostream> -#include <limits.h> #include <sstream> -#include <stdio.h> #include <string> #include "BKE_anim_data.h" diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc index ad0d6820e2b..8acdba416d3 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc @@ -73,7 +73,7 @@ class TestingHierarchyIterator : public AbstractHierarchyIterator { explicit TestingHierarchyIterator(Depsgraph *depsgraph) : AbstractHierarchyIterator(depsgraph) { } - virtual ~TestingHierarchyIterator() + ~TestingHierarchyIterator() override { release_writers(); } @@ -106,13 +106,13 @@ class AbstractHierarchyIteratorTest : public BlendfileLoadingBaseTest { protected: TestingHierarchyIterator *iterator; - virtual void SetUp() + void SetUp() override { BlendfileLoadingBaseTest::SetUp(); iterator = nullptr; } - virtual void TearDown() + void TearDown() override { iterator_free(); BlendfileLoadingBaseTest::TearDown(); diff --git a/source/blender/io/common/intern/object_identifier.cc b/source/blender/io/common/intern/object_identifier.cc index a2d2d998bec..5d0b89b0630 100644 --- a/source/blender/io/common/intern/object_identifier.cc +++ b/source/blender/io/common/intern/object_identifier.cc @@ -21,7 +21,7 @@ #include "BKE_duplilist.h" extern "C" { -#include <limits.h> /* For INT_MAX. */ +#include <climits> /* For INT_MAX. */ } #include <cstring> #include <sstream> diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 9a31447dacd..17d41985f80 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -875,6 +875,10 @@ typedef enum eNlaTrack_Flag { /** track is not allowed to execute, * usually as result of tweaking being enabled (internal flag) */ NLATRACK_DISABLED = (1 << 10), + + /** This NLA track is added to an override ID, which means it is fully editable. + * Irrelevant in case the owner ID is not an override. */ + NLATRACK_OVERRIDELIBRARY_LOCAL = 1 << 16, } eNlaTrack_Flag; /* ************************************ */ diff --git a/source/blender/makesdna/DNA_brush_defaults.h b/source/blender/makesdna/DNA_brush_defaults.h index b0a35ac783e..fb726e24929 100644 --- a/source/blender/makesdna/DNA_brush_defaults.h +++ b/source/blender/makesdna/DNA_brush_defaults.h @@ -45,6 +45,7 @@ .topology_rake_factor = 0.0f, \ .crease_pinch_factor = 0.5f, \ .normal_radius_factor = 0.5f, \ + .wet_paint_radius_factor = 0.5f, \ .area_radius_factor = 0.5f, \ .disconnected_distance_max = 0.1f, \ .sculpt_plane = SCULPT_DISP_DIR_AREA, \ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 756f21321f4..7bd3c7d0117 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -402,6 +402,11 @@ typedef enum eBrushBoundaryFalloffType { BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT = 3, } eBrushBoundaryFalloffType; +typedef enum eBrushSnakeHookDeformType { + BRUSH_SNAKE_HOOK_DEFORM_FALLOFF = 0, + BRUSH_SNAKE_HOOK_DEFORM_ELASTIC = 1, +} eBrushSnakeHookDeformType; + /* Gpencilsettings.Vertex_mode */ typedef enum eGp_Vertex_Mode { /* Affect to Stroke only. */ @@ -585,6 +590,7 @@ typedef struct Brush { float normal_radius_factor; float area_radius_factor; + float wet_paint_radius_factor; float plane_trim; /** Affectable height of brush (layer height for layer tool, i.e.). */ @@ -606,6 +612,9 @@ typedef struct Brush { int elastic_deform_type; float elastic_deform_volume_preservation; + /* snake hook */ + int snake_hook_deform_type; + /* pose */ int pose_deform_type; float pose_offset; diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 70d33d9ff94..ddc1b3bd9d7 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -61,12 +61,17 @@ typedef struct bConstraint { /** Space that target should be evaluated in (only used if 1 target). */ char tarspace; - /** Constraint name, MAX_NAME. */ - char name[64]; - /* An "expand" bit for each of the constraint's (sub)panels (uiPanelDataExpansion). */ short ui_expand_flag; + /** Object to use as target for Custom Space of owner. */ + struct Object *space_object; + /** Subtarget for Custom Space of owner - pchan or vgroup name, MAX_ID_NAME-2. */ + char space_subtarget[64]; + + /** Constraint name, MAX_NAME. */ + char name[64]; + /** Amount of influence exherted by constraint (0.0-1.0). */ float enforce; /** Point along subtarget bone where the actual target is. 0=head (default for all), 1=tail. */ @@ -722,6 +727,8 @@ typedef enum eBConstraint_Flags { typedef enum eBConstraint_SpaceTypes { /** Default for all - worldspace. */ CONSTRAINT_SPACE_WORLD = 0, + /** For all - custom space. */ + CONSTRAINT_SPACE_CUSTOM = 5, /** * For objects (relative to parent/without parent influence), * for bones (along normals of bone, without parent/rest-positions). diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 85065ba35d4..6a91f4857b4 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -47,8 +47,31 @@ typedef enum eViewLayerEEVEEPassType { EEVEE_RENDER_PASS_SHADOW = (1 << 12), EEVEE_RENDER_PASS_AO = (1 << 13), EEVEE_RENDER_PASS_BLOOM = (1 << 14), + EEVEE_RENDER_PASS_AOV = (1 << 15), + EEVEE_RENDER_PASS_CRYPTOMATTE = (1 << 16), } eViewLayerEEVEEPassType; -#define EEVEE_RENDER_PASS_MAX_BIT 15 +#define EEVEE_RENDER_PASS_MAX_BIT 17 + +/* #ViewLayerAOV.type */ +typedef enum eViewLayerAOVType { + AOV_TYPE_VALUE = 0, + AOV_TYPE_COLOR = 1, +} eViewLayerAOVType; + +/* #ViewLayerAOV.flag */ +typedef enum eViewLayerAOVFlag { + AOV_CONFLICT = (1 << 0), +} eViewLayerAOVFlag; + +/* #ViewLayer.cryptomatte_flag */ +typedef enum eViewLayerCryptomatteFlags { + VIEW_LAYER_CRYPTOMATTE_OBJECT = (1 << 0), + VIEW_LAYER_CRYPTOMATTE_MATERIAL = (1 << 1), + VIEW_LAYER_CRYPTOMATTE_ASSET = (1 << 2), + VIEW_LAYER_CRYPTOMATTE_ACCURATE = (1 << 3), +} eViewLayerCryptomatteFlags; +#define VIEW_LAYER_CRYPTOMATTE_ALL \ + (VIEW_LAYER_CRYPTOMATTE_OBJECT | VIEW_LAYER_CRYPTOMATTE_MATERIAL | VIEW_LAYER_CRYPTOMATTE_ASSET) typedef struct Base { struct Base *next, *prev; @@ -104,6 +127,17 @@ typedef struct ViewLayerEEVEE { int _pad[1]; } ViewLayerEEVEE; +/* AOV Renderpass definition. */ +typedef struct ViewLayerAOV { + struct ViewLayerAOV *next, *prev; + + /* Name of the AOV */ + char name[64]; + int flag; + /* Type of AOV (color/value) + * matches `eViewLayerAOVType` */ + int type; +} ViewLayerAOV; typedef struct ViewLayer { struct ViewLayer *next, *prev; /** MAX_NAME. */ @@ -127,6 +161,10 @@ typedef struct ViewLayer { /** Pass_xor has to be after passflag. */ int passflag; float pass_alpha_threshold; + short cryptomatte_flag; + short cryptomatte_levels; + char _pad1[4]; + int samples; struct Material *mat_override; @@ -136,6 +174,10 @@ typedef struct ViewLayer { struct FreestyleConfig freestyle_config; struct ViewLayerEEVEE eevee; + /* List containing the `ViewLayerAOV`s */ + ListBase aovs; + ViewLayerAOV *active_aov; + /* Runtime data */ /** ViewLayerEngineData. */ ListBase drawdata; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index a822a6723fa..04fbc030ed9 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -220,6 +220,8 @@ typedef struct Mesh { float remesh_voxel_adaptivity; char remesh_mode; + /* Indicates the symmetry that a mesh has, according to the artist, so that tools can + * consistently ensure that this symmetry is maintained. */ char symmetry; char _pad1[2]; diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index b2f8d845815..780115a31be 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -340,7 +340,7 @@ enum { }; /** - * \note While alpha is currently is not in the view-port, + * \note While alpha is not currently in the 3D Viewport, * this may eventually be added back, keep this value set to 255. */ typedef struct MLoopCol { diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index f73f43ddade..e122d50cba8 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -801,6 +801,7 @@ #define _DNA_DEFAULT_WeldModifierData \ { \ .merge_dist = 0.001f, \ + .mode = MOD_WELD_MODE_ALL, \ .defgrp_name = "", \ } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index edb0a4439d6..03cf4aca963 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1588,7 +1588,7 @@ typedef struct WeightVGProximityModifierData { /** Name of vertex group to modify/weight. MAX_VGROUP_NAME. */ char defgrp_name[64]; - + /* Mapping stuff. */ /** The custom mapping curve!. */ struct CurveMapping *cmap_curve; @@ -2004,7 +2004,8 @@ typedef struct WeldModifierData { /* Name of vertex group to use to mask, MAX_VGROUP_NAME. */ char defgrp_name[64]; - short flag; + char mode; + char flag; char _pad[2]; } WeldModifierData; @@ -2013,6 +2014,12 @@ enum { MOD_WELD_INVERT_VGROUP = (1 << 0), }; +/* #WeldModifierData.mode */ +enum { + MOD_WELD_MODE_ALL = 0, + MOD_WELD_MODE_CONNECTED = 1, +}; + typedef struct DataTransferModifierData { ModifierData modifier; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 29c83d2d4ed..13f8b11352a 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1464,6 +1464,13 @@ typedef enum GeometryNodeUseAttributeFlag { GEO_NODE_USE_ATTRIBUTE_B = (1 << 1), } GeometryNodeUseAttributeFlag; +typedef enum GeometryNodeAttributeInputMode { + GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE = 0, + GEO_NODE_ATTRIBUTE_INPUT_FLOAT = 1, + GEO_NODE_ATTRIBUTE_INPUT_VECTOR = 2, + GEO_NODE_ATTRIBUTE_INPUT_COLOR = 3, +} GeometryNodeAttributeInputMode; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h index cc376c0cebf..d561b489ae4 100644 --- a/source/blender/makesdna/DNA_outliner_types.h +++ b/source/blender/makesdna/DNA_outliner_types.h @@ -66,7 +66,9 @@ enum { /* Needed because outliner-only elements can be active */ TSE_ACTIVE = (1 << 9), /* TSE_ACTIVE_WALK = (1 << 10), */ /* Unused */ + TSE_HIGHLIGHTED_ICON = (1 << 11), TSE_DRAG_ANY = (TSE_DRAG_INTO | TSE_DRAG_BEFORE | TSE_DRAG_AFTER), + TSE_HIGHLIGHTED_ANY = (TSE_HIGHLIGHTED | TSE_HIGHLIGHTED_ICON), }; /* TreeStoreElem->types */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index cbf6e900416..6fd112628a1 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1,4 +1,4 @@ -/* +/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -279,11 +279,6 @@ typedef struct SpaceOutliner { char show_restrict_flags; short filter_id_type; - /** - * Pointers to treestore elements, grouped by (id, type, nr) - * in hashtable for faster searching */ - void *treehash; - SpaceOutliner_Runtime *runtime; } SpaceOutliner; @@ -703,7 +698,7 @@ typedef struct FileSelectParams { /* short */ /** XXXXX for now store type here, should be moved to the operator. */ - short type; + short type; /* eFileSelectType */ /** Settings for filter, hiding dots files. */ short flag; /** Sort order. */ @@ -812,12 +807,14 @@ enum eFileDetails { #define FILE_MAX_LIBEXTRA (FILE_MAX + MAX_ID_NAME) /* filesel types */ -#define FILE_UNIX 8 -#define FILE_BLENDER 8 /* don't display relative paths */ -#define FILE_SPECIAL 9 - -#define FILE_LOADLIB 1 -#define FILE_MAIN 2 +typedef enum eFileSelectType { + FILE_LOADLIB = 1, + FILE_MAIN = 2, + + FILE_UNIX = 8, + FILE_BLENDER = 8, /* don't display relative paths */ + FILE_SPECIAL = 9, +} eFileSelectType; /* filesel op property -> action */ typedef enum eFileSel_Action { diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h index 6f0820ff62c..bc1a71102da 100644 --- a/source/blender/makesdna/DNA_vfont_types.h +++ b/source/blender/makesdna/DNA_vfont_types.h @@ -20,7 +20,7 @@ /** \file * \ingroup DNA * - * Vector Fonts used for text in the 3D view-port + * Vector Fonts used for text in the 3D Viewport * (unrelated to text used to render the GUI). */ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 9a233878840..b8e2256c3c6 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -192,6 +192,7 @@ typedef struct View3DShading { /* Render pass displayed in the viewport. Is an `eScenePassType` where one bit is set */ int render_pass; + char aov_name[64]; struct IDProperty *prop; void *_pad2; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index f51202348b5..a581edcb04b 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -60,6 +60,7 @@ extern StructRNA RNA_AnimData; extern StructRNA RNA_AnimViz; extern StructRNA RNA_AnimVizMotionPaths; extern StructRNA RNA_AnyType; +extern StructRNA RNA_AOV; extern StructRNA RNA_Area; extern StructRNA RNA_AreaLight; extern StructRNA RNA_Armature; diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index cb316e56a68..d0e0b69a8d5 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -1188,7 +1188,7 @@ static void rna_def_image_preview(BlenderRNA *brna) prop = RNA_def_property(srna, "image_pixels", PROP_INT, PROP_NONE); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_multi_array(prop, 1, NULL); - RNA_def_property_ui_text(prop, "Image Pixels", "Image pixels, as bytes (always RGBA 32bits)"); + RNA_def_property_ui_text(prop, "Image Pixels", "Image pixels, as bytes (always 32-bit RGBA)"); RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_image_pixels_get_length"); RNA_def_property_int_funcs( prop, "rna_ImagePreview_image_pixels_get", "rna_ImagePreview_image_pixels_set", NULL); @@ -1221,7 +1221,7 @@ static void rna_def_image_preview(BlenderRNA *brna) prop = RNA_def_property(srna, "icon_pixels", PROP_INT, PROP_NONE); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_multi_array(prop, 1, NULL); - RNA_def_property_ui_text(prop, "Icon Pixels", "Icon pixels, as bytes (always RGBA 32bits)"); + RNA_def_property_ui_text(prop, "Icon Pixels", "Icon pixels, as bytes (always 32-bit RGBA)"); RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_icon_pixels_get_length"); RNA_def_property_int_funcs( prop, "rna_ImagePreview_icon_pixels_get", "rna_ImagePreview_icon_pixels_set", NULL); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 4991f34c3f6..6586cfc7969 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -31,6 +31,7 @@ #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" +#include "BLI_alloca.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" #include "BLI_ghash.h" @@ -4957,14 +4958,10 @@ PointerRNA rna_array_lookup_int( static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket) { const char *p; - char *buf; - char quote = '\0'; - int i, j, len, escape; - - len = 0; + int len = 0; if (bracket) { - /* get data between [], check escaping ] with \] */ + /* get data between [], check escaping quotes and back-slashes with #BLI_str_unescape. */ if (**path == '[') { (*path)++; } @@ -4974,33 +4971,24 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int p = *path; - /* 2 kinds of lookups now, quoted or unquoted */ - quote = *p; - - if (quote != '"') { /* " - this comment is hack for Aligorith's text editor's sanity */ - quote = 0; - } - - if (quote == 0) { + /* 2 kinds of look-ups now, quoted or unquoted. */ + if (*p != '"') { while (*p && (*p != ']')) { len++; p++; } } else { - escape = 0; - /* skip the first quote */ - len++; - p++; - while (*p && (*p != quote || escape)) { - escape = (*p == '\\'); - len++; - p++; + const char *p_end = BLI_str_escape_find_quote(p + 1); + if (p_end == NULL) { + /* No Matching quote. */ + return NULL; } + /* Skip the last quoted char to get the `]`. */ + p_end += 1; - /* skip the last quoted char to get the ']' */ - len++; - p++; + len += (p_end - p); + p = p_end; } if (*p != ']') { @@ -5022,25 +5010,13 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int return NULL; } - /* try to use fixed buffer if possible */ - if (len + 1 < fixedlen) { - buf = fixedbuf; - } - else { - buf = MEM_mallocN(sizeof(char) * (len + 1), "rna_path_token"); - } + /* Try to use fixed buffer if possible. */ + char *buf = (len + 1 < fixedlen) ? fixedbuf : MEM_mallocN(sizeof(char) * (len + 1), __func__); /* copy string, taking into account escaped ] */ if (bracket) { - for (p = *path, i = 0, j = 0; i < len; i++, p++) { - if (*p == '\\' && *(p + 1) == quote) { - } - else { - buf[j++] = *p; - } - } - - buf[j] = 0; + BLI_str_unescape(buf, *path, len); + p = (*path) + len; } else { memcpy(buf, *path, sizeof(char) * len); @@ -5552,8 +5528,7 @@ char *RNA_path_append( const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey) { DynStr *dynstr; - const char *s; - char appendstr[128], *result; + char *result; dynstr = BLI_dynstr_new(); @@ -5572,22 +5547,15 @@ char *RNA_path_append( BLI_dynstr_append(dynstr, "["); if (strkey) { + const int strkey_esc_max_size = (strlen(strkey) * 2) + 1; + char *strkey_esc = BLI_array_alloca(strkey_esc, strkey_esc_max_size); + BLI_str_escape(strkey_esc, strkey, strkey_esc_max_size); BLI_dynstr_append(dynstr, "\""); - for (s = strkey; *s; s++) { - if (*s == '[') { - appendstr[0] = '\\'; - appendstr[1] = *s; - appendstr[2] = 0; - } - else { - appendstr[0] = *s; - appendstr[1] = 0; - } - BLI_dynstr_append(dynstr, appendstr); - } + BLI_dynstr_append(dynstr, strkey_esc); BLI_dynstr_append(dynstr, "\""); } else { + char appendstr[128]; BLI_snprintf(appendstr, sizeof(appendstr), "%d", intkey); BLI_dynstr_append(dynstr, appendstr); } @@ -6008,7 +5976,7 @@ char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, } else { char propname_esc[MAX_IDPROP_NAME * 2]; - BLI_strescape(propname_esc, propname, sizeof(propname_esc)); + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); path = BLI_sprintfN("%s[\"%s\"]%s", ptrpath, propname_esc, index_str); } MEM_freeN(ptrpath); @@ -6019,7 +5987,7 @@ char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, } else { char propname_esc[MAX_IDPROP_NAME * 2]; - BLI_strescape(propname_esc, propname, sizeof(propname_esc)); + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str); } } @@ -6105,7 +6073,7 @@ char *RNA_path_full_ID_py(Main *bmain, ID *id) char id_esc[(sizeof(id->name) - 2) * 2]; - BLI_strescape(id_esc, id->name + 2, sizeof(id_esc)); + BLI_str_escape(id_esc, id->name + 2, sizeof(id_esc)); return BLI_sprintfN("bpy.data.%s[\"%s\"]%s%s", BKE_idtype_idcode_to_name_plural(GS(id->name)), @@ -7059,7 +7027,7 @@ char *RNA_property_as_string( buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_property_as_string"); buf_esc = MEM_mallocN(sizeof(char) * (length * 2 + 1), "RNA_property_as_string esc"); RNA_property_string_get(ptr, prop, buf); - BLI_strescape(buf_esc, buf, length * 2 + 1); + BLI_str_escape(buf_esc, buf, length * 2 + 1); MEM_freeN(buf); BLI_dynstr_appendf(dynstr, "\"%s\"", buf_esc); MEM_freeN(buf_esc); diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c index 4bbbf5f01da..c0b2de268cd 100644 --- a/source/blender/makesrna/intern/rna_access_compare_override.c +++ b/source/blender/makesrna/intern/rna_access_compare_override.c @@ -23,7 +23,9 @@ #include "MEM_guardedalloc.h" #include "DNA_ID.h" +#include "DNA_anim_types.h" #include "DNA_constraint_types.h" +#include "DNA_gpencil_modifier_types.h" #include "DNA_key_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" @@ -77,6 +79,18 @@ bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop) return true; } } + else if (RNA_struct_is_a(ptr->type, &RNA_GpencilModifier)) { + GpencilModifierData *gp_mod = ptr->data; + if (gp_mod->flag & eGpencilModifierFlag_OverrideLibrary_Local) { + return true; + } + } + else if (RNA_struct_is_a(ptr->type, &RNA_NlaTrack)) { + NlaTrack *nla_track = ptr->data; + if (nla_track->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) { + return true; + } + } /* If this is a RNA-defined property (real or 'virtual' IDProp), * we want to use RNA prop flag. */ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 0a9f2ff4819..10f86fe2671 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -587,7 +587,7 @@ static void rna_KeyingSet_paths_clear(KeyingSet *keyingset, ReportList *reports) /* needs wrapper function to push notifier */ static NlaTrack *rna_NlaTrack_new(ID *id, AnimData *adt, Main *bmain, bContext *C, NlaTrack *track) { - NlaTrack *new_track = BKE_nlatrack_add(adt, track); + NlaTrack *new_track = BKE_nlatrack_add(adt, track, ID_IS_OVERRIDE_LIBRARY(id)); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL); @@ -732,6 +732,60 @@ bool rna_AnimaData_override_apply(Main *UNUSED(bmain), return false; } +bool rna_NLA_tracks_override_apply(Main *bmain, + PointerRNA *ptr_dst, + PointerRNA *ptr_src, + PointerRNA *UNUSED(ptr_storage), + PropertyRNA *UNUSED(prop_dst), + PropertyRNA *UNUSED(prop_src), + PropertyRNA *UNUSED(prop_storage), + const int UNUSED(len_dst), + const int UNUSED(len_src), + const int UNUSED(len_storage), + PointerRNA *UNUSED(ptr_item_dst), + PointerRNA *UNUSED(ptr_item_src), + PointerRNA *UNUSED(ptr_item_storage), + IDOverrideLibraryPropertyOperation *opop) +{ + BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_INSERT_AFTER && + "Unsupported RNA override operation on constraints collection"); + + AnimData *anim_data_dst = (AnimData *)ptr_dst->data; + AnimData *anim_data_src = (AnimData *)ptr_src->data; + + /* Remember that insertion operations are defined and stored in correct order, which means that + * even if we insert several items in a row, we always insert first one, then second one, etc. + * So we should always find 'anchor' track in both _src *and* _dst. */ + NlaTrack *nla_track_anchor = NULL; +# if 0 + /* This is not working so well with index-based insertion, especially in case some tracks get + * added to lib linked data. So we simply add locale tracks at the end of the list always, order + * of override operations should ensure order of local tracks is preserved properly. */ + if (opop->subitem_local_index >= 0) { + nla_track_anchor = BLI_findlink(&anim_data_dst->nla_tracks, opop->subitem_local_index); + } + /* Otherwise we just insert in first position. */ +# else + nla_track_anchor = anim_data_dst->nla_tracks.last; +# endif + + NlaTrack *nla_track_src = NULL; + if (opop->subitem_local_index >= 0) { + nla_track_src = BLI_findlink(&anim_data_src->nla_tracks, opop->subitem_local_index); + } + nla_track_src = nla_track_src ? nla_track_src->next : anim_data_src->nla_tracks.first; + + BLI_assert(nla_track_src != NULL); + + NlaTrack *nla_track_dst = BKE_nlatrack_copy(bmain, nla_track_src, true, 0); + + /* This handles NULL anchor as expected by adding at head of list. */ + BLI_insertlinkafter(&anim_data_dst->nla_tracks, nla_track_anchor, nla_track_dst); + + // printf("%s: We inserted a NLA Track...\n", __func__); + return true; +} + #else /* helper function for Keying Set -> keying settings */ @@ -1251,14 +1305,19 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "nla_tracks", NULL); RNA_def_property_struct_type(prop, "NlaTrack"); RNA_def_property_ui_text(prop, "NLA Tracks", "NLA Tracks (i.e. Animation Layers)"); + RNA_def_property_override_flag(prop, + PROPOVERRIDE_OVERRIDABLE_LIBRARY | + PROPOVERRIDE_LIBRARY_INSERTION | PROPOVERRIDE_NO_PROP_NAME); + RNA_def_property_override_funcs(prop, NULL, NULL, "rna_NLA_tracks_override_apply"); rna_api_animdata_nla_tracks(brna, prop); + RNA_define_lib_overridable(true); + /* Active Action */ prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); /* this flag as well as the dynamic test must be defined for this to be editable... */ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_pointer_funcs( prop, NULL, "rna_AnimData_action_set", NULL, "rna_Action_id_poll"); RNA_def_property_editable_func(prop, "rna_AnimData_action_editable"); @@ -1297,11 +1356,14 @@ static void rna_def_animdata(BlenderRNA *brna) prop = RNA_def_property(srna, "drivers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "drivers", NULL); RNA_def_property_struct_type(prop, "FCurve"); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Drivers", "The Drivers/Expressions for this data-block"); + RNA_define_lib_overridable(false); + rna_api_animdata_drivers(brna, prop); + RNA_define_lib_overridable(true); + /* General Settings */ prop = RNA_def_property(srna, "use_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ADT_NLA_EVAL_OFF); @@ -1322,6 +1384,8 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pin in Graph Editor", ""); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + RNA_define_lib_overridable(false); + /* Animation Data API */ RNA_api_animdata(srna); } diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index d586f222203..1628c978c30 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -245,7 +245,7 @@ static char *rna_Bone_path(PointerRNA *ptr) Bone *bone = (Bone *)ptr->data; char name_esc[sizeof(bone->name) * 2]; - BLI_strescape(name_esc, bone->name, sizeof(name_esc)); + BLI_str_escape(name_esc, bone->name, sizeof(name_esc)); /* special exception for trying to get the path where ID-block is Object * - this will be assumed to be from a Pose Bone... diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index ad615026343..95f6340174a 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -38,10 +38,10 @@ #include "WM_types.h" const EnumPropertyItem rna_enum_attribute_type_items[] = { - {CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating point value"}, - {CD_PROP_INT32, "INT", 0, "Integer", "32 bit integer"}, - {CD_PROP_FLOAT3, "FLOAT_VECTOR", 0, "Vector", "3D vector with floating point values"}, - {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Float Color", "RGBA color with floating point precisions"}, + {CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating-point value"}, + {CD_PROP_INT32, "INT", 0, "Integer", "32-bit integer"}, + {CD_PROP_FLOAT3, "FLOAT_VECTOR", 0, "Vector", "3D vector with floating-point values"}, + {CD_PROP_COLOR, "FLOAT_COLOR", 0, "Float Color", "RGBA color with floating-point precisions"}, {CD_MLOOPCOL, "BYTE_COLOR", 0, "Byte Color", "RGBA color with 8-bit precision"}, {CD_PROP_STRING, "STRING", 0, "String", "Text string"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 33d69f6f912..3e3452af713 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -183,7 +183,7 @@ static char *rna_BoidRule_path(PointerRNA *ptr) BoidRule *rule = (BoidRule *)ptr->data; char name_esc[sizeof(rule->name) * 2]; - BLI_strescape(name_esc, rule->name, sizeof(name_esc)); + BLI_str_escape(name_esc, rule->name, sizeof(name_esc)); return BLI_sprintfN("rules[\"%s\"]", name_esc); /* XXX not unique */ } diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 1e5309e5869..b5ce7976fd8 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -2072,6 +2072,20 @@ static void rna_def_brush(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem brush_snake_hook_deform_type_items[] = { + {BRUSH_SNAKE_HOOK_DEFORM_FALLOFF, + "FALLOFF", + 0, + "Radius Falloff", + "Applies the brush falloff in the tip of the brush"}, + {BRUSH_SNAKE_HOOK_DEFORM_ELASTIC, + "ELASTIC", + 0, + "Elastic", + "Modifies the entire mesh using elastic deform"}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem brush_cloth_deform_type_items[] = { {BRUSH_CLOTH_DEFORM_DRAG, "DRAG", 0, "Drag", ""}, {BRUSH_CLOTH_DEFORM_PUSH, "PUSH", 0, "Push", ""}, @@ -2309,6 +2323,11 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "snake_hook_deform_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, brush_snake_hook_deform_type_items); + RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "cloth_deform_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, brush_cloth_deform_type_items); RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush"); @@ -2854,6 +2873,16 @@ static void rna_def_brush(BlenderRNA *brna) "used to sample the area center"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "wet_paint_radius_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "wet_paint_radius_factor"); + RNA_def_property_range(prop, 0.0f, 2.0f); + RNA_def_property_ui_range(prop, 0.0f, 2.0f, 0.001, 3); + RNA_def_property_ui_text(prop, + "Wet Paint Radius", + "Ratio between the brush radius and the radius that is going to be " + "used to sample the color to blend in wet paint"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "stencil_pos", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "stencil_pos"); RNA_def_property_array(prop, 2); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 27318494428..b0e0b577629 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -439,7 +439,7 @@ static char *rna_ClothSettings_path(PointerRNA *ptr) if (md) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc); } else { @@ -454,7 +454,7 @@ static char *rna_ClothCollisionSettings_path(PointerRNA *ptr) if (md) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].collision_settings", name_esc); } else { diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 1c84be5907b..0b3dc2a3504 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -200,6 +200,12 @@ static const EnumPropertyItem target_space_pchan_items[] = { "World Space", "The transformation of the target is evaluated relative to the world " "coordinate system"}, + {CONSTRAINT_SPACE_CUSTOM, + "CUSTOM", + 0, + "Custom Space", + "The transformation of the target is evaluated relative to a custom object/bone/vertex " + "group"}, {CONSTRAINT_SPACE_POSE, "POSE", 0, @@ -227,6 +233,11 @@ static const EnumPropertyItem owner_space_pchan_items[] = { 0, "World Space", "The constraint is applied relative to the world coordinate system"}, + {CONSTRAINT_SPACE_CUSTOM, + "CUSTOM", + 0, + "Custom Space", + "The constraint is applied in local space of a custom object/bone/vertex group"}, {CONSTRAINT_SPACE_POSE, "POSE", 0, @@ -275,6 +286,12 @@ static const EnumPropertyItem space_object_items[] = { 0, "World Space", "The transformation of the target is evaluated relative to the world coordinate system"}, + {CONSTRAINT_SPACE_CUSTOM, + "CUSTOM", + 0, + "Custom Space", + "The transformation of the target is evaluated relative to a custom object/bone/vertex " + "group"}, {CONSTRAINT_SPACE_LOCAL, "LOCAL", 0, @@ -416,13 +433,13 @@ static char *rna_Constraint_do_compute_path(Object *ob, bConstraint *con) if (pchan) { char name_esc_pchan[sizeof(pchan->name) * 2]; char name_esc_const[sizeof(con->name) * 2]; - BLI_strescape(name_esc_pchan, pchan->name, sizeof(name_esc_pchan)); - BLI_strescape(name_esc_const, con->name, sizeof(name_esc_const)); + BLI_str_escape(name_esc_pchan, pchan->name, sizeof(name_esc_pchan)); + BLI_str_escape(name_esc_const, con->name, sizeof(name_esc_const)); return BLI_sprintfN("pose.bones[\"%s\"].constraints[\"%s\"]", name_esc_pchan, name_esc_const); } else { char name_esc_const[sizeof(con->name) * 2]; - BLI_strescape(name_esc_const, con->name, sizeof(name_esc_const)); + BLI_str_escape(name_esc_const, con->name, sizeof(name_esc_const)); return BLI_sprintfN("constraints[\"%s\"]", name_esc_const); } } @@ -3398,6 +3415,18 @@ void RNA_def_constraint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Target Space", "Space that target is evaluated in"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "space_object", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "space_object"); + RNA_def_property_ui_text(prop, "Object", "Object for Custom Space"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop = RNA_def_property(srna, "space_subtarget", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "space_subtarget"); + RNA_def_property_ui_text(prop, "Sub-Target", "Armature bone, mesh or lattice vertex group, ..."); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); + /* flags */ prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_OFF); diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index f86cfb674d1..7c4762aa3a3 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -57,7 +57,7 @@ static char *rna_DynamicPaintCanvasSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->pmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].canvas_settings", name_esc); } @@ -67,7 +67,7 @@ static char *rna_DynamicPaintBrushSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->pmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].brush_settings", name_esc); } @@ -78,8 +78,8 @@ static char *rna_DynamicPaintSurface_path(PointerRNA *ptr) char name_esc[sizeof(md->name) * 2]; char name_esc_surface[sizeof(surface->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); - BLI_strescape(name_esc_surface, surface->name, sizeof(name_esc_surface)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc_surface, surface->name, sizeof(name_esc_surface)); return BLI_sprintfN( "modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"]", name_esc, name_esc_surface); } diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 02ae71e3b3d..90f5434bea0 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -872,7 +872,7 @@ static char *rna_FluidDomainSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->fmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].domain_settings", name_esc); } @@ -882,7 +882,7 @@ static char *rna_FluidFlowSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->fmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].flow_settings", name_esc); } @@ -892,7 +892,7 @@ static char *rna_FluidEffectorSettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)settings->fmd; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].effector_settings", name_esc); } diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 603bd51b2d9..7be9d14b1d1 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -308,7 +308,7 @@ static char *rna_GPencilLayer_path(PointerRNA *ptr) bGPDlayer *gpl = (bGPDlayer *)ptr->data; char name_esc[sizeof(gpl->info) * 2]; - BLI_strescape(name_esc, gpl->info, sizeof(name_esc)); + BLI_str_escape(name_esc, gpl->info, sizeof(name_esc)); return BLI_sprintfN("layers[\"%s\"]", name_esc); } @@ -406,8 +406,8 @@ static char *rna_GPencilLayerMask_path(PointerRNA *ptr) char name_layer[sizeof(gpl->info) * 2]; char name_mask[sizeof(mask->name) * 2]; - BLI_strescape(name_layer, gpl->info, sizeof(name_layer)); - BLI_strescape(name_mask, mask->name, sizeof(name_mask)); + BLI_str_escape(name_layer, gpl->info, sizeof(name_layer)); + BLI_str_escape(name_mask, mask->name, sizeof(name_mask)); return BLI_sprintfN("layers[\"%s\"].mask_layers[\"%s\"]", name_layer, name_mask); } diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 19264aeebd7..5f131de6a40 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -276,7 +276,7 @@ static char *rna_GpencilModifier_path(PointerRNA *ptr) GpencilModifierData *gmd = ptr->data; char name_esc[sizeof(gmd->name) * 2]; - BLI_strescape(name_esc, gmd->name, sizeof(name_esc)); + BLI_str_escape(name_esc, gmd->name, sizeof(name_esc)); return BLI_sprintfN("grease_pencil_modifiers[\"%s\"]", name_esc); } @@ -781,7 +781,7 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna) prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "factor"); RNA_def_property_range(prop, 0, 100.0); - RNA_def_property_ui_range(prop, 0, 100.0, 1.0f, 3); + RNA_def_property_ui_range(prop, 0, 5.0f, 1.0f, 3); RNA_def_property_ui_text(prop, "Factor", "Factor of Simplify"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 504a4a6bdf3..2373045d95a 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -1136,7 +1136,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_HIGH_BITDEPTH); RNA_def_property_ui_text(prop, "Half Float Precision", - "Use 16bits per channel to lower the memory usage during rendering"); + "Use 16 bits per channel to lower the memory usage during rendering"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_gpu_texture_update"); /* multiview */ diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 31e920a6799..1c6f83efd65 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -345,6 +345,10 @@ void rna_ViewLayer_material_override_update(struct Main *bmain, void rna_ViewLayer_pass_update(struct Main *bmain, struct Scene *activescene, struct PointerRNA *ptr); +void rna_ViewLayer_active_aov_index_range( + PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax); +int rna_ViewLayer_active_aov_index_get(PointerRNA *ptr); +void rna_ViewLayer_active_aov_index_set(PointerRNA *ptr, int value); /* named internal so as not to conflict with obj.update() rna func */ void rna_Object_internal_update_data(struct Main *bmain, diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index e0005766c48..3b9fc970072 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -676,7 +676,7 @@ static char *rna_ShapeKey_path(PointerRNA *ptr) ID *id = ptr->owner_id; char name_esc[sizeof(kb->name) * 2]; - BLI_strescape(name_esc, kb->name, sizeof(name_esc)); + BLI_str_escape(name_esc, kb->name, sizeof(name_esc)); if ((id) && (GS(id->name) != ID_KE)) { return BLI_sprintfN("shape_keys.key_blocks[\"%s\"]", name_esc); @@ -774,7 +774,7 @@ static char *rna_ShapeKeyPoint_path(PointerRNA *ptr) index = rna_ShapeKey_curve_find_index(key, index); } - BLI_strescape(name_esc_kb, kb->name, sizeof(name_esc_kb)); + BLI_str_escape(name_esc_kb, kb->name, sizeof(name_esc_kb)); if (GS(id->name) == ID_KE) { return BLI_sprintfN("key_blocks[\"%s\"].data[%d]", name_esc_kb, index); diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index c7a53757296..afe69c37eef 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -115,7 +115,7 @@ static char *rna_ViewLayer_path(PointerRNA *ptr) ViewLayer *srl = (ViewLayer *)ptr->data; char name_esc[sizeof(srl->name) * 2]; - BLI_strescape(name_esc, srl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, srl->name, sizeof(name_esc)); return BLI_sprintfN("view_layers[\"%s\"]", name_esc); } @@ -152,6 +152,18 @@ static void rna_ViewLayer_update_render_passes(ID *id) if (scene->nodetree) { ntreeCompositUpdateRLayers(scene->nodetree); } + + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + if (engine_type->update_render_passes) { + RenderEngine *engine = RE_engine_create(engine_type); + if (engine) { + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + BKE_view_layer_verify_aov(engine, scene, view_layer); + } + } + RE_engine_free(engine); + engine = NULL; + } } static PointerRNA rna_ViewLayer_objects_get(CollectionPropertyIterator *iter) diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 03442748854..ca97f2c9a55 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -257,7 +257,7 @@ static char *rna_LineStyle_color_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("color_modifiers[\"%s\"]", name_esc); } @@ -265,7 +265,7 @@ static char *rna_LineStyle_alpha_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("alpha_modifiers[\"%s\"]", name_esc); } @@ -273,7 +273,7 @@ static char *rna_LineStyle_thickness_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("thickness_modifiers[\"%s\"]", name_esc); } @@ -281,7 +281,7 @@ static char *rna_LineStyle_geometry_modifier_path(PointerRNA *ptr) { LineStyleModifier *m = (LineStyleModifier *)ptr->data; char name_esc[sizeof(m->name) * 2]; - BLI_strescape(name_esc, m->name, sizeof(name_esc)); + BLI_str_escape(name_esc, m->name, sizeof(name_esc)); return BLI_sprintfN("geometry_modifiers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index cfbaf0cccf5..db3e5195c79 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -182,7 +182,7 @@ static char *rna_MaskLayer_path(PointerRNA *ptr) { MaskLayer *masklay = (MaskLayer *)ptr->data; char name_esc[sizeof(masklay->name) * 2]; - BLI_strescape(name_esc, masklay->name, sizeof(name_esc)); + BLI_str_escape(name_esc, masklay->name, sizeof(name_esc)); return BLI_sprintfN("layers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 4afb17fe0b9..2bbfee2dcef 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -670,7 +670,7 @@ static char *rna_MeshUVLoopLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("uv_layers[\"%s\"]", name_esc); } @@ -913,7 +913,7 @@ static char *rna_MeshSkinVertexLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("skin_vertices[\"%s\"]", name_esc); } @@ -945,7 +945,7 @@ static char *rna_MeshPaintMaskLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_paint_masks[\"%s\"]", name_esc); } @@ -979,7 +979,7 @@ static char *rna_MeshFaceMapLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("face_maps[\"%s\"]", name_esc); } @@ -1189,7 +1189,7 @@ static char *rna_VertCustomData_data_path(PointerRNA *ptr, const char *collectio b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type); if (b >= 0 && b < totvert) { char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b); } } @@ -1210,7 +1210,7 @@ static char *rna_PolyCustomData_data_path(PointerRNA *ptr, const char *collectio b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type); if (b >= 0 && b < totpoly) { char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b); } } @@ -1231,7 +1231,7 @@ static char *rna_LoopCustomData_data_path(PointerRNA *ptr, const char *collectio b = ((char *)ptr->data - ((char *)cdl->data)) / CustomData_sizeof(type); if (b >= 0 && b < totloop) { char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("%s[\"%s\"].data[%d]", collection, name_esc, b); } } @@ -1249,7 +1249,7 @@ static char *rna_MeshLoopColorLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_colors[\"%s\"]", name_esc); } @@ -1262,7 +1262,7 @@ static char *rna_MeshVertColorLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("sculpt_vertex_colors[\"%s\"]", name_esc); } @@ -1276,14 +1276,14 @@ static char *rna_MeshVertexFloatPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_float_layers[\"%s\"]", name_esc); } static char *rna_MeshPolygonFloatPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("polygon_float_layers[\"%s\"]", name_esc); } @@ -1327,14 +1327,14 @@ static char *rna_MeshVertexIntPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_int_layers[\"%s\"]", name_esc); } static char *rna_MeshPolygonIntPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("polygon_int_layers[\"%s\"]", name_esc); } @@ -1378,14 +1378,14 @@ static char *rna_MeshVertexStringPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("vertex_string_layers[\"%s\"]", name_esc); } static char *rna_MeshPolygonStringPropertyLayer_path(PointerRNA *ptr) { CustomDataLayer *cdl = ptr->data; char name_esc[sizeof(cdl->name) * 2]; - BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + BLI_str_escape(name_esc, cdl->name, sizeof(name_esc)); return BLI_sprintfN("polygon_string_layers[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index f0836ae59ad..d91b6ea19f7 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -660,7 +660,7 @@ static char *rna_Modifier_path(PointerRNA *ptr) ModifierData *md = ptr->data; char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"]", name_esc); } @@ -6231,6 +6231,12 @@ static void rna_def_modifier_weld(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static const EnumPropertyItem mode_items[] = { + {MOD_WELD_MODE_ALL, "ALL", 0, "All", "Full merge by distance"}, + {MOD_WELD_MODE_CONNECTED, "CONNECTED", 0, "Connected", "Only merge along the edges"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "WeldModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Weld Modifier", "Weld modifier"); RNA_def_struct_sdna(srna, "WeldModifierData"); @@ -6238,6 +6244,11 @@ static void rna_def_modifier_weld(BlenderRNA *brna) RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "Mode defines the merge rule"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "merge_dist"); RNA_def_property_range(prop, 0, FLT_MAX); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index b0dda1237b0..f8a342e7f7e 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -88,8 +88,8 @@ static char *rna_NlaStrip_path(PointerRNA *ptr) char name_esc_nlt[sizeof(nlt->name) * 2]; char name_esc_strip[sizeof(strip->name) * 2]; - BLI_strescape(name_esc_nlt, nlt->name, sizeof(name_esc_nlt)); - BLI_strescape(name_esc_strip, strip->name, sizeof(name_esc_strip)); + BLI_str_escape(name_esc_nlt, nlt->name, sizeof(name_esc_nlt)); + BLI_str_escape(name_esc_strip, strip->name, sizeof(name_esc_strip)); return BLI_sprintfN( "animation_data.nla_tracks[\"%s\"].strips[\"%s\"]", name_esc_nlt, name_esc_strip); } @@ -607,6 +607,8 @@ static void rna_def_nlastrip(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_NlaStrip_path"); RNA_def_struct_ui_icon(srna, ICON_NLA); /* XXX */ + RNA_define_lib_overridable(true); + /* name property */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", ""); @@ -820,6 +822,8 @@ static void rna_def_nlastrip(BlenderRNA *brna) "Update range of frames referenced from action " "after tweaking strip and its keyframes"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); + + RNA_define_lib_overridable(false); } static void rna_api_nlatrack_strips(BlenderRNA *brna, PropertyRNA *cprop) @@ -877,10 +881,14 @@ static void rna_def_nlatrack(BlenderRNA *brna) /* strips collection */ prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "NlaStrip"); + /* We do not support inserting or removing strips in overrides of tracks for now. */ + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips on this NLA-track"); rna_api_nlatrack_strips(brna, prop); + RNA_define_lib_overridable(true); + /* name property */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", ""); @@ -920,6 +928,8 @@ static void rna_def_nlatrack(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_PROTECTED); RNA_def_property_ui_text(prop, "Locked", "NLA Track is locked"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ + + RNA_define_lib_overridable(false); } /* --------- */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 99ae1b85e0c..dd02cc214e0 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1457,7 +1457,7 @@ static char *rna_Node_path(PointerRNA *ptr) bNode *node = (bNode *)ptr->data; char name_esc[sizeof(node->name) * 2]; - BLI_strescape(name_esc, node->name, sizeof(name_esc)); + BLI_str_escape(name_esc, node->name, sizeof(name_esc)); return BLI_sprintfN("nodes[\"%s\"]", name_esc); } @@ -1484,7 +1484,7 @@ char *rna_Node_ImageUser_path(PointerRNA *ptr) continue; } - BLI_strescape(name_esc, node->name, sizeof(name_esc)); + BLI_str_escape(name_esc, node->name, sizeof(name_esc)); return BLI_sprintfN("nodes[\"%s\"].image_user", name_esc); } @@ -2463,7 +2463,7 @@ static char *rna_NodeSocket_path(PointerRNA *ptr) return NULL; } - BLI_strescape(name_esc, node->name, sizeof(name_esc)); + BLI_str_escape(name_esc, node->name, sizeof(name_esc)); if (sock->in_out == SOCK_IN) { return BLI_sprintfN("nodes[\"%s\"].inputs[%d]", name_esc, socketindex); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index a04ad28f9c3..9fb883568c9 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -324,8 +324,27 @@ static void rna_Object_mat_convert_space(Object *ob, return; } } + /* These checks are extra security, they should never occur. */ + if (from == CONSTRAINT_SPACE_CUSTOM) { + const char *identifier = NULL; + RNA_enum_identifier(space_items, from, &identifier); + BKE_reportf(reports, + RPT_ERROR, + "'from_space' '%s' is invalid when no custom space is given!", + identifier); + return; + } + if (to == CONSTRAINT_SPACE_CUSTOM) { + const char *identifier = NULL; + RNA_enum_identifier(space_items, to, &identifier); + BKE_reportf(reports, + RPT_ERROR, + "'to_space' '%s' is invalid when no custom space is given!", + identifier); + return; + } - BKE_constraint_mat_convertspace(ob, pchan, (float(*)[4])mat_ret, from, to, false); + BKE_constraint_mat_convertspace(ob, pchan, NULL, (float(*)[4])mat_ret, from, to, false); } static void rna_Object_calc_matrix_camera(Object *ob, diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 39783f9e31f..db4f3754b25 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -154,7 +154,7 @@ static char *rna_PointCache_path(PointerRNA *ptr) } char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); switch (md->type) { case eModifierType_ParticleSystem: { @@ -171,7 +171,7 @@ static char *rna_PointCache_path(PointerRNA *ptr) for (; surface; surface = surface->next) { if (surface->pointcache == cache) { char name_surface_esc[sizeof(surface->name) * 2]; - BLI_strescape(name_surface_esc, surface->name, sizeof(name_surface_esc)); + BLI_str_escape(name_surface_esc, surface->name, sizeof(name_surface_esc)); return BLI_sprintfN( "modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"].point_cache", name_esc, @@ -436,7 +436,7 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr)) if (md) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc); } else { @@ -608,7 +608,7 @@ static char *rna_SoftBodySettings_path(PointerRNA *ptr) ModifierData *md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Softbody); char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc); } @@ -797,7 +797,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) /* no pointer from modifier data to actual softbody storage, would be good to add */ if (ob->soft->effector_weights == ew) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc); } } @@ -808,7 +808,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) ClothModifierData *cmd = (ClothModifierData *)md; if (cmd->sim_parms->effector_weights == ew) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc); } } @@ -820,7 +820,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) if (fmd->type == MOD_FLUID_TYPE_DOMAIN && fmd->domain && fmd->domain->effector_weights == ew) { char name_esc[sizeof(md->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); return BLI_sprintfN("modifiers[\"%s\"].domain_settings.effector_weights", name_esc); } } @@ -838,8 +838,8 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) char name_esc[sizeof(md->name) * 2]; char name_esc_surface[sizeof(surface->name) * 2]; - BLI_strescape(name_esc, md->name, sizeof(name_esc)); - BLI_strescape(name_esc_surface, surface->name, sizeof(name_esc_surface)); + BLI_str_escape(name_esc, md->name, sizeof(name_esc)); + BLI_str_escape(name_esc_surface, surface->name, sizeof(name_esc_surface)); return BLI_sprintfN( "modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"]" ".effector_weights", diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 5987f52328d..e04ef105071 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1490,7 +1490,7 @@ static char *rna_ParticleSystem_path(PointerRNA *ptr) ParticleSystem *psys = (ParticleSystem *)ptr->data; char name_esc[sizeof(psys->name) * 2]; - BLI_strescape(name_esc, psys->name, sizeof(name_esc)); + BLI_str_escape(name_esc, psys->name, sizeof(name_esc)); return BLI_sprintfN("particle_systems[\"%s\"]", name_esc); } @@ -2484,7 +2484,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) NULL, "ParticleSettingsTextureSlot", "ParticleSettingsTextureSlots", - "rna_Particle_reset", + "rna_Particle_reset_dependency", NULL); /* Fluid particle type can't be checked from the type value in RNA diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index bc9aabbefe6..5f74e8cfc78 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -132,7 +132,7 @@ static char *rna_PoseBone_path(PointerRNA *ptr) bPoseChannel *pchan = ptr->data; char name_esc[sizeof(pchan->name) * 2]; - BLI_strescape(name_esc, pchan->name, sizeof(name_esc)); + BLI_str_escape(name_esc, pchan->name, sizeof(name_esc)); return BLI_sprintfN("pose.bones[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index eae1c7bc223..98ae7591062 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1360,7 +1360,7 @@ static int rna_property_override_diff_propptr(Main *bmain, BLI_assert(STREQ(rna_itemname_a, rna_itemname_b)); char esc_item_name[RNA_PATH_BUFFSIZE]; - const size_t esc_item_name_len = BLI_strescape( + const size_t esc_item_name_len = BLI_str_escape( esc_item_name, rna_itemname_a, RNA_PATH_BUFFSIZE); extended_rna_path_len = rna_path_len + 2 + esc_item_name_len + 2; if (extended_rna_path_len >= RNA_PATH_BUFFSIZE) { @@ -1858,7 +1858,7 @@ int rna_property_override_diff_default(Main *bmain, is_id, is_valid_for_diffing, is_valid_for_insertion, - (RNA_property_override_flag(prop_a) & PROPOVERRIDE_LIBRARY_INSERTION) != 0, + use_collection_insertion, do_create); } # endif diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 235042122e6..da03921bca6 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -390,7 +390,7 @@ const EnumPropertyItem rna_enum_image_color_mode_items[] = { "BW", 0, "BW", - "Images get saved in 8 bits grayscale (only PNG, JPEG, TGA, TIF)"}, + "Images get saved in 8-bit grayscale (only PNG, JPEG, TGA, TIF)"}, {R_IMF_PLANES_RGB, "RGB", 0, "RGB", "Images are saved with RGB (color) data"}, {R_IMF_PLANES_RGBA, "RGBA", @@ -408,12 +408,12 @@ const EnumPropertyItem rna_enum_image_color_mode_items[] = { const EnumPropertyItem rna_enum_image_color_depth_items[] = { /* 1 (monochrome) not used */ - {R_IMF_CHAN_DEPTH_8, "8", 0, "8", "8 bit color channels"}, - {R_IMF_CHAN_DEPTH_10, "10", 0, "10", "10 bit color channels"}, - {R_IMF_CHAN_DEPTH_12, "12", 0, "12", "12 bit color channels"}, - {R_IMF_CHAN_DEPTH_16, "16", 0, "16", "16 bit color channels"}, + {R_IMF_CHAN_DEPTH_8, "8", 0, "8", "8-bit color channels"}, + {R_IMF_CHAN_DEPTH_10, "10", 0, "10", "10-bit color channels"}, + {R_IMF_CHAN_DEPTH_12, "12", 0, "12", "12-bit color channels"}, + {R_IMF_CHAN_DEPTH_16, "16", 0, "16", "16-bit color channels"}, /* 24 not used */ - {R_IMF_CHAN_DEPTH_32, "32", 0, "32", "32 bit color channels"}, + {R_IMF_CHAN_DEPTH_32, "32", 0, "32", "32-bit color channels"}, {0, NULL, 0, NULL, NULL}, }; @@ -529,6 +529,12 @@ const EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem rna_enum_view_layer_aov_type_items[] = { + {AOV_TYPE_COLOR, "COLOR", 0, "Color", ""}, + {AOV_TYPE_VALUE, "VALUE", 0, "Value", ""}, + {0, NULL, 0, NULL, NULL}, +}; + #ifndef RNA_RUNTIME static const EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = { /* interpolation */ @@ -1779,6 +1785,27 @@ void rna_ViewLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr) ntreeCompositUpdateRLayers(scene->nodetree); } + ViewLayer *view_layer = NULL; + if (ptr->type == &RNA_ViewLayer) { + view_layer = (ViewLayer *)ptr->data; + } + else if (ptr->type == &RNA_AOV) { + ViewLayerAOV *aov = (ViewLayerAOV *)ptr->data; + view_layer = BKE_view_layer_find_with_aov(scene, aov); + } + + if (view_layer) { + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + if (engine_type->update_render_passes) { + RenderEngine *engine = RE_engine_create(engine_type); + if (engine) { + BKE_view_layer_verify_aov(engine, scene, view_layer); + } + RE_engine_free(engine); + engine = NULL; + } + } + rna_Scene_glsl_update(bmain, activescene, ptr); } @@ -2397,6 +2424,28 @@ static void rna_ViewLayer_remove( } } +void rna_ViewLayer_active_aov_index_range( + PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax)) +{ + ViewLayer *view_layer = (ViewLayer *)ptr->data; + + *min = 0; + *max = max_ii(0, BLI_listbase_count(&view_layer->aovs) - 1); +} + +int rna_ViewLayer_active_aov_index_get(PointerRNA *ptr) +{ + ViewLayer *view_layer = (ViewLayer *)ptr->data; + return BLI_findindex(&view_layer->aovs, view_layer->active_aov); +} + +void rna_ViewLayer_active_aov_index_set(PointerRNA *ptr, int value) +{ + ViewLayer *view_layer = (ViewLayer *)ptr->data; + ViewLayerAOV *aov = BLI_findlink(&view_layer->aovs, value); + view_layer->active_aov = aov; +} + /* Fake value, used internally (not saved to DNA). */ # define V3D_ORIENT_DEFAULT -1 @@ -3944,7 +3993,7 @@ static void rna_def_view_layer_eevee(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; srna = RNA_def_struct(brna, "ViewLayerEEVEE", NULL); - RNA_def_struct_ui_text(srna, "EEVEE Settings", "View layer settings for EEVEE"); + RNA_def_struct_ui_text(srna, "Eevee Settings", "View layer settings for Eevee"); prop = RNA_def_property(srna, "use_pass_volume_scatter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_SCATTER); @@ -3963,6 +4012,33 @@ static void rna_def_view_layer_eevee(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); } +static void rna_def_view_layer_aov(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + srna = RNA_def_struct(brna, "AOV", NULL); + RNA_def_struct_sdna(srna, "ViewLayerAOV"); + RNA_def_struct_ui_text(srna, "Shader AOV", ""); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "name"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Name", "Name of the AOV"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", AOV_CONFLICT); + RNA_def_property_ui_text(prop, "Valid", "Is the name of the AOV conflicting"); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, rna_enum_view_layer_aov_type_items); + RNA_def_property_enum_default(prop, AOV_TYPE_COLOR); + RNA_def_property_ui_text(prop, "Type", "Data type of the AOV"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); +} + void rna_def_view_layer_common(StructRNA *srna, const bool scene) { PropertyRNA *prop; @@ -4012,7 +4088,65 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene) prop = RNA_def_property(srna, "eevee", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "ViewLayerEEVEE"); - RNA_def_property_ui_text(prop, "EEVEE Settings", "View layer settings for EEVEE"); + RNA_def_property_ui_text(prop, "Eevee Settings", "View layer settings for Eevee"); + + prop = RNA_def_property(srna, "aovs", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "aovs", NULL); + RNA_def_property_struct_type(prop, "AOV"); + RNA_def_property_ui_text(prop, "Shader AOV", ""); + + prop = RNA_def_property(srna, "active_aov", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "AOV"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Shader AOV", "Active AOV"); + + prop = RNA_def_property(srna, "active_aov_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, + "rna_ViewLayer_active_aov_index_get", + "rna_ViewLayer_active_aov_index_set", + "rna_ViewLayer_active_aov_index_range"); + RNA_def_property_ui_text(prop, "Active AOV Index", "Index of active aov"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_pass_cryptomatte_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "cryptomatte_flag", VIEW_LAYER_CRYPTOMATTE_OBJECT); + RNA_def_property_ui_text( + prop, + "Cryptomatte Object", + "Render cryptomatte object pass, for isolating objects in compositing"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + + prop = RNA_def_property(srna, "use_pass_cryptomatte_material", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "cryptomatte_flag", VIEW_LAYER_CRYPTOMATTE_MATERIAL); + RNA_def_property_ui_text( + prop, + "Cryptomatte Material", + "Render cryptomatte material pass, for isolating materials in compositing"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + + prop = RNA_def_property(srna, "use_pass_cryptomatte_asset", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "cryptomatte_flag", VIEW_LAYER_CRYPTOMATTE_ASSET); + RNA_def_property_ui_text( + prop, + "Cryptomatte Asset", + "Render cryptomatte asset pass, for isolating groups of objects with the same parent"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + + prop = RNA_def_property(srna, "pass_cryptomatte_depth", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "cryptomatte_levels"); + RNA_def_property_int_default(prop, 6); + RNA_def_property_range(prop, 2.0, 16.0); + RNA_def_property_ui_text( + prop, "Cryptomatte Levels", "Sets how many unique objects can be distinguished per pixel"); + RNA_def_property_ui_range(prop, 2.0, 16.0, 2.0, 0.0); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + + prop = RNA_def_property(srna, "use_pass_cryptomatte_accurate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "cryptomatte_flag", VIEW_LAYER_CRYPTOMATTE_ACCURATE); + RNA_def_property_boolean_default(prop, true); + RNA_def_property_ui_text( + prop, "Cryptomatte Accurate", "Generate a more accurate cryptomatte pass"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); } /* layer options */ @@ -5353,7 +5487,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_zbuffer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", R_IMF_FLAG_ZBUF); RNA_def_property_ui_text( - prop, "Z Buffer", "Save the z-depth per pixel (32 bit unsigned int z-buffer)"); + prop, "Z Buffer", "Save the z-depth per pixel (32-bit unsigned integer z-buffer)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_preview", PROP_BOOLEAN, PROP_NONE); @@ -5589,26 +5723,26 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "video_bitrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "video_bitrate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Bitrate", "Video bitrate (kb/s)"); + RNA_def_property_ui_text(prop, "Bitrate", "Video bitrate (kbit/s)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "minrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "rc_min_rate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Min Rate", "Rate control: min rate (kb/s)"); + RNA_def_property_ui_text(prop, "Min Rate", "Rate control: min rate (kbit/s)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "maxrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "rc_max_rate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Max Rate", "Rate control: max rate (kb/s)"); + RNA_def_property_ui_text(prop, "Max Rate", "Rate control: max rate (kbit/s)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "muxrate", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "mux_rate"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0, 100000000); - RNA_def_property_ui_text(prop, "Mux Rate", "Mux rate (bits/s(!))"); + RNA_def_property_ui_text(prop, "Mux Rate", "Mux rate (bits/second)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "gopsize", PROP_INT, PROP_NONE); @@ -7289,7 +7423,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) prop = RNA_def_property(srna, "use_shadow_high_bitdepth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SHADOW_HIGH_BITDEPTH); - RNA_def_property_ui_text(prop, "High Bitdepth", "Use 32bit shadows"); + RNA_def_property_ui_text(prop, "High Bit Depth", "Use 32-bit shadows"); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); @@ -7824,7 +7958,7 @@ void RNA_def_scene(BlenderRNA *brna) /* EEVEE */ prop = RNA_def_property(srna, "eevee", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "SceneEEVEE"); - RNA_def_property_ui_text(prop, "EEVEE", "EEVEE settings for the scene"); + RNA_def_property_ui_text(prop, "Eevee", "Eevee settings for the scene"); /* Grease Pencil */ prop = RNA_def_property(srna, "grease_pencil_settings", PROP_POINTER, PROP_NONE); @@ -7848,6 +7982,7 @@ void RNA_def_scene(BlenderRNA *brna) rna_def_display_safe_areas(brna); rna_def_scene_display(brna); rna_def_scene_eevee(brna); + rna_def_view_layer_aov(brna); rna_def_view_layer_eevee(brna); rna_def_scene_gpencil(brna); RNA_define_animate_sdna(true); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index ac45cd5c5ff..9e7fbf2f9a9 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -506,7 +506,7 @@ static char *rna_SequenceTransform_path(PointerRNA *ptr) if (seq && seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform", name_esc); } else { @@ -558,7 +558,7 @@ static char *rna_SequenceCrop_path(PointerRNA *ptr) if (seq && seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop", name_esc); } else { @@ -704,7 +704,7 @@ static char *rna_Sequence_path(PointerRNA *ptr) if (seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"]", name_esc); } else { @@ -1023,7 +1023,7 @@ static char *rna_SequenceColorBalance_path(PointerRNA *ptr) if (seq && seq->name + 2) { char name_esc[(sizeof(seq->name) - 2) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); if (!smd) { /* path to old filter color balance */ @@ -1033,7 +1033,7 @@ static char *rna_SequenceColorBalance_path(PointerRNA *ptr) /* path to modifier */ char name_esc_smd[sizeof(smd->name) * 2]; - BLI_strescape(name_esc_smd, smd->name, sizeof(name_esc_smd)); + BLI_str_escape(name_esc_smd, smd->name, sizeof(name_esc_smd)); return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].modifiers[\"%s\"].color_balance", name_esc, name_esc_smd); @@ -1168,8 +1168,8 @@ static char *rna_SequenceModifier_path(PointerRNA *ptr) char name_esc[(sizeof(seq->name) - 2) * 2]; char name_esc_smd[sizeof(smd->name) * 2]; - BLI_strescape(name_esc, seq->name + 2, sizeof(name_esc)); - BLI_strescape(name_esc_smd, smd->name, sizeof(name_esc_smd)); + BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc_smd, smd->name, sizeof(name_esc_smd)); return BLI_sprintfN( "sequence_editor.sequences_all[\"%s\"].modifiers[\"%s\"]", name_esc, name_esc_smd); } @@ -1408,7 +1408,7 @@ static void rna_def_strip_transform(BlenderRNA *brna) prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "rotation"); - RNA_def_property_ui_text(prop, "Rotation", "Rotate around image centr"); + RNA_def_property_ui_text(prop, "Rotation", "Rotate around image center"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update"); RNA_def_struct_path_func(srna, "rna_SequenceTransform_path"); diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c index 7b039b91188..451cc56eba7 100644 --- a/source/blender/makesrna/intern/rna_shader_fx.c +++ b/source/blender/makesrna/intern/rna_shader_fx.c @@ -161,7 +161,7 @@ static char *rna_ShaderFx_path(PointerRNA *ptr) ShaderFxData *gmd = ptr->data; char name_esc[sizeof(gmd->name) * 2]; - BLI_strescape(name_esc, gmd->name, sizeof(name_esc)); + BLI_str_escape(name_esc, gmd->name, sizeof(name_esc)); return BLI_sprintfN("shader_effects[\"%s\"]", name_esc); } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 8ff4336ba83..65ea155ffba 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -426,6 +426,9 @@ static const EnumPropertyItem rna_enum_view3dshading_render_pass_type_items[] = {EEVEE_RENDER_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, {EEVEE_RENDER_PASS_MIST, "MIST", 0, "Mist", ""}, + {0, "", ICON_NONE, "Shader AOV", ""}, + {EEVEE_RENDER_PASS_AOV, "AOV", 0, "AOV", ""}, + {0, NULL, 0, NULL, NULL}, }; @@ -1065,6 +1068,19 @@ static Scene *rna_3DViewShading_scene(PointerRNA *ptr) } } +static ViewLayer *rna_3DViewShading_view_layer(PointerRNA *ptr) +{ + /* Get scene, depends if using 3D view or OpenGL render settings. */ + ID *id = ptr->owner_id; + if (GS(id->name) == ID_SCE) { + return NULL; + } + else { + bScreen *screen = (bScreen *)ptr->owner_id; + return WM_windows_view_layer_get_from_screen(G_MAIN->wm.first, screen); + } +} + static int rna_3DViewShading_type_get(PointerRNA *ptr) { /* Available shading types depend on render engine. */ @@ -1292,15 +1308,33 @@ static const EnumPropertyItem *rna_3DViewShading_render_pass_itemf(bContext *C, bool *r_free) { Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); const bool bloom_enabled = scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED; + const bool aov_available = BKE_view_layer_has_valid_aov(view_layer); int totitem = 0; EnumPropertyItem *result = NULL; + EnumPropertyItem aov_template; for (int i = 0; rna_enum_view3dshading_render_pass_type_items[i].identifier != NULL; i++) { const EnumPropertyItem *item = &rna_enum_view3dshading_render_pass_type_items[i]; - if (!((!bloom_enabled && - (item->value == EEVEE_RENDER_PASS_BLOOM || STREQ(item->name, "Effects"))))) { + if (item->value == EEVEE_RENDER_PASS_AOV) { + aov_template.value = item->value; + aov_template.icon = 0; + aov_template.description = item->description; + LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { + if ((aov->flag & AOV_CONFLICT) != 0) { + continue; + } + aov_template.name = aov->name; + aov_template.identifier = aov->name; + RNA_enum_item_add(&result, &totitem, &aov_template); + aov_template.value++; + } + } + else if (!((!bloom_enabled && + (item->value == EEVEE_RENDER_PASS_BLOOM || STREQ(item->name, "Effects"))) || + (!aov_available && STREQ(item->name, "Shader AOV")))) { RNA_enum_item_add(&result, &totitem, item); } } @@ -1314,14 +1348,58 @@ static int rna_3DViewShading_render_pass_get(PointerRNA *ptr) View3DShading *shading = (View3DShading *)ptr->data; eViewLayerEEVEEPassType result = shading->render_pass; Scene *scene = rna_3DViewShading_scene(ptr); + ViewLayer *view_layer = rna_3DViewShading_view_layer(ptr); if (result == EEVEE_RENDER_PASS_BLOOM && ((scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) == 0)) { - result = EEVEE_RENDER_PASS_COMBINED; + return EEVEE_RENDER_PASS_COMBINED; + } + else if (result == EEVEE_RENDER_PASS_AOV) { + if (!view_layer) { + return EEVEE_RENDER_PASS_COMBINED; + } + const int aov_index = BLI_findstringindex( + &view_layer->aovs, shading->aov_name, offsetof(ViewLayerAOV, name)); + if (aov_index == -1) { + return EEVEE_RENDER_PASS_COMBINED; + } + return result + aov_index; } return result; } +static void rna_3DViewShading_render_pass_set(PointerRNA *ptr, int value) +{ + View3DShading *shading = (View3DShading *)ptr->data; + Scene *scene = rna_3DViewShading_scene(ptr); + ViewLayer *view_layer = rna_3DViewShading_view_layer(ptr); + shading->aov_name[0] = 0; + + if ((value & EEVEE_RENDER_PASS_AOV) != 0) { + if (!view_layer) { + shading->render_pass = EEVEE_RENDER_PASS_COMBINED; + return; + } + const int aov_index = value & ~EEVEE_RENDER_PASS_AOV; + ViewLayerAOV *aov = BLI_findlink(&view_layer->aovs, aov_index); + if (!aov) { + /* AOV not found, cannot select AOV. */ + shading->render_pass = EEVEE_RENDER_PASS_COMBINED; + return; + } + + shading->render_pass = EEVEE_RENDER_PASS_AOV; + BLI_strncpy(shading->aov_name, aov->name, sizeof(aov->name)); + } + else if (value == EEVEE_RENDER_PASS_BLOOM && + ((scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) == 0)) { + shading->render_pass = EEVEE_RENDER_PASS_COMBINED; + } + else { + shading->render_pass = value; + } +} + static void rna_SpaceView3D_use_local_collections_update(bContext *C, PointerRNA *ptr) { Main *bmain = CTX_data_main(C); @@ -2035,7 +2113,7 @@ static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr) * and the user then uses the browse menu to get back to this action, * assigning it as the active action (i.e. the stash strip gets out of sync) */ - BKE_nla_action_stash(adt); + BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(id)); } BKE_animdata_set_action(NULL, id, saction->action); @@ -2389,6 +2467,18 @@ static PointerRNA rna_FileSelectParams_filter_id_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_FileSelectIDFilter, ptr->data); } +static PointerRNA rna_FileBrowser_params_get(PointerRNA *ptr) +{ + SpaceFile *sfile = ptr->data; + FileSelectParams *params = ED_fileselect_get_active_params(sfile); + + if (params) { + return rna_pointer_inherit_refine(ptr, &RNA_FileSelectParams, params); + } + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + static void rna_FileBrowser_FSMenuEntry_path_get(PointerRNA *ptr, char *value) { char *path = ED_fsmenu_entry_get_path(ptr->data); @@ -3488,9 +3578,17 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "render_pass"); RNA_def_property_enum_items(prop, rna_enum_view3dshading_render_pass_type_items); RNA_def_property_ui_text(prop, "Render Pass", "Render Pass to show in the viewport"); - RNA_def_property_enum_funcs( - prop, "rna_3DViewShading_render_pass_get", NULL, "rna_3DViewShading_render_pass_itemf"); + RNA_def_property_enum_funcs(prop, + "rna_3DViewShading_render_pass_get", + "rna_3DViewShading_render_pass_set", + "rna_3DViewShading_render_pass_itemf"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL); + + prop = RNA_def_property(srna, "aov_name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "aov_name"); + RNA_def_property_ui_text(prop, "Shader AOV Name", "Name of the active Shader AOV"); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } static void rna_def_space_view3d_overlay(BlenderRNA *brna) @@ -5957,7 +6055,8 @@ static void rna_def_space_filebrowser(BlenderRNA *brna) rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI)); prop = RNA_def_property(srna, "params", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "params"); + RNA_def_property_struct_type(prop, "FileSelectParams"); + RNA_def_property_pointer_funcs(prop, "rna_FileBrowser_params_get", NULL, NULL, NULL); RNA_def_property_ui_text( prop, "Filebrowser Parameter", "Parameters and Settings for the Filebrowser"); diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index fb6d40b3a55..cf8abf26c0a 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -148,6 +148,7 @@ static const EnumPropertyItem blend_type_items[] = { # include "BKE_texture.h" # include "DEG_depsgraph.h" +# include "DEG_depsgraph_build.h" # include "ED_node.h" # include "ED_render.h" @@ -233,6 +234,12 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value) BKE_texture_type_set(tex, value); } +void rna_TextureSlotTexture_update(bContext *C, PointerRNA *ptr) +{ + DEG_relations_tag_update(CTX_data_main(C)); + rna_TextureSlot_update(C, ptr); +} + void rna_TextureSlot_update(bContext *C, PointerRNA *ptr) { ID *id = ptr->owner_id; @@ -317,7 +324,7 @@ char *rna_TextureSlot_path(PointerRNA *ptr) if (mtex->tex) { char name_esc[(sizeof(mtex->tex->id.name) - 2) * 2]; - BLI_strescape(name_esc, mtex->tex->id.name + 2, sizeof(name_esc)); + BLI_str_escape(name_esc, mtex->tex->id.name + 2, sizeof(name_esc)); return BLI_sprintfN("texture_slots[\"%s\"]", name_esc); } else { @@ -623,7 +630,7 @@ static void rna_def_mtex(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Texture", "Texture data-block used by this texture slot"); - RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update"); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlotTexture_update"); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs( diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 23f3a04fd91..f1f7810bcf0 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -5026,7 +5026,6 @@ static void rna_def_userdef_edit(BlenderRNA *brna) prop, "Channel Group Colors", "Use animation channel group colors; generally this is used to show bone group colors"); - RNA_def_property_boolean_default(prop, true); RNA_def_property_update(prop, 0, "rna_userdef_anim_update"); prop = RNA_def_property(srna, "fcurve_new_auto_smoothing", PROP_ENUM, PROP_NONE); @@ -5274,12 +5273,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) }; static const EnumPropertyItem audio_format_items[] = { - {0x01, "U8", 0, "8-bit Unsigned", "Set audio sample format to 8 bit unsigned integer"}, - {0x12, "S16", 0, "16-bit Signed", "Set audio sample format to 16 bit signed integer"}, - {0x13, "S24", 0, "24-bit Signed", "Set audio sample format to 24 bit signed integer"}, - {0x14, "S32", 0, "32-bit Signed", "Set audio sample format to 32 bit signed integer"}, - {0x24, "FLOAT", 0, "32-bit Float", "Set audio sample format to 32 bit float"}, - {0x28, "DOUBLE", 0, "64-bit Float", "Set audio sample format to 64 bit float"}, + {0x01, "U8", 0, "8-bit Unsigned", "Set audio sample format to 8-bit unsigned integer"}, + {0x12, "S16", 0, "16-bit Signed", "Set audio sample format to 16-bit signed integer"}, + {0x13, "S24", 0, "24-bit Signed", "Set audio sample format to 24-bit signed integer"}, + {0x14, "S32", 0, "32-bit Signed", "Set audio sample format to 32-bit signed integer"}, + {0x24, "FLOAT", 0, "32-bit Float", "Set audio sample format to 32-bit float"}, + {0x28, "DOUBLE", 0, "64-bit Float", "Set audio sample format to 64-bit float"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_volume.c b/source/blender/makesrna/intern/rna_volume.c index 37b34f68be5..42d491b734e 100644 --- a/source/blender/makesrna/intern/rna_volume.c +++ b/source/blender/makesrna/intern/rna_volume.c @@ -228,8 +228,8 @@ static void rna_def_volume_grid(BlenderRNA *brna) {VOLUME_GRID_BOOLEAN, "BOOLEAN", 0, "Boolean", "Boolean"}, {VOLUME_GRID_FLOAT, "FLOAT", 0, "Float", "Single precision float"}, {VOLUME_GRID_DOUBLE, "DOUBLE", 0, "Double", "Double precision"}, - {VOLUME_GRID_INT, "INT", 0, "Integer", "32 bit integer"}, - {VOLUME_GRID_INT64, "INT64", 0, "Integer 64 bit", "64 bit integer"}, + {VOLUME_GRID_INT, "INT", 0, "Integer", "32-bit integer"}, + {VOLUME_GRID_INT64, "INT64", 0, "Integer 64-bit", "64-bit integer"}, {VOLUME_GRID_MASK, "MASK", 0, "Mask", "No data, boolean mask of active voxels"}, {VOLUME_GRID_STRING, "STRING", 0, "String", "Text string"}, {VOLUME_GRID_VECTOR_FLOAT, "VECTOR_FLOAT", 0, "Float Vector", "3D float vector"}, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 4152e8633e5..0513d3af13a 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -630,7 +630,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Object *operand_ob = bmd->object; +#ifdef DEBUG_TIME + TIMEIT_BLOCK_INIT(operand_get_evaluated_mesh); + TIMEIT_BLOCK_START(operand_get_evaluated_mesh); +#endif mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, false); +#ifdef DEBUG_TIME + TIMEIT_BLOCK_END(operand_get_evaluated_mesh); + TIMEIT_BLOCK_STATS(operand_get_evaluated_mesh); +#endif if (mesh_operand_ob) { /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh! @@ -642,11 +650,35 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = get_quick_mesh(object, mesh, operand_ob, mesh_operand_ob, bmd->operation); if (result == NULL) { +#ifdef DEBUG_TIME + TIMEIT_BLOCK_INIT(object_BMD_mesh_bm_create); + TIMEIT_BLOCK_START(object_BMD_mesh_bm_create); +#endif bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip); +#ifdef DEBUG_TIME + TIMEIT_BLOCK_END(object_BMD_mesh_bm_create); + TIMEIT_BLOCK_STATS(object_BMD_mesh_bm_create); +#endif +#ifdef DEBUG_TIME + TIMEIT_BLOCK_INIT(BMD_mesh_intersection); + TIMEIT_BLOCK_START(BMD_mesh_intersection); +#endif BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip); +#ifdef DEBUG_TIME + TIMEIT_BLOCK_END(BMD_mesh_intersection); + TIMEIT_BLOCK_STATS(BMD_mesh_intersection); +#endif +#ifdef DEBUG_TIME + TIMEIT_BLOCK_INIT(BKE_mesh_from_bmesh_for_eval_nomain); + TIMEIT_BLOCK_START(BKE_mesh_from_bmesh_for_eval_nomain); +#endif result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); +#ifdef DEBUG_TIME + TIMEIT_BLOCK_END(BKE_mesh_from_bmesh_for_eval_nomain); + TIMEIT_BLOCK_STATS(BKE_mesh_from_bmesh_for_eval_nomain); +#endif BM_mesh_free(bm); result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index 1a25c24fedc..e34dcf48c19 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -1567,6 +1567,12 @@ static bool bvhtree_weld_overlap_cb(void *userdata, int index_a, int index_b, in } #endif +/** Use for #MOD_WELD_MODE_CONNECTED calculation. */ +struct WeldVertexCluster { + float co[3]; + uint merged_verts; +}; + static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; @@ -1606,6 +1612,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex * This indicates which vert it is or is going to be merged. */ uint *vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__); uint vert_kill_len = 0; + if (wmd->mode == MOD_WELD_MODE_ALL) #ifdef USE_BVHTREEKDOP { /* Get overlap map. */ @@ -1701,6 +1708,80 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex BLI_kdtree_3d_free(tree); } #endif + else { + BLI_assert(wmd->mode == MOD_WELD_MODE_CONNECTED); + + MEdge *medge, *me; + + medge = mesh->medge; + totvert = mesh->totvert; + totedge = mesh->totedge; + + struct WeldVertexCluster *vert_clusters = MEM_malloc_arrayN( + totvert, sizeof(*vert_clusters), __func__); + struct WeldVertexCluster *vc = &vert_clusters[0]; + for (uint i = 0; i < totvert; i++, vc++) { + copy_v3_v3(vc->co, mvert[i].co); + vc->merged_verts = 0; + } + const float merge_dist_sq = square_f(wmd->merge_dist); + + range_vn_u(vert_dest_map, totvert, 0); + + /* Collapse Edges that are shorter than the threshold. */ + me = &medge[0]; + for (uint i = 0; i < totedge; i++, me++) { + uint v1 = me->v1; + uint v2 = me->v2; + + while (v1 != vert_dest_map[v1]) { + v1 = vert_dest_map[v1]; + } + while (v2 != vert_dest_map[v2]) { + v2 = vert_dest_map[v2]; + } + if (v1 == v2) { + continue; + } + if (v_mask && (!BLI_BITMAP_TEST(v_mask, v1) || !BLI_BITMAP_TEST(v_mask, v2))) { + continue; + } + if (v1 > v2) { + SWAP(uint, v1, v2); + } + struct WeldVertexCluster *v1_cluster = &vert_clusters[v1]; + struct WeldVertexCluster *v2_cluster = &vert_clusters[v2]; + + float edgedir[3]; + sub_v3_v3v3(edgedir, v2_cluster->co, v1_cluster->co); + const float dist_sq = len_squared_v3(edgedir); + if (dist_sq <= merge_dist_sq) { + float influence = (v2_cluster->merged_verts + 1) / + (float)(v1_cluster->merged_verts + v2_cluster->merged_verts + 2); + madd_v3_v3fl(v1_cluster->co, edgedir, influence); + + v1_cluster->merged_verts += v2_cluster->merged_verts + 1; + vert_dest_map[v2] = v1; + vert_kill_len++; + } + } + + MEM_freeN(vert_clusters); + + for (uint i = 0; i < totvert; i++) { + if (i == vert_dest_map[i]) { + vert_dest_map[i] = OUT_OF_CONTEXT; + } + else { + uint v = i; + while ((v != vert_dest_map[v]) && (vert_dest_map[v] != OUT_OF_CONTEXT)) { + v = vert_dest_map[v]; + } + vert_dest_map[v] = v; + vert_dest_map[i] = v; + } + } + } if (v_mask) { MEM_freeN(v_mask); @@ -1940,6 +2021,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); + uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE); modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 2b95f76d06b..a7df4bc3e1b 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -26,6 +26,8 @@ namespace blender::nodes { +using bke::Color4fReadAttribute; +using bke::Color4fWriteAttribute; using bke::Float3ReadAttribute; using bke::Float3WriteAttribute; using bke::FloatReadAttribute; @@ -146,6 +148,26 @@ class GeoNodeExecParams { return self_object_; } + /** + * Creates a read-only attribute based on node inputs. The method automatically detects which + * input with the given name is available. + */ + ReadAttributePtr get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const CustomDataType type, + const void *default_value) const; + + template<typename T> + bke::TypedReadAttribute<T> get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const T &default_value) const + { + const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get<T>()); + return this->get_input_attribute(name, component, domain, type, &default_value); + } + private: /* Utilities for detecting common errors at when using this class. */ void check_extract_input(StringRef identifier, const CPPType *requested_type = nullptr) const; diff --git a/source/blender/nodes/geometry/node_geometry_tree.cc b/source/blender/nodes/geometry/node_geometry_tree.cc index 69f9f7fb4ed..da77e8896fb 100644 --- a/source/blender/nodes/geometry/node_geometry_tree.cc +++ b/source/blender/nodes/geometry/node_geometry_tree.cc @@ -14,7 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include <string.h> +#include <cstring> #include "MEM_guardedalloc.h" diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc index 41bdb1cfff0..34c7d224f03 100644 --- a/source/blender/nodes/geometry/node_geometry_util.cc +++ b/source/blender/nodes/geometry/node_geometry_util.cc @@ -17,6 +17,27 @@ #include "node_geometry_util.hh" #include "node_util.h" +namespace blender::nodes { + +void update_attribute_input_socket_availabilities(bNode &node, + const StringRef name, + const GeometryNodeAttributeInputMode mode) +{ + const GeometryNodeAttributeInputMode mode_ = (GeometryNodeAttributeInputMode)mode; + LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { + if (name == socket->name) { + const bool is_available = + ((socket->type == SOCK_STRING && mode_ == GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE) || + (socket->type == SOCK_FLOAT && mode_ == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) || + (socket->type == SOCK_VECTOR && mode_ == GEO_NODE_ATTRIBUTE_INPUT_VECTOR) || + (socket->type == SOCK_RGBA && mode_ == GEO_NODE_ATTRIBUTE_INPUT_COLOR)); + nodeSetSocketAvailability(socket, is_available); + } + } +} + +} // namespace blender::nodes + bool geo_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) { return STREQ(ntree->idname, "GeometryNodeTree"); diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index bb26763642b..ec389961615 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -37,3 +37,9 @@ void geo_node_type_base( struct bNodeType *ntype, int type, const char *name, short nclass, short flag); bool geo_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); + +namespace blender::nodes { +void update_attribute_input_socket_availabilities(bNode &node, + const StringRef name, + const GeometryNodeAttributeInputMode mode); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_common.cc b/source/blender/nodes/geometry/nodes/node_geo_common.cc index 8adc3962698..441ad6bdc13 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_common.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_common.cc @@ -26,7 +26,7 @@ void register_node_type_geo_group(void) { static bNodeType ntype; - node_type_base_custom(&ntype, "GeometryNodeGroup", "Group", 0, 0); + node_type_base_custom(&ntype, "GeometryNodeGroup", "Group", NODE_CLASS_GROUP, 0); ntype.type = NODE_GROUP; ntype.poll = geo_node_poll_default; ntype.poll_instance = node_group_poll_instance; diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index e5e7cf57e27..543859aef3f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -16,6 +16,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_mesh.h" #include "BKE_subdiv.h" #include "BKE_subdiv_mesh.h" @@ -25,7 +26,7 @@ static bNodeSocketTemplate geo_node_subdivision_surface_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_INT, N_("Level"), 1, 0, 0, 0, 0, 6}, {SOCK_BOOLEAN, N_("Use Creases")}, - {SOCK_BOOLEAN, N_("Boundary Smooth")}, + {SOCK_BOOLEAN, N_("Boundary Smooth"), true}, {SOCK_BOOLEAN, N_("Smooth UVs")}, {-1, ""}, }; @@ -76,7 +77,7 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params) subdiv_settings.level = subdiv_level; subdiv_settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( - boundary_smooth); + !boundary_smooth); subdiv_settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( smooth_uvs); @@ -90,6 +91,7 @@ static void geo_node_subdivision_surface_exec(GeoNodeExecParams params) } Mesh *mesh_out = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh_in); + BKE_mesh_calc_normals(mesh_out); geometry_set.replace_mesh(mesh_out); diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index 50292cb8cfb..a6d9115f01f 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -19,6 +19,47 @@ namespace blender::nodes { +ReadAttributePtr GeoNodeExecParams::get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const CustomDataType type, + const void *default_value) const +{ + const bNodeSocket *found_socket = nullptr; + LISTBASE_FOREACH (const bNodeSocket *, socket, &node_.inputs) { + if ((socket->flag & SOCK_UNAVAIL) != 0) { + continue; + } + if (name == socket->name) { + found_socket = socket; + break; + } + } + BLI_assert(found_socket != nullptr); + + if (found_socket->type == SOCK_STRING) { + const std::string name = this->get_input<std::string>(found_socket->identifier); + return component.attribute_get_for_read(name, domain, type, default_value); + } + if (found_socket->type == SOCK_FLOAT) { + const float value = this->get_input<float>(found_socket->identifier); + return component.attribute_get_constant_for_read_converted( + domain, CD_PROP_FLOAT, type, &value); + } + if (found_socket->type == SOCK_VECTOR) { + const float3 value = this->get_input<float3>(found_socket->identifier); + return component.attribute_get_constant_for_read_converted( + domain, CD_PROP_FLOAT3, type, &value); + } + if (found_socket->type == SOCK_RGBA) { + const Color4f value = this->get_input<Color4f>(found_socket->identifier); + return component.attribute_get_constant_for_read_converted( + domain, CD_PROP_COLOR, type, &value); + } + BLI_assert(false); + return component.attribute_get_constant_for_read(domain, type, default_value); +} + void GeoNodeExecParams::check_extract_input(StringRef identifier, const CPPType *requested_type) const { diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index d4b1df2f3f0..ebc70956147 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -21,7 +21,7 @@ * \ingroup nodes */ -#include <limits.h> +#include <climits> #include "DNA_node_types.h" diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc index 8440e996651..ec5527a2970 100644 --- a/source/blender/nodes/intern/node_tree_multi_function.cc +++ b/source/blender/nodes/intern/node_tree_multi_function.cc @@ -204,6 +204,10 @@ static DataTypeConversions create_implicit_conversions() conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); }); add_implicit_conversion<Color4f, float3>( conversions, "Color4f to float3", [](Color4f a) { return float3(a.r, a.g, a.b); }); + add_implicit_conversion<float, Color4f>( + conversions, "float to Color4f", [](float a) { return Color4f(a, a, a, 1.0f); }); + add_implicit_conversion<Color4f, float>( + conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); }); return conversions; } diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index efd0e48f41a..a385cb7039f 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -903,6 +903,16 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree, /* Duplicate bump height branches for manual derivatives. */ nodeChainIterBackwards(localtree, output, ntree_shader_bump_branches, localtree, 0); + LISTBASE_FOREACH (bNode *, node, &localtree->nodes) { + if (node->type == SH_NODE_OUTPUT_AOV) { + nodeChainIterBackwards(localtree, node, ntree_shader_bump_branches, localtree, 0); + nTreeTags tags = { + .ssr_id = 1.0, + .sss_id = 1.0, + }; + ntree_shader_tag_nodes(localtree, node, &tags); + } + } /* TODO(fclem): consider moving this to the gpu shader tree evaluation. */ nTreeTags tags = { @@ -913,6 +923,11 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree, exec = ntreeShaderBeginExecTree(localtree); ntreeExecGPUNodes(exec, mat, output); + LISTBASE_FOREACH (bNode *, node, &localtree->nodes) { + if (node->type == SH_NODE_OUTPUT_AOV) { + ntreeExecGPUNodes(exec, mat, node); + } + } ntreeShaderEndExecTree(exec); /* EEVEE: Find which material domain was used (volume, surface ...). */ diff --git a/source/blender/nodes/shader/nodes/node_shader_output_aov.c b/source/blender/nodes/shader/nodes/node_shader_output_aov.c index 8e73a547bf7..403b3e6d9d6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_aov.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_aov.c @@ -19,6 +19,8 @@ #include "../node_shader_util.h" +#include "BLI_hash.h" + /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_output_aov_in[] = { @@ -33,6 +35,22 @@ static void node_shader_init_output_aov(bNodeTree *UNUSED(ntree), bNode *node) node->storage = aov; } +static int node_shader_gpu_output_aov(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + GPUNodeLink *outlink; + NodeShaderOutputAOV *aov = (NodeShaderOutputAOV *)node->storage; + /* Keep in sync with `renderpass_lib.glsl#render_pass_aov_hash`. */ + unsigned int hash = BLI_hash_string(aov->name) & ~1; + GPU_stack_link(mat, node, "node_output_aov", in, out, &outlink); + GPU_material_add_output_link_aov(mat, outlink, hash); + + return true; +} + /* node type definition */ void register_node_type_sh_output_aov(void) { @@ -43,6 +61,7 @@ void register_node_type_sh_output_aov(void) node_type_init(&ntype, node_shader_init_output_aov); node_type_storage( &ntype, "NodeShaderOutputAOV", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, node_shader_gpu_output_aov); /* Do not allow muting output node. */ node_type_internal_links(&ntype, NULL); diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index a8b66f3f2fe..63fb685e66d 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -20,8 +20,6 @@ #include <Python.h> -#include <string.h> - #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" @@ -255,7 +253,7 @@ static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUS name = _PyUnicode_AsStringAndSize(value, &name_size); - if (name_size > MAX_IDPROP_NAME) { + if (name_size >= MAX_IDPROP_NAME) { PyErr_SetString(PyExc_TypeError, "string length cannot exceed 63 characters!"); return -1; } @@ -367,16 +365,11 @@ static const char *idp_try_read_name(PyObject *name_obj) return NULL; } - if (name_size > MAX_IDPROP_NAME) { + if (name_size >= MAX_IDPROP_NAME) { PyErr_SetString(PyExc_KeyError, "the length of IDProperty names is limited to 63 characters"); return NULL; } - - if (strchr(name, '\"') || strchr(name, '\\') || strchr(name, '\'')) { - PyErr_SetString(PyExc_KeyError, "IDProperty names cannot include \", \\, or \'"); - return NULL; - } } else { name = ""; diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 772b31fd9d8..5d8330e368d 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -255,7 +255,11 @@ if(WITH_SDL) list(APPEND INC_SYS ${SDL_INCLUDE_DIR} ) - if(NOT WITH_SDL_DYNLOAD) + if(WITH_SDL_DYNLOAD) + list(APPEND LIB + extern_sdlew + ) + else() list(APPEND LIB ${SDL_LIBRARY} ) diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 804a28d0ebc..6462f8320d7 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -260,25 +260,19 @@ PyDoc_STRVAR(bpy_escape_identifier_doc, " :rtype: string\n"); static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) { - const char *value_str; Py_ssize_t value_str_len; - - char *value_escape_str; - Py_ssize_t value_escape_str_len; - PyObject *value_escape; - size_t size; - - value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); + const char *value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); if (value_str == NULL) { PyErr_SetString(PyExc_TypeError, "expected a string"); return NULL; } - size = (value_str_len * 2) + 1; - value_escape_str = PyMem_MALLOC(size); - value_escape_str_len = BLI_strescape(value_escape_str, value_str, size); + const size_t size = (value_str_len * 2) + 1; + char *value_escape_str = PyMem_MALLOC(size); + const Py_ssize_t value_escape_str_len = BLI_str_escape(value_escape_str, value_str, size); + PyObject *value_escape; if (value_escape_str_len == value_str_len) { Py_INCREF(value); value_escape = value; @@ -292,6 +286,44 @@ static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) return value_escape; } +PyDoc_STRVAR(bpy_unescape_identifier_doc, + ".. function:: unescape_identifier(string)\n" + "\n" + " Simple string un-escape function used for animation paths.\n" + " This performs the reverse of `escape_identifier`.\n" + "\n" + " :arg string: text\n" + " :type string: string\n" + " :return: The un-escaped string.\n" + " :rtype: string\n"); +static PyObject *bpy_unescape_identifier(PyObject *UNUSED(self), PyObject *value) +{ + Py_ssize_t value_str_len; + const char *value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); + + if (value_str == NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string"); + return NULL; + } + + const size_t size = value_str_len + 1; + char *value_unescape_str = PyMem_MALLOC(size); + const Py_ssize_t value_unescape_str_len = BLI_str_unescape(value_unescape_str, value_str, size); + + PyObject *value_unescape; + if (value_unescape_str_len == value_str_len) { + Py_INCREF(value); + value_unescape = value; + } + else { + value_unescape = PyUnicode_FromStringAndSize(value_unescape_str, value_unescape_str_len); + } + + PyMem_FREE(value_unescape_str); + + return value_unescape; +} + static PyMethodDef meth_bpy_script_paths = { "script_paths", (PyCFunction)bpy_script_paths, @@ -328,6 +360,12 @@ static PyMethodDef meth_bpy_escape_identifier = { METH_O, bpy_escape_identifier_doc, }; +static PyMethodDef meth_bpy_unescape_identifier = { + "unescape_identifier", + (PyCFunction)bpy_unescape_identifier, + METH_O, + bpy_unescape_identifier_doc, +}; static PyObject *bpy_import_test(const char *modname) { @@ -429,6 +467,9 @@ void BPy_init_modules(struct bContext *C) PyModule_AddObject(mod, meth_bpy_escape_identifier.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_escape_identifier, NULL)); + PyModule_AddObject(mod, + meth_bpy_unescape_identifier.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_unescape_identifier, NULL)); /* register funcs (bpy_rna.c) */ PyModule_AddObject(mod, diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index bc3d8b2c360..c6f0fbd3a2b 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -44,6 +44,8 @@ #include "BLO_readfile.h" +#include "MEM_guardedalloc.h" + #include "bpy_capi_utils.h" #include "bpy_library.h" @@ -225,7 +227,7 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype) PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); counter++; } - BLI_linklist_free(names, free); /* free linklist *and* each node's data */ + BLI_linklist_freeN(names); /* free linklist *and* each node's data */ } return list; diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index d45c8e8b131..9d69d91c8c8 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -3494,7 +3494,6 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) { PyErr_Format(PyExc_TypeError, "CollectionProperty(...) expected an RNA type derived from %.200s", - RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup)); return NULL; } diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index 0ebf8f3c8e7..c998886626c 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -505,7 +505,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char { char name_esc[SEQ_NAME_MAXSTR * 2]; - BLI_strescape(name_esc, name, sizeof(name_esc)); + BLI_str_escape(name_esc, name, sizeof(name_esc)); return BLI_snprintf_rlen( str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); } diff --git a/source/blender/simulation/intern/hair_volume.cpp b/source/blender/simulation/intern/hair_volume.cpp index 123b91edaac..08af2344bc4 100644 --- a/source/blender/simulation/intern/hair_volume.cpp +++ b/source/blender/simulation/intern/hair_volume.cpp @@ -68,20 +68,20 @@ BLI_INLINE int hair_grid_size(const int res[3]) return res[0] * res[1] * res[2]; } -typedef struct HairGridVert { +struct HairGridVert { int samples; float velocity[3]; float density; float velocity_smooth[3]; -} HairGridVert; +}; -typedef struct HairGrid { +struct HairGrid { HairGridVert *verts; int res[3]; float gmin[3], gmax[3]; float cellsize, inv_cellsize; -} HairGrid; +}; #define HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, axis) \ (min_ii(max_ii((int)((vec[axis] - gmin[axis]) * scale), 0), res[axis] - 2)) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 47c5487a458..da2115e12fb 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -47,7 +47,6 @@ struct ImBuf; struct ImageFormatData; struct Main; struct MenuType; -struct Operator; struct PointerRNA; struct PropertyRNA; struct ScrArea; @@ -130,6 +129,9 @@ void WM_windows_scene_data_sync(const ListBase *win_lb, struct Scene *scene) ATT struct Scene *WM_windows_scene_get_from_screen(const struct wmWindowManager *wm, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +struct ViewLayer *WM_windows_view_layer_get_from_screen(const struct wmWindowManager *wm, + const struct bScreen *screen) + ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; struct WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; @@ -256,9 +258,6 @@ void WM_event_set_keymap_handler_post_callback(struct wmEventHandler_Keymap *han wmKeyMap *WM_event_get_keymap_from_handler(wmWindowManager *wm, struct wmEventHandler_Keymap *handler); -wmKeyMapItem *WM_event_match_modal_keymap_item(const wmKeyMap *keymap, - struct wmOperator *op, - const struct wmEvent *event); wmKeyMapItem *WM_event_match_keymap_item(struct bContext *C, wmKeyMap *keymap, const struct wmEvent *event); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 587abf6fa0a..ac27862d507 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -376,10 +376,9 @@ void wm_event_do_refresh_wm_and_depsgraph(bContext *C) /* Cached: editor refresh callbacks now, they get context. */ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { const bScreen *screen = WM_window_get_active_screen(win); - ScrArea *area; CTX_wm_window_set(C, win); - for (area = screen->areabase.first; area; area = area->next) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { if (area->do_refresh) { CTX_wm_area_set(C, area); ED_area_do_refresh(C, area); @@ -516,7 +515,7 @@ void wm_event_do_notifiers(bContext *C) bScreen *screen = WM_window_get_active_screen(win); WorkSpace *workspace = WM_window_get_active_workspace(win); - /* Dilter out notifiers. */ + /* Filter out notifiers. */ if (note->category == NC_SCREEN && note->reference && note->reference != screen && note->reference != workspace && note->reference != WM_window_get_active_layout(win)) { /* Pass. */ @@ -525,8 +524,6 @@ void wm_event_do_notifiers(bContext *C) /* Pass. */ } else { - ARegion *region; - /* XXX context in notifiers? */ CTX_wm_window_set(C, win); @@ -538,13 +535,13 @@ void wm_event_do_notifiers(bContext *C) # endif ED_screen_do_listen(C, note); - for (region = screen->regionbase.first; region; region = region->next) { + LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { ED_region_do_listen(win, NULL, region, note, scene); } ED_screen_areas_iter (win, screen, area) { ED_area_do_listen(win, area, note, scene); - for (region = area->regionbase.first; region; region = region->next) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { ED_region_do_listen(win, area, region, note, scene); } } @@ -1708,7 +1705,8 @@ static void wm_handler_op_context(bContext *C, wmEventHandler_Op *handler, const } if (region == NULL) { - for (region = area->regionbase.first; region; region = region->next) { + LISTBASE_FOREACH (ARegion *, region_iter, &area->regionbase) { + region = region_iter; if (region == handler->context.region) { break; } @@ -1911,13 +1909,6 @@ static wmKeyMapItem *wm_eventmatch_modal_keymap_items(const wmKeyMap *keymap, return NULL; } -wmKeyMapItem *WM_event_match_modal_keymap_item(const wmKeyMap *keymap, - wmOperator *op, - const wmEvent *event) -{ - return wm_eventmatch_modal_keymap_items(keymap, op, event); -} - /** * This function prepares events for use with #wmOperatorType.modal by: * @@ -2254,23 +2245,23 @@ static int wm_handler_fileselect_do(bContext *C, } } else { - wmWindow *temp_win; ScrArea *ctx_area = CTX_wm_area(C); - for (temp_win = wm->windows.first; temp_win; temp_win = temp_win->next) { - bScreen *screen = WM_window_get_active_screen(temp_win); + wmWindow *temp_win = NULL; + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + bScreen *screen = WM_window_get_active_screen(win); ScrArea *file_area = screen->areabase.first; if (screen->temp && (file_area->spacetype == SPACE_FILE)) { int win_size[2]; bool is_maximized; - ED_fileselect_window_params_get(temp_win, win_size, &is_maximized); + ED_fileselect_window_params_get(win, win_size, &is_maximized); ED_fileselect_params_to_userdef(file_area->spacedata.first, win_size, is_maximized); if (BLI_listbase_is_single(&file_area->spacedata)) { - BLI_assert(ctx_win != temp_win); + BLI_assert(ctx_win != win); - wm_window_close(C, wm, temp_win); + wm_window_close(C, wm, win); CTX_wm_window_set(C, ctx_win); /* #wm_window_close() NULLs. */ /* Some operators expect a drawable context (for EVT_FILESELECT_EXEC). */ @@ -2279,7 +2270,7 @@ static int wm_handler_fileselect_do(bContext *C, * opening (UI_BLOCK_MOVEMOUSE_QUIT). */ wm_get_cursor_position(ctx_win, &ctx_win->eventstate->x, &ctx_win->eventstate->y); wm->winactive = ctx_win; /* Reports use this... */ - if (handler->context.win == temp_win) { + if (handler->context.win == win) { handler->context.win = NULL; } } @@ -2290,6 +2281,7 @@ static int wm_handler_fileselect_do(bContext *C, ED_area_prevspace(C, file_area); } + temp_win = win; break; } } @@ -2492,14 +2484,13 @@ static int wm_handlers_do_keymap_with_gizmo_handler( { int action = WM_HANDLER_CONTINUE; bool keymap_poll = false; - wmKeyMapItem *kmi; PRINT("%s: checking '%s' ...", __func__, keymap->idname); if (WM_keymap_poll(C, keymap)) { keymap_poll = true; PRINT("pass\n"); - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { if (wm_eventmatch(event, kmi)) { PRINT("%s: item matched '%s'\n", __func__, kmi->idname); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 3ddac8babd4..5b21b2397e7 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -115,7 +115,6 @@ #include "GHOST_Path-api.h" #include "UI_interface.h" -#include "UI_interface_icons.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -178,22 +177,17 @@ bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm) */ static void wm_window_match_init(bContext *C, ListBase *wmlist) { - wmWindowManager *wm; - wmWindow *win, *active_win; - *wmlist = G_MAIN->wm; BLI_listbase_clear(&G_MAIN->wm); - active_win = CTX_wm_window(C); + wmWindow *active_win = CTX_wm_window(C); /* first wrap up running stuff */ /* code copied from wm_init_exit.c */ - for (wm = wmlist->first; wm; wm = wm->id.next) { - + LISTBASE_FOREACH (wmWindowManager *, wm, wmlist) { WM_jobs_kill_all(wm); - for (win = wm->windows.first; win; win = win->next) { - + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); @@ -519,11 +513,9 @@ void WM_file_autoexec_init(const char *filepath) void wm_file_read_report(bContext *C, Main *bmain) { ReportList *reports = NULL; - Scene *sce; - - for (sce = bmain->scenes.first; sce; sce = sce->id.next) { - if (sce->r.engine[0] && - BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + if (scene->r.engine[0] && + BLI_findstring(&R_engines, scene->r.engine, offsetof(RenderEngineType, idname)) == NULL) { if (reports == NULL) { reports = CTX_wm_reports(C); } @@ -532,8 +524,8 @@ void wm_file_read_report(bContext *C, Main *bmain) RPT_ERROR, "Engine '%s' not available for scene '%s' (an add-on may need to be installed " "or enabled)", - sce->r.engine, - sce->id.name + 2); + scene->r.engine, + scene->id.name + 2); } } @@ -1136,7 +1128,7 @@ void wm_homefile_read(bContext *C, if (use_userdef) { /* Clear keymaps because the current default keymap may have been initialized * from user preferences, which have been reset. */ - for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) { if (wm->defaultconf) { wm->defaultconf->flag &= ~KEYCONF_INIT_DEFAULT; } @@ -1236,8 +1228,7 @@ static void wm_history_file_write(void) fp = BLI_fopen(name, "w"); if (fp) { - struct RecentFile *recent; - for (recent = G.recent_files.first; recent; recent = recent->next) { + LISTBASE_FOREACH (RecentFile *, recent, &G.recent_files) { fprintf(fp, "%s\n", recent->filepath); } fclose(fp); @@ -1430,7 +1421,6 @@ static bool wm_file_write(bContext *C, ReportList *reports) { Main *bmain = CTX_data_main(C); - Library *li; int len; int ok = false; BlendThumbnail *thumb, *main_thumb; @@ -1459,7 +1449,7 @@ static bool wm_file_write(bContext *C, * its handy for scripts to save to a predefined name without blender editing it */ /* send the OnSave event */ - for (li = bmain->libraries.first; li; li = li->id.next) { + LISTBASE_FOREACH (Library *, li, &bmain->libraries) { if (BLI_path_cmp(li->filepath_abs, filepath) == 0) { BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath); return ok; @@ -3206,40 +3196,13 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, { wmGenericCallback *post_action = (wmGenericCallback *)arg1; Main *bmain = CTX_data_main(C); - const uiStyle *style = UI_style_get_dpi(); - const short icon_size = 64 * U.dpi_fac; - const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); - const int dialog_width = icon_size + (text_points_max * 34 * U.dpi_fac); - - /* By default, the space between icon and text/buttons will be equal to the 'columnspace', - this extra padding will add some space by increasing the left column width, - making the icon placement more symmetrical, between the block edge and the text. */ - const float icon_padding = 6.0f * U.dpi_fac; - /* Calculate icon column factor. */ - const float split_factor = ((float)icon_size + icon_padding) / - (float)(dialog_width - style->columnspace); uiBlock *block = UI_block_begin(C, region, close_file_dialog_name, UI_EMBOSS); - UI_block_flag_enable( block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - UI_block_emboss_set(block, UI_EMBOSS); - - uiLayout *block_layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style); - - /* Split layout to put alert icon on left side. */ - uiLayout *split_block = uiLayoutSplit(block_layout, split_factor, false); - - /* Alert Icon. */ - uiLayout *layout = uiLayoutRow(split_block, false); - /* Using 'align_left' with 'row' avoids stretching the icon along the width of column. */ - uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_LEFT); - uiDefButAlert(block, ALERT_ICON_QUESTION, 0, 0, icon_size, icon_size); - /* The rest of the content on the right. */ - layout = uiLayoutColumn(split_block, false); + uiLayout *layout = uiItemsAlertBox(block, 34, ALERT_ICON_QUESTION); /* Title. */ uiItemL_ex(layout, TIP_("Save changes before closing?"), ICON_NONE, true, false); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 926e61f4a0e..7984c2fd879 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -412,9 +412,7 @@ void WM_init_splash(bContext *C) /* free strings of open recent files */ static void free_openrecent(void) { - struct RecentFile *recent; - - for (recent = G.recent_files.first; recent; recent = recent->next) { + LISTBASE_FOREACH (RecentFile *, recent, &G.recent_files) { MEM_freeN(recent->filepath); } @@ -656,6 +654,7 @@ void WM_exit_ex(bContext *C, const bool do_python) * pieces of Blender using sound may exit cleanly, see also T50676. */ BKE_sound_exit(); + BKE_appdir_exit(); CLG_exit(); BKE_blender_atexit(); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index a1140c01d44..443a6fd1979 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -222,10 +222,8 @@ wmJob *WM_jobs_get( /* returns true if job runs, for UI (progress) indicators */ bool WM_jobs_test(wmWindowManager *wm, void *owner, int job_type) { - wmJob *wm_job; - /* job can be running or about to run (suspended) */ - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) { if (wm_job->owner == owner) { if (ELEM(job_type, WM_JOB_TYPE_ANY, wm_job->job_type)) { if (wm_job->running || wm_job->suspended) { @@ -266,17 +264,14 @@ static void wm_jobs_update_progress_bars(wmWindowManager *wm) /* if there are running jobs, set the global progress indicator */ if (jobs_progress > 0) { - wmWindow *win; float progress = total_progress / (float)jobs_progress; - for (win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { WM_progress_set(win, progress); } } else { - wmWindow *win; - - for (win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { WM_progress_clear(win); } } @@ -400,7 +395,6 @@ static void *do_job_thread(void *job_v) /* don't allow same startjob to be executed twice */ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test) { - wmJob *wm_job; bool suspend = false; /* job added with suspend flag, we wait 1 timer step before activating it */ @@ -410,7 +404,7 @@ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test) } else { /* check other jobs */ - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) { /* obvious case, no test needed */ if (wm_job == test || !wm_job->running) { continue; @@ -568,11 +562,7 @@ void WM_jobs_kill_all(wmWindowManager *wm) /* wait until every job ended, except for one owner (used in undo to keep screen job alive) */ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) { - wmJob *wm_job, *next_job; - - for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { - next_job = wm_job->next; - + LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->jobs) { if (wm_job->owner != owner) { wm_jobs_kill_job(wm, wm_job); } @@ -581,11 +571,7 @@ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type) { - wmJob *wm_job, *next_job; - - for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { - next_job = wm_job->next; - + LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->jobs) { if (!owner || wm_job->owner == owner) { if (ELEM(job_type, WM_JOB_TYPE_ANY, wm_job->job_type)) { wm_jobs_kill_job(wm, wm_job); @@ -597,9 +583,7 @@ void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type) /* signal job(s) from this owner or callback to stop, timer is required to get handled */ void WM_jobs_stop(wmWindowManager *wm, void *owner, void *startjob) { - wmJob *wm_job; - - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) { if (wm_job->owner == owner || wm_job->startjob == startjob) { if (wm_job->running) { wm_job->stop = true; @@ -613,17 +597,9 @@ void WM_jobs_kill(wmWindowManager *wm, void *owner, void (*startjob)(void *, short int *, short int *, float *)) { - wmJob *wm_job; - - wm_job = wm->jobs.first; - while (wm_job) { + LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->jobs) { if (wm_job->owner == owner || wm_job->startjob == startjob) { - wmJob *wm_job_kill = wm_job; - wm_job = wm_job->next; - wm_jobs_kill_job(wm, wm_job_kill); - } - else { - wm_job = wm_job->next; + wm_jobs_kill_job(wm, wm_job); } } } @@ -631,9 +607,7 @@ void WM_jobs_kill(wmWindowManager *wm, /* kill job entirely, also removes timer itself */ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt) { - wmJob *wm_job; - - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) { if (wm_job->wt == wt) { wm_jobs_kill_job(wm, wm_job); return; @@ -644,13 +618,8 @@ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt) /* hardcoded to event TIMERJOBS */ void wm_jobs_timer(wmWindowManager *wm, wmTimer *wt) { - wmJob *wm_job, *wm_jobnext; - - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_jobnext) { - wm_jobnext = wm_job->next; - + LISTBASE_FOREACH_MUTABLE (wmJob *, wm_job, &wm->jobs) { if (wm_job->wt == wt) { - /* running threads */ if (wm_job->threads.first) { @@ -735,9 +704,7 @@ void wm_jobs_timer(wmWindowManager *wm, wmTimer *wt) bool WM_jobs_has_running(wmWindowManager *wm) { - wmJob *wm_job; - - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + LISTBASE_FOREACH (wmJob *, wm_job, &wm->jobs) { if (wm_job->running) { return true; } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 1daab07812d..1f730be8c82 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -392,8 +392,6 @@ static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid) static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap) { wmKeyMap *keymapn = MEM_dupallocN(keymap); - wmKeyMapItem *kmi, *kmin; - wmKeyMapDiffItem *kmdi, *kmdin; keymapn->modal_items = keymap->modal_items; keymapn->poll = keymap->poll; @@ -401,14 +399,14 @@ static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap) BLI_listbase_clear(&keymapn->items); keymapn->flag &= ~(KEYMAP_UPDATE | KEYMAP_EXPANDED); - for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) { - kmdin = wm_keymap_diff_item_copy(kmdi); - BLI_addtail(&keymapn->items, kmdin); + LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &keymap->diff_items) { + wmKeyMapDiffItem *kmdi_new = wm_keymap_diff_item_copy(kmdi); + BLI_addtail(&keymapn->items, kmdi_new); } - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - kmin = wm_keymap_item_copy(kmi); - BLI_addtail(&keymapn->items, kmin); + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { + wmKeyMapItem *kmi_new = wm_keymap_item_copy(kmi); + BLI_addtail(&keymapn->items, kmi_new); } return keymapn; @@ -416,14 +414,11 @@ static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap) void WM_keymap_clear(wmKeyMap *keymap) { - wmKeyMapItem *kmi; - wmKeyMapDiffItem *kmdi; - - for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) { + LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &keymap->diff_items) { wm_keymap_diff_item_free(kmdi); } - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { wm_keymap_item_free(kmi); } @@ -558,20 +553,16 @@ bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap) { - wmKeyMapItem *kmi, *kmin; - - for (kmi = addonmap->items.first; kmi; kmi = kmi->next) { - kmin = wm_keymap_item_copy(kmi); - keymap_item_set_id(keymap, kmin); - BLI_addhead(&keymap->items, kmin); + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &addonmap->items) { + wmKeyMapItem *kmi_new = wm_keymap_item_copy(kmi); + keymap_item_set_id(keymap, kmi_new); + BLI_addhead(&keymap->items, kmi_new); } } static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle) { - wmKeyMapItem *kmi; - - for (kmi = km->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) { if (wm_keymap_item_equals(kmi, needle)) { return kmi; } @@ -582,9 +573,7 @@ static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *need static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle) { - wmKeyMapItem *kmi; - - for (kmi = km->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) { if (wm_keymap_item_equals_result(kmi, needle)) { return kmi; } @@ -596,21 +585,18 @@ static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapIte static void wm_keymap_diff( wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km) { - wmKeyMapItem *kmi, *to_kmi, *orig_kmi; - wmKeyMapDiffItem *kmdi; - - for (kmi = from_km->items.first; kmi; kmi = kmi->next) { - to_kmi = WM_keymap_item_find_id(to_km, kmi->id); + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &from_km->items) { + wmKeyMapItem *to_kmi = WM_keymap_item_find_id(to_km, kmi->id); if (!to_kmi) { /* remove item */ - kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + wmKeyMapDiffItem *kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); kmdi->remove_item = wm_keymap_item_copy(kmi); BLI_addtail(&diff_km->diff_items, kmdi); } else if (to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) { /* replace item */ - kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + wmKeyMapDiffItem *kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); kmdi->remove_item = wm_keymap_item_copy(kmi); kmdi->add_item = wm_keymap_item_copy(to_kmi); BLI_addtail(&diff_km->diff_items, kmdi); @@ -618,7 +604,7 @@ static void wm_keymap_diff( /* sync expanded flag back to original so we don't lose it on repatch */ if (to_kmi) { - orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id); + wmKeyMapItem *orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id); if (!orig_kmi && addon_km) { orig_kmi = wm_keymap_find_item_equals(addon_km, kmi); @@ -631,10 +617,10 @@ static void wm_keymap_diff( } } - for (kmi = to_km->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &to_km->items) { if (kmi->id < 0) { /* add item */ - kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + wmKeyMapDiffItem *kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); kmdi->add_item = wm_keymap_item_copy(kmi); BLI_addtail(&diff_km->diff_items, kmdi); } @@ -643,12 +629,9 @@ static void wm_keymap_diff( static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) { - wmKeyMapDiffItem *kmdi; - wmKeyMapItem *kmi_remove, *kmi_add; - - for (kmdi = diff_km->diff_items.first; kmdi; kmdi = kmdi->next) { + LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &diff_km->diff_items) { /* find item to remove */ - kmi_remove = NULL; + wmKeyMapItem *kmi_remove = NULL; if (kmdi->remove_item) { kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item); if (!kmi_remove) { @@ -660,7 +643,7 @@ static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) if (kmdi->add_item) { /* Do not re-add an already existing keymap item! See T42088. */ /* We seek only for exact copy here! See T42137. */ - kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item); + wmKeyMapItem *kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item); /** If kmi_add is same as kmi_remove (can happen in some cases, * typically when we got kmi_remove from #wm_keymap_find_item_equals_result()), @@ -712,11 +695,11 @@ static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *addonmap, wmKeyMap *usermap) { - wmKeyMap *km; int expanded = 0; /* remove previous keymap in list, we will replace it */ - km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid); + wmKeyMap *km = WM_keymap_list_find( + lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid); if (km) { expanded = (km->flag & (KEYMAP_EXPANDED | KEYMAP_CHILDREN_EXPANDED)); WM_keymap_clear(km); @@ -727,13 +710,12 @@ static wmKeyMap *wm_keymap_patch_update(ListBase *lb, if (usermap && !(usermap->flag & KEYMAP_DIFF)) { /* for compatibility with old user preferences with non-diff * keymaps we override the original entirely */ - wmKeyMapItem *kmi, *orig_kmi; km = wm_keymap_copy(usermap); /* try to find corresponding id's for items */ - for (kmi = km->items.first; kmi; kmi = kmi->next) { - orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi); + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) { + wmKeyMapItem *orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi); if (!orig_kmi) { orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi); } @@ -779,10 +761,8 @@ static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *addonmap, wmKeyMap *km) { - wmKeyMap *diffmap, *prevmap, *origmap; - /* create temporary default + addon keymap for diff */ - origmap = defaultmap; + wmKeyMap *origmap = defaultmap; if (addonmap) { defaultmap = wm_keymap_copy(defaultmap); @@ -790,14 +770,14 @@ static void wm_keymap_diff_update(ListBase *lb, } /* remove previous diff keymap in list, we will replace it */ - prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid); + wmKeyMap *prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid); if (prevmap) { WM_keymap_clear(prevmap); BLI_freelinkN(lb, prevmap); } /* create diff keymap */ - diffmap = wm_keymap_new(km->idname, km->spaceid, km->regionid); + wmKeyMap *diffmap = wm_keymap_new(km->idname, km->spaceid, km->regionid); diffmap->flag |= KEYMAP_DIFF; if (defaultmap->flag & KEYMAP_MODAL) { diffmap->flag |= KEYMAP_MODAL; @@ -833,9 +813,7 @@ static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid) { - wmKeyMap *km; - - for (km = lb->first; km; km = km->next) { + LISTBASE_FOREACH (wmKeyMap *, km, lb) { if (km->spaceid == spaceid && km->regionid == regionid) { if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { return km; @@ -851,9 +829,7 @@ wmKeyMap *WM_keymap_list_find_spaceid_or_empty(ListBase *lb, int spaceid, int regionid) { - wmKeyMap *km; - - for (km = lb->first; km; km = km->next) { + LISTBASE_FOREACH (wmKeyMap *, km, lb) { if (ELEM(km->spaceid, spaceid, SPACE_EMPTY) && km->regionid == regionid) { if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { return km; @@ -928,17 +904,16 @@ wmKeyMap *WM_modalkeymap_ensure(wmKeyConfig *keyconf, wmKeyMap *WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname) { - wmKeyMap *km; - - for (km = keyconf->keymaps.first; km; km = km->next) { + LISTBASE_FOREACH (wmKeyMap *, km, &keyconf->keymaps) { if (km->flag & KEYMAP_MODAL) { if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) { + return km; break; } } } - return km; + return NULL; } wmKeyMapItem *WM_modalkeymap_add_item( @@ -1015,17 +990,13 @@ static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km) { /* here we convert propvalue string values delayed, due to python keymaps * being created before the actual modal keymaps, so no modal_items */ - wmKeyMap *defaultkm; - wmKeyMapItem *kmi; - int propvalue; if (km && (km->flag & KEYMAP_MODAL) && !km->modal_items) { if (wm->defaultconf == NULL) { return; } - defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); - + wmKeyMap *defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0); if (!defaultkm) { return; } @@ -1035,8 +1006,9 @@ static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km) km->poll_modal_item = defaultkm->poll_modal_item; if (km->modal_items) { - for (kmi = km->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) { if (kmi->propvalue_str[0]) { + int propvalue; if (RNA_enum_value_from_id(km->modal_items, kmi->propvalue_str, &propvalue)) { kmi->propvalue = propvalue; } @@ -1510,8 +1482,6 @@ static wmKeyMapItem *wm_keymap_item_find(const bContext *C, const struct wmKeyMapItemFind_Params *params, wmKeyMap **r_keymap) { - wmKeyMapItem *found; - /* XXX Hack! Macro operators in menu entry have their whole props defined, * which is not the case for relevant keymap entries. * Could be good to check and harmonize this, @@ -1521,7 +1491,8 @@ static wmKeyMapItem *wm_keymap_item_find(const bContext *C, is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0); } - found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, params, r_keymap); + wmKeyMapItem *found = wm_keymap_item_find_props( + C, opname, opcontext, properties, is_strict, params, r_keymap); /* This block is *only* useful in one case: when op uses an enum menu in its prop member * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle, @@ -1556,8 +1527,6 @@ static wmKeyMapItem *wm_keymap_item_find(const bContext *C, /* Debug only, helps spotting mismatches between menu entries and shortcuts! */ if (G.debug & G_DEBUG_WM) { if (!found && is_strict && properties) { - wmKeyMap *km; - wmKeyMapItem *kmi; if (ot) { /* make a copy of the properties and set unset ones to their default values. */ PointerRNA opptr; @@ -1566,7 +1535,8 @@ static wmKeyMapItem *wm_keymap_item_find(const bContext *C, RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); WM_operator_properties_default(&opptr, true); - kmi = wm_keymap_item_find_props( + wmKeyMap *km; + wmKeyMapItem *kmi = wm_keymap_item_find_props( C, opname, opcontext, properties_default, is_strict, params, &km); if (kmi) { char kmi_str[128]; @@ -1687,15 +1657,13 @@ wmKeyMapItem *WM_key_event_operator_from_keymap(wmKeyMap *keymap, bool WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) { - int k1type, k2type; - if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE) { return 0; } /* take event mapping into account */ - k1type = WM_userdef_event_map(k1->type); - k2type = WM_userdef_event_map(k2->type); + int k1type = WM_userdef_event_map(k1->type); + int k2type = WM_userdef_event_map(k2->type); if (k1type != KM_ANY && k2type != KM_ANY && k1type != k2type) { return 0; @@ -1777,13 +1745,10 @@ void WM_keyconfig_update_operatortype(void) static bool wm_keymap_test_and_clear_update(wmKeyMap *km) { - wmKeyMapItem *kmi; - int update; - - update = (km->flag & KEYMAP_UPDATE); + int update = (km->flag & KEYMAP_UPDATE); km->flag &= ~KEYMAP_UPDATE; - for (kmi = km->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) { update = update || (kmi->flag & KMI_UPDATE); kmi->flag &= ~KMI_UPDATE; } @@ -1794,9 +1759,7 @@ static bool wm_keymap_test_and_clear_update(wmKeyMap *km) static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km) { wmKeyConfig *keyconf = WM_keyconfig_active(wm); - wmKeyMap *keymap; - - keymap = WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid); + wmKeyMap *keymap = WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid); if (!keymap && wm->defaultconf) { keymap = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid); } @@ -1806,9 +1769,6 @@ static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km) void WM_keyconfig_update(wmWindowManager *wm) { - wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn; - wmKeyMapItem *kmi; - wmKeyMapDiffItem *kmdi; bool compat_update = false; if (G.background) { @@ -1822,8 +1782,6 @@ void WM_keyconfig_update(wmWindowManager *wm) if (wm_keymap_update_flag & WM_KEYMAP_UPDATE_OPERATORTYPE) { /* an operatortype has been removed, this wont happen often * but when it does we have to check _every_ keymap item */ - wmKeyConfig *kc; - ListBase *keymaps_lb[] = { &U.user_keymaps, &wm->userconf->keymaps, @@ -1838,7 +1796,7 @@ void WM_keyconfig_update(wmWindowManager *wm) wm_keymap_item_properties_update_ot_from_list(keymaps_lb[i]); } - for (kc = wm->keyconfigs.first; kc; kc = kc->next) { + LISTBASE_FOREACH (wmKeyConfig *, kc, &wm->keyconfigs) { wm_keymap_item_properties_update_ot_from_list(&kc->keymaps); } @@ -1850,9 +1808,9 @@ void WM_keyconfig_update(wmWindowManager *wm) } /* update operator properties for non-modal user keymaps */ - for (km = U.user_keymaps.first; km; km = km->next) { + LISTBASE_FOREACH (wmKeyMap *, km, &U.user_keymaps) { if ((km->flag & KEYMAP_MODAL) == 0) { - for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { + LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &km->diff_items) { if (kmdi->add_item) { wm_keymap_item_properties_set(kmdi->add_item); } @@ -1861,19 +1819,19 @@ void WM_keyconfig_update(wmWindowManager *wm) } } - for (kmi = km->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) { wm_keymap_item_properties_set(kmi); } } } /* update U.user_keymaps with user key configuration changes */ - for (km = wm->userconf->keymaps.first; km; km = km->next) { + LISTBASE_FOREACH (wmKeyMap *, km, &wm->userconf->keymaps) { /* only diff if the user keymap was modified */ if (wm_keymap_test_and_clear_update(km)) { /* find keymaps */ - defaultmap = wm_keymap_preset(wm, km); - addonmap = WM_keymap_list_find( + wmKeyMap *defaultmap = wm_keymap_preset(wm, km); + wmKeyMap *addonmap = WM_keymap_list_find( &wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); /* diff */ @@ -1884,18 +1842,20 @@ void WM_keyconfig_update(wmWindowManager *wm) } /* create user key configuration from preset + addon + user preferences */ - for (km = wm->defaultconf->keymaps.first; km; km = km->next) { + LISTBASE_FOREACH (wmKeyMap *, km, &wm->defaultconf->keymaps) { /* find keymaps */ - defaultmap = wm_keymap_preset(wm, km); - addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); - usermap = WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid); + wmKeyMap *defaultmap = wm_keymap_preset(wm, km); + wmKeyMap *addonmap = WM_keymap_list_find( + &wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); + wmKeyMap *usermap = WM_keymap_list_find( + &U.user_keymaps, km->idname, km->spaceid, km->regionid); /* For now only the default map defines modal key-maps, * if we support modal keymaps for 'addonmap', these will need to be enabled too. */ wm_user_modal_keymap_set_items(wm, defaultmap); /* add */ - kmn = wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); + wmKeyMap *kmn = wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); if (kmn) { kmn->modal_items = km->modal_items; @@ -1928,14 +1888,12 @@ void WM_keyconfig_update(wmWindowManager *wm) wmKeyMap *WM_keymap_active(const wmWindowManager *wm, wmKeyMap *keymap) { - wmKeyMap *km; - if (!keymap) { return NULL; } /* first user defined keymaps */ - km = WM_keymap_list_find( + wmKeyMap *km = WM_keymap_list_find( &wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if (km) { @@ -1955,16 +1913,13 @@ wmKeyMap *WM_keymap_active(const wmWindowManager *wm, wmKeyMap *keymap) void WM_keymap_item_restore_to_default(wmWindowManager *wm, wmKeyMap *keymap, wmKeyMapItem *kmi) { - wmKeyMap *defaultmap, *addonmap; - wmKeyMapItem *orig; - if (!keymap) { return; } /* construct default keymap from preset + addons */ - defaultmap = wm_keymap_preset(wm, keymap); - addonmap = WM_keymap_list_find( + wmKeyMap *defaultmap = wm_keymap_preset(wm, keymap); + wmKeyMap *addonmap = WM_keymap_list_find( &wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if (addonmap) { @@ -1973,7 +1928,7 @@ void WM_keymap_item_restore_to_default(wmWindowManager *wm, wmKeyMap *keymap, wm } /* find original item */ - orig = WM_keymap_item_find_id(defaultmap, kmi->id); + wmKeyMapItem *orig = WM_keymap_item_find_id(defaultmap, kmi->id); if (orig) { /* restore to original */ @@ -2030,9 +1985,7 @@ void WM_keymap_restore_to_default(wmKeyMap *keymap, wmWindowManager *wm) wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id) { - wmKeyMapItem *kmi; - - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { if (kmi->id == id) { return kmi; } diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c index 7621862708e..4c4fd2b1a8e 100644 --- a/source/blender/windowmanager/intern/wm_operator_type.c +++ b/source/blender/windowmanager/intern/wm_operator_type.c @@ -572,9 +572,7 @@ wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char static void wm_operatortype_free_macro(wmOperatorType *ot) { - wmOperatorTypeMacro *otmacro; - - for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) { + LISTBASE_FOREACH (wmOperatorTypeMacro *, otmacro, &ot->macro) { if (otmacro->ptr) { WM_operator_properties_free(otmacro->ptr); MEM_freeN(otmacro->ptr); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 9eedd5b2faa..a5d23365df3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -84,6 +84,7 @@ #include "IMB_imbuf_types.h" +#include "ED_fileselect.h" #include "ED_numinput.h" #include "ED_screen.h" #include "ED_undo.h" @@ -496,7 +497,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr } case SPACE_FILE: { const SpaceFile *sfile = (SpaceFile *)space_data; - const FileSelectParams *params = sfile->params; + const FileSelectParams *params = ED_fileselect_get_active_params(sfile); TEST_PTR_DATA_TYPE("space_data", RNA_FileSelectParams, ptr, params); break; } diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index d732393b631..a3619a69152 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -256,71 +256,62 @@ void WM_OT_splash(wmOperatorType *ot) static uiBlock *wm_block_create_about(bContext *C, ARegion *region, void *UNUSED(arg)) { const uiStyle *style = UI_style_get_dpi(); - const short logo_size = 128 * U.dpi_fac; const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); - const int dialog_width = logo_size + (text_points_max * 32 * U.dpi_fac); - - /* Calculate icon column factor. */ - const float split_factor = (float)logo_size / (float)(dialog_width - style->columnspace); + const int dialog_width = text_points_max * 42 * U.dpi_fac; uiBlock *block = UI_block_begin(C, region, "about", UI_EMBOSS); - UI_block_flag_enable( - block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); + UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); - UI_block_emboss_set(block, UI_EMBOSS); - uiLayout *block_layout = UI_block_layout( + uiLayout *layout = UI_block_layout( block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style); - /* Split layout to put Blender logo on left side. */ - uiLayout *split_block = uiLayoutSplit(block_layout, split_factor, false); - - /* Blender Logo. */ - uiLayout *layout = uiLayoutColumn(split_block, false); - uiDefButAlert(block, ALERT_ICON_BLENDER, 0, 0, 0, logo_size); - - /* The rest of the content on the right. */ - layout = uiLayoutColumn(split_block, false); - - uiLayoutSetScaleY(layout, 0.7f); - - uiItemS_ex(layout, 1.0f); - - /* Title. */ - uiItemL_ex(layout, "Blender", ICON_NONE, true, false); + /* Blender logo. */ +#ifndef WITH_HEADLESS + extern char datatoc_blender_logo_png[]; + extern int datatoc_blender_logo_png_size; - /* Version. */ - uiItemL(layout, BKE_blender_version_string(), ICON_NONE); + const uchar *blender_logo_data = (const uchar *)datatoc_blender_logo_png; + size_t blender_logo_data_size = datatoc_blender_logo_png_size; + ImBuf *ibuf = IMB_ibImageFromMemory( + blender_logo_data, blender_logo_data_size, IB_rect, NULL, "blender_logo"); - uiItemS_ex(layout, 3.0f); + if (ibuf) { + int width = 0.5 * dialog_width; + int height = (width * ibuf->y) / ibuf->x; -#ifdef WITH_BUILDINFO + IMB_premultiply_alpha(ibuf); + IMB_scaleImBuf(ibuf, width, height); - extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[]; + bTheme *btheme = UI_GetTheme(); + const uchar *color = btheme->tui.wcol_menu_back.text_sel; - char str_buf[256] = "\0"; - BLI_snprintf(str_buf, sizeof(str_buf), "Date: %s %s", build_commit_date, build_commit_time); - uiItemL(layout, str_buf, ICON_NONE); + /* The top margin. */ + uiLayout *row = uiLayoutRow(layout, false); + uiItemS_ex(row, 0.2f); - BLI_snprintf(str_buf, sizeof(str_buf), "Hash: %s", build_hash); - uiItemL(layout, str_buf, ICON_NONE); + /* The logo image. */ + row = uiLayoutRow(layout, false); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); + uiDefButImage(block, ibuf, 0, U.widget_unit, width, height, color); - BLI_snprintf(str_buf, sizeof(str_buf), "Branch: %s", build_branch); - uiItemL(layout, str_buf, ICON_NONE); + /* Padding below the logo. */ + row = uiLayoutRow(layout, false); + uiItemS_ex(row, 2.7f); + } +#endif /* WITH_HEADLESS */ -#endif /* WITH_BUILDINFO */ + uiLayout *col = uiLayoutColumn(layout, true); - uiItemS_ex(layout, 1.5f); + uiItemL_ex(col, N_("Blender"), ICON_NONE, true, false); MenuType *mt = WM_menutype_find("WM_MT_splash_about", true); if (mt) { - UI_menutype_draw(C, mt, layout); + UI_menutype_draw(C, mt, col); } - uiItemS_ex(layout, 2.0f); - - UI_block_bounds_set_centered(block, 14 * U.dpi_fac); + UI_block_bounds_set_centered(block, 22 * U.dpi_fac); return block; } diff --git a/source/blender/windowmanager/intern/wm_surface.c b/source/blender/windowmanager/intern/wm_surface.c index 4139574460b..715f72d70cf 100644 --- a/source/blender/windowmanager/intern/wm_surface.c +++ b/source/blender/windowmanager/intern/wm_surface.c @@ -116,8 +116,7 @@ void wm_surfaces_free(void) { wm_surface_clear_drawable(); - for (wmSurface *surf = global_surface_list.first, *surf_next; surf; surf = surf_next) { - surf_next = surf->next; + LISTBASE_FOREACH_MUTABLE (wmSurface *, surf, &global_surface_list) { wm_surface_remove(surf); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 589b8e2f156..14798653a31 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -2261,6 +2261,17 @@ Scene *WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen return NULL; } +ViewLayer *WM_windows_view_layer_get_from_screen(const wmWindowManager *wm, const bScreen *screen) +{ + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + if (WM_window_get_active_screen(win) == screen) { + return WM_window_get_active_view_layer(win); + } + } + + return NULL; +} + WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm, const bScreen *screen) { LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index c6a1c565350..2651ec2554f 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -667,9 +667,6 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo # else printf(" $TMP or $TMPDIR Store temporary files here.\n"); # endif -# ifdef WITH_SDL - printf(" $SDL_AUDIODRIVER LibSDL audio driver - alsa, esd, dma.\n"); -# endif exit(0); diff --git a/source/tools b/source/tools -Subproject 7011d02c292ac1c91a5c9cc1a075ea2727982ce +Subproject d7d7e9d41f7499aa4639f96c843156ff834385b diff --git a/tests/python/bl_blendfile_io.py b/tests/python/bl_blendfile_io.py index 49814ea5902..2c27b60f34e 100644 --- a/tests/python/bl_blendfile_io.py +++ b/tests/python/bl_blendfile_io.py @@ -20,7 +20,9 @@ class TestBlendFileSaveLoadBasic(TestHelper): output_dir = self.args.output_dir self.ensure_path(output_dir) - output_path = os.path.join(output_dir, "blendfile.blend") + + # Take care to keep the name unique so multiple test jobs can run at once. + output_path = os.path.join(output_dir, "blendfile_io.blend") orig_data = self.blender_data_to_tuple(bpy.data, "orig_data 1") diff --git a/tests/python/bl_blendfile_liblink.py b/tests/python/bl_blendfile_liblink.py index b48deb7bd7b..fc618314216 100644 --- a/tests/python/bl_blendfile_liblink.py +++ b/tests/python/bl_blendfile_liblink.py @@ -21,6 +21,7 @@ class TestBlendLibLinkSaveLoadBasic(TestHelper): output_dir = self.args.output_dir self.ensure_path(output_dir) + # Take care to keep the name unique so multiple test jobs can run at once. output_path = os.path.join(output_dir, "blendlib.blend") bpy.ops.wm.save_as_mainfile(filepath=output_path, check_existing=False, compress=False) diff --git a/tests/python/bl_constraints.py b/tests/python/bl_constraints.py index 4deabc5f541..279c896c6af 100644 --- a/tests/python/bl_constraints.py +++ b/tests/python/bl_constraints.py @@ -301,6 +301,80 @@ class ObjectSolverTest(AbstractConstraintTests): self.matrix_test('Object Solver.owner', initial_matrix) +class CustomSpaceTest(AbstractConstraintTests): + layer_collection = 'Custom Space' + + def test_loc_like_object(self): + """Custom Space: basic custom space evaluation for objects""" + loc_like_constraint = bpy.data.objects["Custom Space.object.owner"].constraints["Copy Location"] + loc_like_constraint.use_x = True + loc_like_constraint.use_y = True + loc_like_constraint.use_z = True + self.matrix_test('Custom Space.object.owner', Matrix(( + (1.0, 0.0, -2.9802322387695312e-08, -0.01753106713294983), + (0.0, 1.0, 0.0, -0.08039519190788269), + (-2.9802322387695312e-08, 5.960464477539063e-08, 1.0, 0.1584688425064087), + (0.0, 0.0, 0.0, 1.0), + ))) + loc_like_constraint.use_x = False + self.matrix_test('Custom Space.object.owner', Matrix(( + (1.0, 0.0, -2.9802322387695312e-08, 0.18370598554611206), + (0.0, 1.0, 0.0, 0.47120195627212524), + (-2.9802322387695312e-08, 5.960464477539063e-08, 1.0, -0.16521614789962769), + (0.0, 0.0, 0.0, 1.0), + ))) + loc_like_constraint.use_y = False + self.matrix_test('Custom Space.object.owner', Matrix(( + (1.0, 0.0, -2.9802322387695312e-08, -0.46946945786476135), + (0.0, 1.0, 0.0, 0.423120379447937), + (-2.9802322387695312e-08, 5.960464477539063e-08, 1.0, -0.6532361507415771), + (0.0, 0.0, 0.0, 1.0), + ))) + loc_like_constraint.use_z = False + loc_like_constraint.use_y = True + self.matrix_test('Custom Space.object.owner', Matrix(( + (1.0, 0.0, -2.9802322387695312e-08, -0.346824586391449), + (0.0, 1.0, 0.0, 1.0480815172195435), + (-2.9802322387695312e-08, 5.960464477539063e-08, 1.0, 0.48802000284194946), + (0.0, 0.0, 0.0, 1.0), + ))) + + def test_loc_like_armature(self): + """Custom Space: basic custom space evaluation for bones""" + loc_like_constraint = bpy.data.objects["Custom Space.armature.owner"].pose.bones["Bone"].constraints["Copy Location"] + loc_like_constraint.use_x = True + loc_like_constraint.use_y = True + loc_like_constraint.use_z = True + self.bone_matrix_test('Custom Space.armature.owner', 'Bone', Matrix(( + (0.4556015729904175, -0.03673229366540909, -0.8894257545471191, -0.01753103733062744), + (-0.45956411957740784, -0.8654094934463501, -0.19966775178909302, -0.08039522171020508), + (-0.762383222579956, 0.49971696734428406, -0.4111628830432892, 0.1584688425064087), + (0.0, 0.0, 0.0, 1.0), + ))) + loc_like_constraint.use_x = False + self.bone_matrix_test('Custom Space.armature.owner', 'Bone', Matrix(( + (0.4556015729904175, -0.03673229366540909, -0.8894257545471191, -0.310153603553772), + (-0.45956411957740784, -0.8654094934463501, -0.19966775178909302, -0.8824828863143921), + (-0.762383222579956, 0.49971696734428406, -0.4111628830432892, 0.629145085811615), + (0.0, 0.0, 0.0, 1.0), + ))) + loc_like_constraint.use_y = False + self.bone_matrix_test('Custom Space.armature.owner', 'Bone', Matrix(( + (0.4556015729904175, -0.03673229366540909, -0.8894257545471191, -1.0574829578399658), + (-0.45956411957740784, -0.8654094934463501, -0.19966775178909302, -0.937495231628418), + (-0.762383222579956, 0.49971696734428406, -0.4111628830432892, 0.07077804207801819), + (0.0, 0.0, 0.0, 1.0), + ))) + loc_like_constraint.use_z = False + loc_like_constraint.use_y = True + self.bone_matrix_test('Custom Space.armature.owner', 'Bone', Matrix(( + (0.4556015729904175, -0.03673229366540909, -0.8894257545471191, -0.25267064571380615), + (-0.45956411957740784, -0.8654094934463501, -0.19966775178909302, -0.9449876546859741), + (-0.762383222579956, 0.49971696734428406, -0.4111628830432892, 0.5583670735359192), + (0.0, 0.0, 0.0, 1.0), + ))) + + def main(): global args import argparse diff --git a/tests/python/eevee_render_tests.py b/tests/python/eevee_render_tests.py index 4f1eba3348f..6a21afc7c9a 100644 --- a/tests/python/eevee_render_tests.py +++ b/tests/python/eevee_render_tests.py @@ -137,7 +137,7 @@ def main(): report = render_report.Report("Eevee", output_dir, idiff) report.set_pixelated(True) report.set_reference_dir("eevee_renders") - report.set_compare_engines('cycles', 'CPU') + report.set_compare_engine('cycles', 'CPU') ok = report.run(test_dir, blender, get_arguments, batch=True) sys.exit(not ok) |