diff options
author | Nathan Craddock <nzcraddock@gmail.com> | 2019-08-16 01:11:28 +0300 |
---|---|---|
committer | Nathan Craddock <nzcraddock@gmail.com> | 2019-08-16 01:16:51 +0300 |
commit | d156139cbccc16ee457974455624cf75e91a1670 (patch) | |
tree | 7c7c720bcf1696c043ee62d6d0d77000742e8fe9 | |
parent | 28ee7e60c5cdc5a123b6aed9fc2367d3c5815a8d (diff) | |
parent | 9dab57a9f829881dad1e659b53413ded15ec085e (diff) |
Merge branch 'master' into soc-2019-outliner
105 files changed, 2070 insertions, 680 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ced6e1d76d..16ac322ebdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,6 +182,8 @@ if(UNIX AND NOT APPLE) set(_init_SDL OFF) set(_init_FFTW3 OFF) set(_init_OPENSUBDIV OFF) + set(_init_OPENVDB OFF) + set(_init_OPENIMAGEDENOISE OFF) elseif(WIN32) set(_init_JACK OFF) elseif(APPLE) @@ -237,11 +239,12 @@ option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLO # Compositor option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON) +option(WITH_OPENIMAGEDENOISE "Enable the OpenImageDenoise compositing node" ${_init_OPENIMAGEDENOISE}) option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" ${_init_OPENSUBDIV}) -option(WITH_OPENVDB "Enable features relying on OpenVDB" OFF) -option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" OFF) +option(WITH_OPENVDB "Enable features relying on OpenVDB" ${_init_OPENVDB}) +option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" ${_init_OPENVDB}) option(WITH_OPENVDB_3_ABI_COMPATIBLE "Assume OpenVDB library has been compiled with version 3 ABI compatibility" OFF) mark_as_advanced(WITH_OPENVDB_3_ABI_COMPATIBLE) @@ -1760,6 +1763,7 @@ if(FIRST_RUN) info_cfg_option(WITH_CYCLES) info_cfg_option(WITH_FREESTYLE) info_cfg_option(WITH_OPENCOLORIO) + info_cfg_option(WITH_OPENIMAGEDENOISE) info_cfg_option(WITH_OPENVDB) info_cfg_option(WITH_ALEMBIC) diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index 0dbd3b572cf..1b387cb86a2 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -97,6 +97,7 @@ if(UNIX AND NOT APPLE) else() include(cmake/pugixml.cmake) endif() +include(cmake/openimagedenoise.cmake) if(WITH_WEBP) include(cmake/webp.cmake) diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake index 27bcd184c44..97e4a6b69d4 100644 --- a/build_files/build_environment/cmake/harvest.cmake +++ b/build_files/build_environment/cmake/harvest.cmake @@ -166,6 +166,8 @@ harvest(openimageio/bin openimageio/bin "maketx") harvest(openimageio/bin openimageio/bin "oiiotool") harvest(openimageio/include openimageio/include "*") harvest(openimageio/lib openimageio/lib "*.a") +harvest(openimagedenoise/include openimagedenoise/include "*") +harvest(openimagedenoise/lib openimagedenoise/lib "*.a") harvest(openjpeg/include/openjpeg-2.3 openjpeg/include "*.h") harvest(openjpeg/lib openjpeg/lib "*.a") harvest(opensubdiv/include opensubdiv/include "*.h") diff --git a/build_files/build_environment/cmake/openimagedenoise.cmake b/build_files/build_environment/cmake/openimagedenoise.cmake new file mode 100644 index 00000000000..b20bb838ede --- /dev/null +++ b/build_files/build_environment/cmake/openimagedenoise.cmake @@ -0,0 +1,61 @@ +# ***** 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 ***** + + +set(OIDN_EXTRA_ARGS + -DWITH_EXAMPLE=OFF + -DWITH_TEST=OFF + -DTBB_ROOT=${LIBDIR}/tbb + -DTBB_STATIC_LIB=ON + -DOIDN_STATIC_LIB=ON +) + +ExternalProject_Add(external_openimagedenoise + URL ${OIDN_URI} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH MD5=${OIDN_HASH} + PREFIX ${BUILD_DIR}/openimagedenoise + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openimagedenoise ${DEFAULT_CMAKE_FLAGS} ${OIDN_EXTRA_ARGS} + PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/openimagedenoise/src/external_openimagedenoise < ${PATCH_DIR}/openimagedenoise.diff + INSTALL_DIR ${LIBDIR}/openimagedenoise +) + +add_dependencies( + external_openimagedenoise + external_tbb +) + +if(WIN32) + if(BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_openimagedenoise after_install + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openimagedenoise/include ${HARVEST_TARGET}/openimagedenoise/include + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/openimagedenoise.lib ${HARVEST_TARGET}/openimagedenoise/lib/openimagedenoise.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/common.lib ${HARVEST_TARGET}/openimagedenoise/lib/common.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/mkldnn.lib ${HARVEST_TARGET}/openimagedenoise/lib/mkldnn.lib + DEPENDEES install + ) + endif() + if(BUILD_MODE STREQUAL Debug) + ExternalProject_Add_Step(external_openimagedenoise after_install + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/openimagedenoise.lib ${HARVEST_TARGET}/openimagedenoise/lib/openimagedenoise_d.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/common.lib ${HARVEST_TARGET}/openimagedenoise/lib/common_d.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/mkldnn.lib ${HARVEST_TARGET}/openimagedenoise/lib/mkldnn_d.lib + DEPENDEES install + ) + endif() +endif() diff --git a/build_files/build_environment/cmake/tbb.cmake b/build_files/build_environment/cmake/tbb.cmake index 77f061e30d0..26c52e00c76 100644 --- a/build_files/build_environment/cmake/tbb.cmake +++ b/build_files/build_environment/cmake/tbb.cmake @@ -18,7 +18,7 @@ set(TBB_EXTRA_ARGS -DTBB_BUILD_SHARED=Off - -DTBB_BUILD_TBBMALLOC=Off + -DTBB_BUILD_TBBMALLOC=On -DTBB_BUILD_TBBMALLOC_PROXY=Off -DTBB_BUILD_STATIC=On ) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 3ee6a4920ed..c3b713096d6 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -302,3 +302,7 @@ set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7) set(EMBREE_VERSION 3.2.4) set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip) set(EMBREE_HASH 3d4a1147002ff43939d45140aa9d6fb8) + +set(OIDN_VERSION 1.0.0) +set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.zip) +set(OIDN_HASH 19fe67b0164e8f020ac8a4f520defe60) diff --git a/build_files/build_environment/patches/openimagedenoise.diff b/build_files/build_environment/patches/openimagedenoise.diff new file mode 100644 index 00000000000..08d7a397a6d --- /dev/null +++ b/build_files/build_environment/patches/openimagedenoise.diff @@ -0,0 +1,119 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 70ec895..e616b63 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -178,7 +178,9 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY SOVERSION "0") + ## Open Image Denoise examples + ## ---------------------------------------------------------------------------- + +-add_subdirectory(examples) ++if(WITH_EXAMPLE) ++ add_subdirectory(examples) ++endif() + + ## ---------------------------------------------------------------------------- + ## Open Image Denoise install and packaging +Submodule mkl-dnn contains modified content +diff --git a/mkl-dnn/cmake/TBB.cmake b/mkl-dnn/cmake/TBB.cmake +index 0711e699..c14210b6 100644 +--- a/mkl-dnn/cmake/TBB.cmake ++++ b/mkl-dnn/cmake/TBB.cmake +@@ -90,8 +90,8 @@ if(WIN32) + NO_DEFAULT_PATH + ) + set(TBB_LIB_DIR ${TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER}) +- find_library(TBB_LIBRARY tbb PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) +- find_library(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) ++ find_library(TBB_LIBRARY tbb_static PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) ++ find_library(TBB_LIBRARY_MALLOC tbbmalloc_static PATHS ${TBB_LIB_DIR} ${TBB_ROOT}/lib NO_DEFAULT_PATH) + endif() + + else() +@@ -138,13 +138,13 @@ else() + set(TBB_LIBRARY_MALLOC TBB_LIBRARY_MALLOC-NOTFOUND) + if(APPLE) + find_path(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH) +- find_library(TBB_LIBRARY tbb PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH) +- find_library(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH) ++ find_library(TBB_LIBRARY tbb_static PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH) ++ find_library(TBB_LIBRARY_MALLOC tbbmalloc_static PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH) + else() + find_path(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH) + set(TBB_HINTS HINTS ${TBB_ROOT}/lib/intel64/gcc4.4 ${TBB_ROOT}/lib ${TBB_ROOT}/lib64 PATHS /usr/libx86_64-linux-gnu/) +- find_library(TBB_LIBRARY tbb ${TBB_HINTS}) +- find_library(TBB_LIBRARY_MALLOC tbbmalloc ${TBB_HINTS}) ++ find_library(TBB_LIBRARY tbb_static ${TBB_HINTS}) ++ find_library(TBB_LIBRARY_MALLOC tbbmalloc_static ${TBB_HINTS}) + endif() + endif() + +diff '--ignore-matching-lines=:' -ur '--exclude=*.svn*' -u -r +--- a/cmake/install.cmake 2019-08-12 18:02:20.794402575 +0200 ++++ b/cmake/install.cmake 2019-08-12 18:06:07.470045703 +0200 +@@ -18,6 +18,13 @@ + ## Install library + ## ---------------------------------------------------------------------------- + ++if(UNIX) ++install(FILES ++ ${CMAKE_BINARY_DIR}/libOpenImageDenoise.a ++ ${CMAKE_BINARY_DIR}/libmkldnn.a ++ ${CMAKE_BINARY_DIR}/libcommon.a ++ DESTINATION ${CMAKE_INSTALL_LIBDIR}) ++else() + install(TARGETS ${PROJECT_NAME} + EXPORT + ${PROJECT_NAME}_Export +@@ -38,6 +45,7 @@ + DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel + ) + endif() ++endif() + + ## ---------------------------------------------------------------------------- + ## Install headers +@@ -78,6 +86,7 @@ + ## Install CMake configuration files + ## ---------------------------------------------------------------------------- + ++if(NOT UNIX) + install(EXPORT ${PROJECT_NAME}_Export + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + #NAMESPACE ${PROJECT_NAME}:: +@@ -92,3 +101,4 @@ + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + COMPONENT devel + ) ++endif() +diff '--ignore-matching-lines=:' -ur '--exclude=*.svn*' -u -r +--- a/CMakeLists.txt 2019-08-12 14:22:00.974078598 +0200 ++++ b/CMakeLists.txt 2019-08-12 18:05:05.949057375 +0200 +@@ -14,7 +14,11 @@ + ## limitations under the License. ## + ## ======================================================================== ## + +-cmake_minimum_required(VERSION 3.1) ++if(UNIX) ++ cmake_minimum_required(VERSION 3.1) ++else() ++ cmake_minimum_required(VERSION 3.13) ++endif() + + set(OIDN_VERSION_MAJOR 1) + set(OIDN_VERSION_MINOR 0) +@@ -32,13 +36,8 @@ + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") + + # Build as shared or static library +-if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") +- option(OIDN_STATIC_LIB "Build Open Image Denoise as a static library.") +- mark_as_advanced(CLEAR OIDN_STATIC_LIB) +-else() +- set(OIDN_STATIC_LIB OFF CACHE BOOL "Build Open Image Denoise as a static library." FORCE) +- mark_as_advanced(OIDN_STATIC_LIB) +-endif() ++option(OIDN_STATIC_LIB "Build Open Image Denoise as a static library.") ++mark_as_advanced(CLEAR OIDN_STATIC_LIB) + if(OIDN_STATIC_LIB) + set(OIDN_LIB_TYPE STATIC) + else() diff --git a/build_files/cmake/Modules/FindOpenImageDenoise.cmake b/build_files/cmake/Modules/FindOpenImageDenoise.cmake new file mode 100644 index 00000000000..85ba10b14e4 --- /dev/null +++ b/build_files/cmake/Modules/FindOpenImageDenoise.cmake @@ -0,0 +1,101 @@ +# - Find OpenImageDenoise library +# Find the native OpenImageDenoise includes and library +# This module defines +# OPENIMAGEDENOISE_INCLUDE_DIRS, where to find oidn.h, Set when +# OPENIMAGEDENOISE is found. +# OPENIMAGEDENOISE_LIBRARIES, libraries to link against to use OpenImageDenoise. +# OPENIMAGEDENOISE_ROOT_DIR, The base directory to search for OpenImageDenoise. +# This can also be an environment variable. +# OPENIMAGEDENOISE_FOUND, If false, do not try to use OpenImageDenoise. +# +# also defined, but not for general use are +# OPENIMAGEDENOISE_LIBRARY, where to find the OpenImageDenoise library. + +#============================================================================= +# Copyright 2019 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# If OPENIMAGEDENOISE_ROOT_DIR was defined in the environment, use it. +IF(NOT OPENIMAGEDENOISE_ROOT_DIR AND NOT $ENV{OPENIMAGEDENOISE_ROOT_DIR} STREQUAL "") + SET(OPENIMAGEDENOISE_ROOT_DIR $ENV{OPENIMAGEDENOISE_ROOT_DIR}) +ENDIF() + +SET(_openimagedenoise_SEARCH_DIRS + ${OPENIMAGEDENOISE_ROOT_DIR} + /usr/local + /sw # Fink + /opt/local # DarwinPorts + /opt/lib/openimagedenoise +) + +FIND_PATH(OPENIMAGEDENOISE_INCLUDE_DIR + NAMES + OpenImageDenoise/oidn.h + HINTS + ${_openimagedenoise_SEARCH_DIRS} + PATH_SUFFIXES + include +) + +SET(_openimagedenoise_FIND_COMPONENTS + OpenImageDenoise + common + mkldnn +) + +SET(_openimagedenoise_LIBRARIES) +FOREACH(COMPONENT ${_openimagedenoise_FIND_COMPONENTS}) + STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) + + FIND_LIBRARY(OPENIMAGEDENOISE_${UPPERCOMPONENT}_LIBRARY + NAMES + ${COMPONENT} + HINTS + ${_openimagedenoise_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + LIST(APPEND _openimagedenoise_LIBRARIES "${OPENIMAGEDENOISE_${UPPERCOMPONENT}_LIBRARY}") +ENDFOREACH() + +FIND_LIBRARY(OPENIMAGEDENOISE_LIBRARY + NAMES + OpenImageDenoise + HINTS + ${_openimagedenoise_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +# handle the QUIETLY and REQUIRED arguments and set OPENIMAGEDENOISE_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENIMAGEDENOISE DEFAULT_MSG + OPENIMAGEDENOISE_LIBRARY OPENIMAGEDENOISE_INCLUDE_DIR) + +IF(OPENIMAGEDENOISE_FOUND) + SET(OPENIMAGEDENOISE_LIBRARIES ${_openimagedenoise_LIBRARIES}) + SET(OPENIMAGEDENOISE_INCLUDE_DIRS ${OPENIMAGEDENOISE_INCLUDE_DIR}) +ELSE() + SET(OPENIMAGEDENOISE_FOUND FALSE) +ENDIF() + +MARK_AS_ADVANCED( + OPENIMAGEDENOISE_INCLUDE_DIR +) + +FOREACH(COMPONENT ${_openimagedenoise_FIND_COMPONENTS}) + STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) + MARK_AS_ADVANCED(OPENIMAGEDENOISE_${UPPERCOMPONENT}_LIBRARY) +ENDFOREACH() + +UNSET(_openimagedenoise_SEARCH_DIRS) +UNSET(_openimagedenoise_FIND_COMPONENTS) +UNSET(_openimagedenoise_LIBRARIES) diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index 6786cb5ce37..75c5e0f34c1 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -40,6 +40,7 @@ set(WITH_AUDASPACE ON CACHE BOOL "" FORCE) set(WITH_OPENAL ON CACHE BOOL "" FORCE) set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE) set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE) +set(WITH_OPENIMAGEDENOISE ON CACHE BOOL "" FORCE) set(WITH_OPENMP ON CACHE BOOL "" FORCE) set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE) set(WITH_OPENVDB ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index b85176d37f3..6596d1db674 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -45,6 +45,7 @@ set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE) set(WITH_OPENAL OFF CACHE BOOL "" FORCE) set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE) set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE) +set(WITH_OPENIMAGEDENOISE OFF CACHE BOOL "" FORCE) set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE) set(WITH_OPENMP OFF CACHE BOOL "" FORCE) set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index 24032b6aed6..08218a5e57c 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -41,6 +41,7 @@ set(WITH_AUDASPACE ON CACHE BOOL "" FORCE) set(WITH_OPENAL ON CACHE BOOL "" FORCE) set(WITH_OPENCOLLADA ON CACHE BOOL "" FORCE) set(WITH_OPENCOLORIO ON CACHE BOOL "" FORCE) +set(WITH_OPENIMAGEDENOISE ON CACHE BOOL "" FORCE) set(WITH_OPENMP ON CACHE BOOL "" FORCE) set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE) set(WITH_OPENVDB ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index c2f608de921..f6756cb514c 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -352,6 +352,9 @@ function(SETUP_LIBDIRS) if(WITH_OPENIMAGEIO) link_directories(${OPENIMAGEIO_LIBPATH}) endif() + if(WITH_OPENIMAGEDENOISE) + link_directories(${OPENIMAGEDENOISE_LIBPATH}) + endif() if(WITH_OPENCOLORIO) link_directories(${OPENCOLORIO_LIBPATH}) endif() @@ -462,6 +465,9 @@ function(setup_liblinks if(WITH_OPENIMAGEIO) target_link_libraries(${target} ${OPENIMAGEIO_LIBRARIES}) endif() + if(WITH_OPENIMAGEDENOISE) + target_link_libraries(${target} ${OPENIMAGEDENOISE_LIBRARIES} ${TBB_LIBRARIES}) + endif() if(WITH_OPENCOLORIO) target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES}) endif() diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake index 06a97fc9abb..5ace42646c5 100644 --- a/build_files/cmake/packaging.cmake +++ b/build_files/cmake/packaging.cmake @@ -80,22 +80,28 @@ if(APPLE) endif() if(WIN32) - set(CPACK_PACKAGE_INSTALL_DIRECTORY "Blender Foundation/Blender") - set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "Blender Foundation/Blender") + set(CPACK_PACKAGE_INSTALL_DIRECTORY "Blender Foundation/Blender ${MAJOR_VERSION}.${MINOR_VERSION}") + set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "Blender Foundation/Blender ${MAJOR_VERSION}.${MINOR_VERSION}") set(CPACK_NSIS_MUI_ICON ${CMAKE_SOURCE_DIR}/release/windows/icons/winblender.ico) set(CPACK_NSIS_COMPRESSOR "/SOLID lzma") set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/release/text/GPL3-license.txt) set(CPACK_WIX_PRODUCT_ICON ${CMAKE_SOURCE_DIR}/release/windows/icons/winblender.ico) - set(CPACK_WIX_UPGRADE_GUID "B767E4FD-7DE7-4094-B051-3AE62E13A17A") + + set(BLENDER_NAMESPACE_GUID "507F933F-5898-404A-9A05-18282FD491A6") + + string(UUID CPACK_WIX_UPGRADE_GUID + NAMESPACE ${BLENDER_NAMESPACE_GUID} + NAME ${CPACK_PACKAGE_INSTALL_DIRECTORY} + TYPE SHA1 UPPER + ) set(CPACK_WIX_TEMPLATE ${LIBDIR}/package/installer_wix/WIX.template) set(CPACK_WIX_UI_BANNER ${LIBDIR}/package/installer_wix/WIX_UI_BANNER.bmp) set(CPACK_WIX_UI_DIALOG ${LIBDIR}/package/installer_wix/WIX_UI_DIALOG.bmp) - #force lzma instead of deflate - set(CPACK_WIX_LIGHT_EXTRA_FLAGS -dcl:high) + set(CPACK_WIX_LIGHT_EXTRA_FLAGS -dcl:medium) endif() set(CPACK_PACKAGE_EXECUTABLES "blender" "blender") diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 882f41b3c0d..e79359e9f3b 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -382,6 +382,19 @@ if(WITH_CYCLES_EMBREE) set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Xlinker -stack_size -Xlinker 0x100000") endif() +if(WITH_OPENIMAGEDENOISE) + find_package(OpenImageDenoise) + find_package(TBB) + + if(NOT OPENIMAGEDENOISE_FOUND) + set(WITH_OPENIMAGEDENOISE OFF) + message(STATUS "OpenImageDenoise not found") + elseif(NOT TBB_FOUND) + set(WITH_OPENIMAGEDENOISE OFF) + message(STATUS "TBB not found") + endif() +endif() + # CMake FindOpenMP doesn't know about AppleClang before 3.12, so provide custom flags. if(WITH_OPENMP) if(CMAKE_C_COMPILER_ID MATCHES "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0") diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 43d13a97a3e..1b3f9cf3fad 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -368,6 +368,15 @@ if(WITH_CYCLES_EMBREE) find_package(Embree 3.2.4 REQUIRED) endif() +if(WITH_OPENIMAGEDENOISE) + find_package_wrapper(OpenImageDenoise) + + if(NOT OPENIMAGEDENOISE_FOUND) + set(WITH_OPENIMAGEDENOISE OFF) + message(STATUS "OpenImageDenoise not found") + endif() +endif() + if(WITH_LLVM) if(EXISTS ${LIBDIR}) set(LLVM_STATIC ON) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index ad1249949c9..42ac285f88d 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -131,8 +131,8 @@ if(MSVC_CLANG) # Clangs version of cl doesn't support all flags set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc /bigobj") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj") endif() set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") @@ -349,7 +349,7 @@ if(WITH_PYTHON) string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) set(PYTHON_LIBRARY ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}.lib) set(PYTHON_LIBRARY_DEBUG ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}_d.lib) - + set(PYTHON_INCLUDE_DIR ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/include) set(PYTHON_NUMPY_INCLUDE_DIRS ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/lib/site-packages/numpy/core/include) set(NUMPY_FOUND On) @@ -418,7 +418,7 @@ endif() if(WITH_OPENIMAGEIO) windows_find_package(OpenImageIO) - set(OPENIMAGEIO ${LIBDIR}/openimageio) + set(OPENIMAGEIO ${LIBDIR}/OpenImageIO) set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) set(OIIO_OPTIMIZED optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO.lib optimized ${OPENIMAGEIO_LIBPATH}/OpenImageIO_Util.lib) @@ -459,14 +459,14 @@ if(WITH_LLVM) endif() if(WITH_OPENCOLORIO) - set(OPENCOLORIO ${LIBDIR}/opencolorio) + set(OPENCOLORIO ${LIBDIR}/OpenColorIO) set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) - set(OPENCOLORIO_LIBPATH ${LIBDIR}/opencolorio/lib) + set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib) set(OPENCOLORIO_LIBRARIES optimized ${OPENCOLORIO_LIBPATH}/OpenColorIO.lib optimized ${OPENCOLORIO_LIBPATH}/tinyxml.lib optimized ${OPENCOLORIO_LIBPATH}/libyaml-cpp.lib - debug ${OPENCOLORIO_LIBPATH}/OpenColorIO_d.lib + debug ${OPENCOLORIO_LIBPATH}/OpencolorIO_d.lib debug ${OPENCOLORIO_LIBPATH}/tinyxml_d.lib debug ${OPENCOLORIO_LIBPATH}/libyaml-cpp_d.lib ) @@ -477,19 +477,32 @@ if(WITH_OPENVDB) set(BLOSC_LIBRARIES optimized ${LIBDIR}/blosc/lib/libblosc.lib debug ${LIBDIR}/blosc/lib/libblosc_d.lib) set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib) set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include) - set(OPENVDB ${LIBDIR}/openvdb) - set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib) + set(OPENVDB ${LIBDIR}/openVDB) + set(OPENVDB_LIBPATH ${OPENVDB}/lib) set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include ${TBB_INCLUDE_DIR}) set(OPENVDB_LIBRARIES optimized ${OPENVDB_LIBPATH}/openvdb.lib debug ${OPENVDB_LIBPATH}/openvdb_d.lib ${TBB_LIBRARIES} ${BLOSC_LIBRARIES}) set(OPENVDB_DEFINITIONS -DNOMINMAX) endif() +if(WITH_OPENIMAGEDENOISE) + set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib) + set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include) + set(OPENIMAGEDENOISE ${LIBDIR}/OpenImageDenoise) + set(OPENIMAGEDENOISE_LIBPATH ${LIBDIR}/OpenImageDenoise/lib) + set(OPENIMAGEDENOISE_INCLUDE_DIRS ${OPENIMAGEDENOISE}/include ${TBB_INCLUDE_DIR}) + set(OPENIMAGEDENOISE_LIBRARIES + optimized ${OPENIMAGEDENOISE_LIBPATH}/OpenImageDenoise.lib ${OPENIMAGEDENOISE_LIBPATH}/common.lib ${OPENIMAGEDENOISE_LIBPATH}/mkldnn.lib + debug ${OPENIMAGEDENOISE_LIBPATH}/OpenImageDenoise_d.lib ${OPENIMAGEDENOISE_LIBPATH}/common_d.lib ${OPENIMAGEDENOISE_LIBPATH}/mkldnn_d.lib + ${TBB_LIBRARIES}) + set(OPENIMAGEDENOISE_DEFINITIONS) +endif() + if(WITH_ALEMBIC) set(ALEMBIC ${LIBDIR}/alembic) set(ALEMBIC_INCLUDE_DIR ${ALEMBIC}/include) set(ALEMBIC_INCLUDE_DIRS ${ALEMBIC_INCLUDE_DIR}) set(ALEMBIC_LIBPATH ${ALEMBIC}/lib) - set(ALEMBIC_LIBRARIES optimized ${ALEMBIC}/lib/alembic.lib debug ${ALEMBIC}/lib/alembic_d.lib) + set(ALEMBIC_LIBRARIES optimized ${ALEMBIC}/lib/Alembic.lib debug ${ALEMBIC}/lib/Alembic_d.lib) set(ALEMBIC_FOUND 1) endif() diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 70768a102b3..376193f73a5 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -42,7 +42,7 @@ addons_fake_modules = {} def _initialize(): path_list = paths() for path in path_list: - _bpy.utils._sys_path_ensure(path) + _bpy.utils._sys_path_ensure_append(path) for addon in _preferences.addons: enable(addon.module) diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index b39099158c6..04aaa7bd69d 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -119,11 +119,17 @@ def _test_import(module_name, loaded_modules): return mod -def _sys_path_ensure(path): - if path not in _sys.path: # reloading would add twice +# Reloading would add twice. +def _sys_path_ensure_prepend(path): + if path not in _sys.path: _sys.path.insert(0, path) +def _sys_path_ensure_append(path): + if path not in _sys.path: + _sys.path.append(path) + + def modules_from_path(path, loaded_modules): """ Load all modules in a path and return them as a list. @@ -253,7 +259,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): for path_subdir in _script_module_dirs: path = _os.path.join(base_path, path_subdir) if _os.path.isdir(path): - _sys_path_ensure(path) + _sys_path_ensure_prepend(path) # Only add to 'sys.modules' unless this is 'startup'. if path_subdir == "startup": @@ -385,13 +391,13 @@ def refresh_script_paths(): for path_subdir in _script_module_dirs: path = _os.path.join(base_path, path_subdir) if _os.path.isdir(path): - _sys_path_ensure(path) + _sys_path_ensure_prepend(path) for path in _addon_utils.paths(): - _sys_path_ensure(path) + _sys_path_ensure_append(path) path = _os.path.join(path, "modules") if _os.path.isdir(path): - _sys_path_ensure(path) + _sys_path_ensure_append(path) def app_template_paths(subdir=None): diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index a626984cfa7..c6e83a646e5 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -352,6 +352,7 @@ compositor_node_categories = [ NodeItem("CompositorNodeDBlur"), NodeItem("CompositorNodePixelate"), NodeItem("CompositorNodeSunBeams"), + NodeItem("CompositorNodeDenoise"), ]), CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[ NodeItem("CompositorNodeNormal"), diff --git a/release/windows/batch/blender_debug_log.cmd b/release/windows/batch/blender_debug_log.cmd index ecb5803a5c9..2d708ea9104 100644 --- a/release/windows/batch/blender_debug_log.cmd +++ b/release/windows/batch/blender_debug_log.cmd @@ -12,5 +12,5 @@ mkdir "%temp%\blender\debug_logs" > NUL 2>&1 echo. echo Starting blender and waiting for it to exit.... set PYTHONPATH= -blender --debug --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1 < %0 +blender --debug --debug-cycles --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1 < %0 explorer "%temp%\blender\debug_logs" diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 53976b4c1ad..755a155653b 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -137,8 +137,8 @@ void CTX_store_free(bContextStore *store); void CTX_store_free_list(ListBase *contexts); /* need to store if python is initialized or not */ -int CTX_py_init_get(bContext *C); -void CTX_py_init_set(bContext *C, int value); +bool CTX_py_init_get(bContext *C); +void CTX_py_init_set(bContext *C, bool value); void *CTX_py_dict_get(const bContext *C); void CTX_py_dict_set(bContext *C, void *value); diff --git a/source/blender/blenkernel/BKE_remesh.h b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h index 996e88e0ea0..089e4de4709 100644 --- a/source/blender/blenkernel/BKE_remesh.h +++ b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h @@ -31,14 +31,14 @@ struct Mesh; /* OpenVDB Voxel Remesher */ #ifdef WITH_OPENVDB -struct OpenVDBLevelSet *BKE_remesh_voxel_ovdb_mesh_to_level_set_create( +struct OpenVDBLevelSet *BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create( struct Mesh *mesh, struct OpenVDBTransform *transform); -struct Mesh *BKE_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *level_set, - double isovalue, - double adaptivity, - bool relax_disoriented_triangles); +struct Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *level_set, + double isovalue, + double adaptivity, + bool relax_disoriented_triangles); #endif -struct Mesh *BKE_remesh_voxel_to_mesh_nomain(struct Mesh *mesh, float voxel_size); +struct Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(struct Mesh *mesh, float voxel_size); /* Data reprojection functions */ void BKE_remesh_reproject_paint_mask(struct Mesh *target, struct Mesh *source); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d9acbb3a843..9b2db5acd3b 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1129,6 +1129,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree, #define CMP_NODE_CORNERPIN 321 #define CMP_NODE_SWITCH_VIEW 322 #define CMP_NODE_CRYPTOMATTE 323 +#define CMP_NODE_DENOISE 324 /* channel toggles */ #define CMP_CHAN_RGB 1 diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index cbe250d0ac8..37667599488 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -259,6 +259,8 @@ typedef struct SculptSession { struct StrokeCache *cache; + int active_vertex_index; + union { struct { struct SculptVertexPaintGeomMap gmap; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 3806868e060..62544efad2c 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -301,6 +301,7 @@ typedef struct PBVHVertexIter { int gx; int gy; int i; + int index; /* grid */ struct CCGElem **grids; @@ -369,6 +370,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo continue; \ vi.co = vi.mvert->co; \ vi.no = vi.mvert->no; \ + vi.index = vi.vert_indices[vi.i]; \ if (vi.vmask) \ vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \ } \ @@ -385,6 +387,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo continue; \ vi.co = vi.bm_vert->co; \ vi.fno = vi.bm_vert->no; \ + vi.index = BM_elem_index_get(vi.bm_vert); \ vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \ } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 1f125b93b3f..669abff6599 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -151,6 +151,7 @@ set(SRC intern/mesh_mapping.c intern/mesh_merge.c intern/mesh_remap.c + intern/mesh_remesh_voxel.c intern/mesh_runtime.c intern/mesh_tangent.c intern/mesh_validate.c @@ -178,7 +179,6 @@ set(SRC intern/pbvh.c intern/pbvh_bmesh.c intern/pointcache.c - intern/remesh.c intern/report.c intern/rigidbody.c intern/scene.c @@ -301,6 +301,7 @@ set(SRC BKE_mesh_iterators.h BKE_mesh_mapping.h BKE_mesh_remap.h + BKE_mesh_remesh_voxel.h BKE_mesh_runtime.h BKE_mesh_tangent.h BKE_modifier.h @@ -318,7 +319,6 @@ set(SRC BKE_particle.h BKE_pbvh.h BKE_pointcache.h - BKE_remesh.h BKE_report.h BKE_rigidbody.h BKE_scene.h diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 2cb98d8d90b..f536f21c3e5 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -89,7 +89,8 @@ struct bContext { struct Scene *scene; int recursion; - int py_init; /* true if python is initialized */ + /** True if python is initialized. */ + bool py_init; void *py_context; } data; }; @@ -212,11 +213,11 @@ void CTX_store_free_list(ListBase *contexts) /* is python initialized? */ -int CTX_py_init_get(bContext *C) +bool CTX_py_init_get(bContext *C) { return C->data.py_init; } -void CTX_py_init_set(bContext *C, int value) +void CTX_py_init_set(bContext *C, bool value) { C->data.py_init = value; } diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 78117a4f615..b55635560be 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -955,7 +955,7 @@ static bool vfont_to_curve(Object *ob, } } - current_line_length += xof; + current_line_length += xof - MARGIN_X_MIN; if (ct->dobreak) { current_line_length += twidth; } @@ -1026,7 +1026,7 @@ static bool vfont_to_curve(Object *ob, } ct++; } - current_line_length += xof + twidth; + current_line_length += xof + twidth - MARGIN_X_MIN; longest_line_length = MAX2(current_line_length, longest_line_length); cu->lines = 1; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 8e04ef2d3ca..a99407b9bf9 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2766,8 +2766,8 @@ static void do_makepicstring(char *string, int frame, const char imtype, const ImageFormatData *im_format, - const short use_ext, - const short use_frames, + const bool use_ext, + const bool use_frames, const char *suffix) { if (string == NULL) { diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index ee060a117dc..3a2ba078dce 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -978,7 +978,7 @@ static void curve_to_mesh_eval_ensure(Object *object) * * So we create temporary copy of the object which will use same data as the original bevel, but * will have no modifiers. */ - Object bevel_object = {NULL}; + Object bevel_object = {{NULL}}; if (remapped_curve.bevobj != NULL) { bevel_object = *remapped_curve.bevobj; BLI_listbase_clear(&bevel_object.modifiers); @@ -986,7 +986,7 @@ static void curve_to_mesh_eval_ensure(Object *object) } /* Same thing for taper. */ - Object taper_object = {NULL}; + Object taper_object = {{NULL}}; if (remapped_curve.taperobj != NULL) { taper_object = *remapped_curve.taperobj; BLI_listbase_clear(&taper_object.modifiers); diff --git a/source/blender/blenkernel/intern/remesh.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c index 36e92689f1a..a5136311a22 100644 --- a/source/blender/blenkernel/intern/remesh.c +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c @@ -43,14 +43,14 @@ #include "BKE_library.h" #include "BKE_customdata.h" #include "BKE_bvhutils.h" -#include "BKE_remesh.h" +#include "BKE_mesh_remesh_voxel.h" /* own include */ #ifdef WITH_OPENVDB # include "openvdb_capi.h" #endif #ifdef WITH_OPENVDB -struct OpenVDBLevelSet *BKE_remesh_voxel_ovdb_mesh_to_level_set_create( +struct OpenVDBLevelSet *BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create( Mesh *mesh, struct OpenVDBTransform *transform) { BKE_mesh_runtime_looptri_recalc(mesh); @@ -90,10 +90,10 @@ struct OpenVDBLevelSet *BKE_remesh_voxel_ovdb_mesh_to_level_set_create( return level_set; } -Mesh *BKE_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *level_set, - double isovalue, - double adaptivity, - bool relax_disoriented_triangles) +Mesh *BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *level_set, + double isovalue, + double adaptivity, + bool relax_disoriented_triangles) { # ifdef WITH_OPENVDB struct OpenVDBVolumeToMeshData output_mesh; @@ -101,34 +101,38 @@ Mesh *BKE_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *level_ level_set, &output_mesh, isovalue, adaptivity, relax_disoriented_triangles); # endif - Mesh *mesh = BKE_mesh_new_nomain( - output_mesh.totvertices, 0, output_mesh.totquads + output_mesh.tottriangles, 0, 0); - int q = output_mesh.totquads; + Mesh *mesh = BKE_mesh_new_nomain(output_mesh.totvertices, + 0, + 0, + (output_mesh.totquads * 4) + (output_mesh.tottriangles * 3), + output_mesh.totquads + output_mesh.tottriangles); for (int i = 0; i < output_mesh.totvertices; i++) { - float vco[3] = {output_mesh.vertices[i * 3], - output_mesh.vertices[i * 3 + 1], - output_mesh.vertices[i * 3 + 2]}; - copy_v3_v3(mesh->mvert[i].co, vco); + copy_v3_v3(mesh->mvert[i].co, &output_mesh.vertices[i * 3]); } - for (int i = 0; i < output_mesh.totquads; i++) { - mesh->mface[i].v4 = output_mesh.quads[i * 4]; - mesh->mface[i].v3 = output_mesh.quads[i * 4 + 1]; - mesh->mface[i].v2 = output_mesh.quads[i * 4 + 2]; - mesh->mface[i].v1 = output_mesh.quads[i * 4 + 3]; + MPoly *mp = mesh->mpoly; + MLoop *ml = mesh->mloop; + for (int i = 0; i < output_mesh.totquads; i++, mp++, ml += 4) { + mp->loopstart = (int)(ml - mesh->mloop); + mp->totloop = 4; + + ml[0].v = output_mesh.quads[i * 4 + 3]; + ml[1].v = output_mesh.quads[i * 4 + 2]; + ml[2].v = output_mesh.quads[i * 4 + 1]; + ml[3].v = output_mesh.quads[i * 4]; } - for (int i = 0; i < output_mesh.tottriangles; i++) { - mesh->mface[i + q].v4 = 0; - mesh->mface[i + q].v3 = output_mesh.triangles[i * 3]; - mesh->mface[i + q].v2 = output_mesh.triangles[i * 3 + 1]; - mesh->mface[i + q].v1 = output_mesh.triangles[i * 3 + 2]; + for (int i = 0; i < output_mesh.tottriangles; i++, mp++, ml += 3) { + mp->loopstart = (int)(ml - mesh->mloop); + mp->totloop = 3; + + ml[0].v = output_mesh.triangles[i * 3 + 2]; + ml[1].v = output_mesh.triangles[i * 3 + 1]; + ml[2].v = output_mesh.triangles[i * 3]; } - BKE_mesh_calc_edges_tessface(mesh); - BKE_mesh_convert_mfaces_to_mpolys(mesh); - BKE_mesh_tessface_clear(mesh); + BKE_mesh_calc_edges(mesh, false, false); BKE_mesh_calc_normals(mesh); MEM_freeN(output_mesh.quads); @@ -142,15 +146,15 @@ Mesh *BKE_remesh_voxel_ovdb_volume_to_mesh_nomain(struct OpenVDBLevelSet *level_ } #endif -Mesh *BKE_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size) +Mesh *BKE_mesh_remesh_voxel_to_mesh_nomain(Mesh *mesh, float voxel_size) { Mesh *new_mesh = NULL; #ifdef WITH_OPENVDB struct OpenVDBLevelSet *level_set; struct OpenVDBTransform *xform = OpenVDBTransform_create(); OpenVDBTransform_create_linear_transform(xform, (double)voxel_size); - level_set = BKE_remesh_voxel_ovdb_mesh_to_level_set_create(mesh, xform); - new_mesh = BKE_remesh_voxel_ovdb_volume_to_mesh_nomain(level_set, 0.0, 0.0, false); + level_set = BKE_mesh_remesh_voxel_ovdb_mesh_to_level_set_create(mesh, xform); + new_mesh = BKE_mesh_remesh_voxel_ovdb_volume_to_mesh_nomain(level_set, 0.0, 0.0, false); OpenVDBLevelSet_free(level_set); OpenVDBTransform_free(xform); #else diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 7d7e1c75391..986571e34bd 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3779,6 +3779,7 @@ static void registerCompositNodes(void) register_node_type_cmp_despeckle(); register_node_type_cmp_defocus(); register_node_type_cmp_sunbeams(); + register_node_type_cmp_denoise(); register_node_type_cmp_valtorgb(); register_node_type_cmp_rgbtobw(); diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c index 8e2687a6b2f..23f560c5463 100644 --- a/source/blender/blenlib/intern/delaunay_2d.c +++ b/source/blender/blenlib/intern/delaunay_2d.c @@ -1961,13 +1961,17 @@ static void add_face_ids( } } -/* Delete_edge but try not to mess up outer face. */ +/* Delete_edge but try not to mess up outer face. + * Also faces have symedges now, so make sure not + * to mess those up either. */ static void dissolve_symedge(CDT_state *cdt, SymEdge *se) { - if (sym(se)->face == cdt->outer_face) { + SymEdge *symse = sym(se); + if (symse->face == cdt->outer_face) { se = sym(se); + symse = sym(se); } - if (cdt->outer_face->symedge == se || cdt->outer_face->symedge == sym(se)) { + if (cdt->outer_face->symedge == se || cdt->outer_face->symedge == symse) { /* Advancing by 2 to get past possible 'sym(se)'. */ if (se->next->next == se) { cdt->outer_face->symedge = NULL; @@ -1976,6 +1980,14 @@ static void dissolve_symedge(CDT_state *cdt, SymEdge *se) cdt->outer_face->symedge = se->next->next; } } + else { + if (se->face->symedge == se) { + se->face->symedge = se->next; + } + if (symse->face->symedge == se) { + symse->face->symedge = symse->next; + } + } delete_edge(cdt, se); } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 2262edb32df..43472929682 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -737,7 +737,8 @@ static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase) /* Return true if there is something to convert. */ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, char blend_method, - GSet *nodegrp_tree_set) + GSet *nodegrp_tree_set, + GSet *nooutput_tree_set) { bool need_update = false; bool do_conversion = false; @@ -758,9 +759,10 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, bNodeTree *group_ntree = (bNodeTree *)fromnode->id; if (BLI_gset_add(nodegrp_tree_set, group_ntree)) { /* Recursive but not convert (blend_method = -1). Conversion happens after. */ - if (!do_versions_material_convert_legacy_blend_mode(group_ntree, -1, nodegrp_tree_set)) { - /* There is no output to convert in the tree, remove it. */ - BLI_gset_remove(nodegrp_tree_set, group_ntree, NULL); + if (!do_versions_material_convert_legacy_blend_mode( + group_ntree, -1, nodegrp_tree_set, nooutput_tree_set)) { + /* There is no output to convert in the tree. */ + BLI_gset_add(nooutput_tree_set, group_ntree); } } } @@ -768,9 +770,10 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, bNodeTree *group_ntree = (bNodeTree *)tonode->id; if (BLI_gset_add(nodegrp_tree_set, group_ntree)) { /* Recursive but not convert (blend_method = -1). Conversion happens after. */ - if (!do_versions_material_convert_legacy_blend_mode(group_ntree, -1, nodegrp_tree_set)) { - /* There is no output to convert in the tree, remove it. */ - BLI_gset_remove(nodegrp_tree_set, group_ntree, NULL); + if (!do_versions_material_convert_legacy_blend_mode( + group_ntree, -1, nodegrp_tree_set, nooutput_tree_set)) { + /* There is no output to convert in the tree. */ + BLI_gset_add(nooutput_tree_set, group_ntree); } } } @@ -1259,32 +1262,45 @@ void do_versions_after_linking_280(Main *bmain, ReportList *reports) GSet *ntrees_additive = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); GSet *ntrees_multiply = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); GSet *ntrees_nolegacy = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + GSet *ntrees_nooutput = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) { bNodeTree *ntree = ma->nodetree; if (ma->blend_method == 1 /* MA_BM_ADD */) { if (ma->use_nodes) { - do_versions_material_convert_legacy_blend_mode(ntree, ma->blend_method, ntrees_additive); + do_versions_material_convert_legacy_blend_mode( + ntree, ma->blend_method, ntrees_additive, ntrees_nooutput); } ma->blend_method = MA_BM_BLEND; } else if (ma->blend_method == 2 /* MA_BM_MULTIPLY */) { if (ma->use_nodes) { - do_versions_material_convert_legacy_blend_mode(ntree, ma->blend_method, ntrees_multiply); + do_versions_material_convert_legacy_blend_mode( + ntree, ma->blend_method, ntrees_multiply, ntrees_nooutput); } ma->blend_method = MA_BM_BLEND; } else { /* Still tag the group nodes as not using legacy blend modes. */ if (ma->use_nodes) { - do_versions_material_convert_legacy_blend_mode(ntree, -1, ntrees_nolegacy); + do_versions_material_convert_legacy_blend_mode( + ntree, -1, ntrees_nolegacy, ntrees_nooutput); } } } - /* Remove group nodetree that are used by material using non-legacy blend mode. */ GHashIterState iter = {0}; bNodeTree *ntree; + /* Remove trees that have no output nodes. + * This is done separately to avoid infinite recursion. */ + while (BLI_gset_pop(ntrees_nooutput, (GSetIterState *)&iter, (void **)&ntree)) { + BLI_gset_remove(ntrees_additive, ntree, NULL); + BLI_gset_remove(ntrees_multiply, ntree, NULL); + BLI_gset_remove(ntrees_nolegacy, ntree, NULL); + } + BLI_gset_free(ntrees_nooutput, NULL); + /* Remove group nodetree that are used by material using non-legacy blend mode. */ + GHashIterState iter_rm = {0}; bool error = false; - while (BLI_gset_pop(ntrees_nolegacy, (GSetIterState *)&iter, (void **)&ntree)) { + while (BLI_gset_pop(ntrees_nolegacy, (GSetIterState *)&iter_rm, (void **)&ntree)) { if (BLI_gset_remove(ntrees_additive, ntree, NULL)) { error = true; } @@ -1297,10 +1313,10 @@ void do_versions_after_linking_280(Main *bmain, ReportList *reports) GHashIterState iter_add = {0}; GHashIterState iter_mul = {0}; while (BLI_gset_pop(ntrees_additive, (GSetIterState *)&iter_add, (void **)&ntree)) { - do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */, NULL); + do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */, NULL, NULL); } while (BLI_gset_pop(ntrees_multiply, (GSetIterState *)&iter_mul, (void **)&ntree)) { - do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */, NULL); + do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */, NULL, NULL); } BLI_gset_free(ntrees_additive, NULL); BLI_gset_free(ntrees_multiply, NULL); diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 308a95c0e0c..50b5951f99f 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -276,11 +276,12 @@ set(SRC nodes/COM_VectorBlurNode.h operations/COM_VectorBlurOperation.cpp operations/COM_VectorBlurOperation.h - nodes/COM_BlurNode.cpp nodes/COM_BlurNode.h nodes/COM_BokehBlurNode.cpp nodes/COM_BokehBlurNode.h + nodes/COM_DenoiseNode.h + nodes/COM_DenoiseNode.cpp nodes/COM_DespeckleNode.cpp nodes/COM_DespeckleNode.h nodes/COM_DilateErodeNode.cpp @@ -490,6 +491,8 @@ set(SRC operations/COM_ConvolutionEdgeFilterOperation.h operations/COM_ConvolutionFilterOperation.cpp operations/COM_ConvolutionFilterOperation.h + operations/COM_DenoiseOperation.h + operations/COM_DenoiseOperation.cpp operations/COM_DespeckleOperation.cpp operations/COM_DespeckleOperation.h operations/COM_DilateErodeOperation.cpp @@ -558,4 +561,12 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_OPENIMAGEDENOISE) + add_definitions(-DWITH_OPENIMAGEDENOISE) + add_definitions(-DOIDN_STATIC_LIB) + list(APPEND INC_SYS + ${OPENIMAGEDENOISE_INCLUDE_DIRS} + ) +endif() + blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 9dc55527f0d..704833389f8 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -53,6 +53,7 @@ extern "C" { #include "COM_CropNode.h" #include "COM_CryptomatteNode.h" #include "COM_DefocusNode.h" +#include "COM_DenoiseNode.h" #include "COM_DespeckleNode.h" #include "COM_DifferenceMatteNode.h" #include "COM_DilateErodeNode.h" @@ -122,7 +123,7 @@ bool Converter::is_fast_node(bNode *b_node) b_node->type == CMP_NODE_BOKEHBLUR || b_node->type == CMP_NODE_GLARE || b_node->type == CMP_NODE_DBLUR || b_node->type == CMP_NODE_MOVIEDISTORTION || b_node->type == CMP_NODE_LENSDIST || b_node->type == CMP_NODE_DOUBLEEDGEMASK || - b_node->type == CMP_NODE_DILATEERODE); + b_node->type == CMP_NODE_DILATEERODE || b_node->type == CMP_NODE_DENOISE); } Node *Converter::convert(bNode *b_node) @@ -402,6 +403,9 @@ Node *Converter::convert(bNode *b_node) case CMP_NODE_CRYPTOMATTE: node = new CryptomatteNode(b_node); break; + case CMP_NODE_DENOISE: + node = new DenoiseNode(b_node); + break; } return node; } diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.cpp b/source/blender/compositor/nodes/COM_DenoiseNode.cpp new file mode 100644 index 00000000000..7de120d1204 --- /dev/null +++ b/source/blender/compositor/nodes/COM_DenoiseNode.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2019, Blender Foundation. + * + * 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. + * + * Contributor: + * Stefan Werner + */ + +#include "COM_DenoiseNode.h" +#include "DNA_node_types.h" +#include "COM_SetValueOperation.h" +#include "COM_MixOperation.h" +#include "COM_DenoiseOperation.h" + +DenoiseNode::DenoiseNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void DenoiseNode::convertToOperations(NodeConverter &converter, + const CompositorContext & /*context*/) const +{ + bNode *node = this->getbNode(); + NodeDenoise *denoise = (NodeDenoise *)node->storage; + + DenoiseOperation *operation = new DenoiseOperation(); + converter.addOperation(operation); + operation->setDenoiseSettings(denoise); + + converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0)); + converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1)); + converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2)); + converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0)); +} diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.h b/source/blender/compositor/nodes/COM_DenoiseNode.h new file mode 100644 index 00000000000..0924da8931c --- /dev/null +++ b/source/blender/compositor/nodes/COM_DenoiseNode.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019, Blender Foundation. + * + * 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. + * + * Contributor: + * Stefan Werner + */ + +#ifndef __COM_DENOISENODE_H__ +#define __COM_DENOISENODE_H__ + +#include "COM_Node.h" + +/** + * \brief DenoiseNode + * \ingroup Node + */ +class DenoiseNode : public Node { + public: + DenoiseNode(bNode *editorNode); + void convertToOperations(NodeConverter &converter, const CompositorContext &context) const; +}; + +#endif diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cpp b/source/blender/compositor/operations/COM_DenoiseOperation.cpp new file mode 100644 index 00000000000..af568490c72 --- /dev/null +++ b/source/blender/compositor/operations/COM_DenoiseOperation.cpp @@ -0,0 +1,154 @@ +/* + * Copyright 2019, Blender Foundation. + * + * 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. + * + * Contributor: + * Stefan Werner + */ + +#include "COM_DenoiseOperation.h" +#include "BLI_math.h" +#ifdef WITH_OPENIMAGEDENOISE +# include <OpenImageDenoise/oidn.hpp> +#endif +#include <iostream> + +DenoiseOperation::DenoiseOperation() : SingleThreadedOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_settings = NULL; +} +void DenoiseOperation::initExecution() +{ + SingleThreadedOperation::initExecution(); + this->m_inputProgramColor = getInputSocketReader(0); + this->m_inputProgramAlbedo = getInputSocketReader(1); + this->m_inputProgramNormal = getInputSocketReader(2); +} + +void DenoiseOperation::deinitExecution() +{ + this->m_inputProgramColor = NULL; + this->m_inputProgramAlbedo = NULL; + this->m_inputProgramNormal = NULL; + SingleThreadedOperation::deinitExecution(); +} + +MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2) +{ + MemoryBuffer *tileColor = (MemoryBuffer *)this->m_inputProgramColor->initializeTileData(rect2); + MemoryBuffer *tileAlbedo = (MemoryBuffer *)this->m_inputProgramAlbedo->initializeTileData(rect2); + MemoryBuffer *tileNormal = (MemoryBuffer *)this->m_inputProgramNormal->initializeTileData(rect2); + rcti rect; + rect.xmin = 0; + rect.ymin = 0; + rect.xmax = getWidth(); + rect.ymax = getHeight(); + MemoryBuffer *result = new MemoryBuffer(COM_DT_COLOR, &rect); + float *data = result->getBuffer(); + this->generateDenoise(data, tileColor, tileAlbedo, tileNormal, this->m_settings); + return result; +} + +bool DenoiseOperation::determineDependingAreaOfInterest(rcti * /*input*/, + ReadBufferOperation *readOperation, + rcti *output) +{ + if (isCached()) { + return false; + } + else { + rcti newInput; + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } +} + +void DenoiseOperation::generateDenoise(float *data, + MemoryBuffer *inputTileColor, + MemoryBuffer *inputTileAlbedo, + MemoryBuffer *inputTileNormal, + NodeDenoise *settings) +{ + float *inputBufferColor = inputTileColor->getBuffer(); + BLI_assert(inputBufferColor); + if (!inputBufferColor) { + return; + } +#ifdef WITH_OPENIMAGEDENOISE + oidn::DeviceRef device = oidn::newDevice(); + device.commit(); + + oidn::FilterRef filter = device.newFilter("RT"); + filter.setImage("color", + inputBufferColor, + oidn::Format::Float3, + inputTileColor->getWidth(), + inputTileColor->getHeight(), + 0, + 4 * sizeof(float)); + if (inputTileAlbedo && inputTileAlbedo->getBuffer()) { + filter.setImage("albedo", + inputTileAlbedo->getBuffer(), + oidn::Format::Float3, + inputTileAlbedo->getWidth(), + inputTileAlbedo->getHeight(), + 0, + 4 * sizeof(float)); + } + if (inputTileNormal && inputTileNormal->getBuffer()) { + filter.setImage("normal", + inputTileNormal->getBuffer(), + oidn::Format::Float3, + inputTileNormal->getWidth(), + inputTileNormal->getHeight(), + 0, + 3 * sizeof(float)); + } + filter.setImage("output", + data, + oidn::Format::Float3, + inputTileColor->getWidth(), + inputTileColor->getHeight(), + 0, + 4 * sizeof(float)); + + BLI_assert(settings); + if (settings) { + filter.set("hdr", settings->hdr); + filter.set("srgb", false); + } + + filter.commit(); + filter.execute(); + + /* copy the alpha channel, OpenImageDenoise currently only supports RGB */ + size_t numPixels = inputTileColor->getWidth() * inputTileColor->getHeight(); + for (size_t i = 0; i < numPixels; ++i) { + data[i * 4 + 3] = inputBufferColor[i * 4 + 3]; + } +#else + ::memcpy(data, + inputBufferColor, + inputTileColor->getWidth() * inputTileColor->getHeight() * sizeof(float) * 4); +#endif +} diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.h b/source/blender/compositor/operations/COM_DenoiseOperation.h new file mode 100644 index 00000000000..6e19bd6034a --- /dev/null +++ b/source/blender/compositor/operations/COM_DenoiseOperation.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019, Blender Foundation. + * + * 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. + * + * Contributor: + * Stefan Werner + */ + +#ifndef __COM_DENOISEBASEOPERATION_H__ +#define __COM_DENOISEBASEOPERATION_H__ + +#include "COM_SingleThreadedOperation.h" +#include "DNA_node_types.h" + +class DenoiseOperation : public SingleThreadedOperation { + private: + /** + * \brief Cached reference to the input programs + */ + SocketReader *m_inputProgramColor; + SocketReader *m_inputProgramAlbedo; + SocketReader *m_inputProgramNormal; + + /** + * \brief settings of the denoise node. + */ + NodeDenoise *m_settings; + + public: + DenoiseOperation(); + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setDenoiseSettings(NodeDenoise *settings) + { + this->m_settings = settings; + } + bool determineDependingAreaOfInterest(rcti *input, + ReadBufferOperation *readOperation, + rcti *output); + + protected: + void generateDenoise(float *data, + MemoryBuffer *inputTileColor, + MemoryBuffer *inputTileAlbedo, + MemoryBuffer *inputTileNormal, + NodeDenoise *settings); + + MemoryBuffer *createMemoryBuffer(rcti *rect); +}; +#endif diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 53cec599b82..6cae9ceb7d6 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -141,9 +141,7 @@ void DRW_draw_depth_object(struct ARegion *ar, void DRW_draw_select_id(struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, - struct Base **bases, - const uint bases_len, - short select_mode); + const struct rcti *rect); /* grease pencil render */ bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph); diff --git a/source/blender/draw/DRW_select_buffer.h b/source/blender/draw/DRW_select_buffer.h index ff40508b1a1..4aa1c403710 100644 --- a/source/blender/draw/DRW_select_buffer.h +++ b/source/blender/draw/DRW_select_buffer.h @@ -33,6 +33,13 @@ struct View3D; struct ViewLayer; struct rcti; +typedef struct SELECTID_ObjectData { + DrawData dd; + + uint drawn_index; + bool is_drawn; +} SELECTID_ObjectData; + struct ObjectOffsets { /* For convenience only. */ union { @@ -54,43 +61,75 @@ struct SELECTID_Context { struct GPUFrameBuffer *framebuffer_select_id; struct GPUTexture *texture_u32; - struct ObjectOffsets *index_offsets; + /* All context objects */ + struct Object **objects; uint objects_len; - uint last_object_drawn; - /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ - uint last_index_drawn; + + /* Array with only drawn objects. When a new object is found within the rect, + * it is added to the end of the list. + * The list is reset to any viewport or context update. */ + struct ObjectOffsets *index_offsets; + struct Object **objects_drawn; + uint objects_drawn_len; + + /** Total number of element indices `index_offsets[object_drawn_len - 1].vert`. */ + uint index_drawn_len; short select_mode; + + /* To check for updates. */ + float persmat[4][4]; + bool is_dirty; + + /* rect is used to check which objects whose indexes need to be drawn. */ + rcti last_rect; }; -/* select_buffer.c */ -void DRW_select_buffer_context_create(struct Base **bases, - const uint bases_len, - short select_mode); +/* draw_select_buffer.c */ bool DRW_select_buffer_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type); -uint DRW_select_buffer_context_offset_for_object_elem(const uint base_index, char elem_type); -uint *DRW_select_buffer_read(const struct rcti *rect, uint *r_buf_len); -void DRW_draw_select_id_object(struct Depsgraph *depsgraph, - struct ViewLayer *view_layer, - struct ARegion *ar, - struct View3D *v3d, - struct Object *ob, - short select_mode); -uint *DRW_select_buffer_bitmap_from_rect(const struct rcti *rect, uint *r_bitmap_len); -uint *DRW_select_buffer_bitmap_from_circle(const int center[2], +uint DRW_select_buffer_context_offset_for_object_elem(struct Depsgraph *depsgraph, + struct Object *object, + char elem_type); +uint *DRW_select_buffer_read(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const rcti *rect, + uint *r_buf_len); +uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const struct rcti *rect, + uint *r_bitmap_len); +uint *DRW_select_buffer_bitmap_from_circle(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const int radius, uint *r_bitmap_len); -uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], +uint *DRW_select_buffer_bitmap_from_poly(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int poly[][2], const int poly_len, - const struct rcti *rect); -uint DRW_select_buffer_sample_point(const int center[2]); -uint DRW_select_buffer_find_nearest_to_point(const int center[2], + const struct rcti *rect, + uint *r_bitmap_len); +uint DRW_select_buffer_sample_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2]); +uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const uint id_min, const uint id_max, uint *dist); +void DRW_select_buffer_context_create(struct Base **bases, + const uint bases_len, + short select_mode); /* select_engine.c */ struct SELECTID_Context *DRW_select_engine_context_get(void); diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index e6e699bef10..f52fcf31267 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -75,22 +75,21 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, if (LOOK_DEV_OVERLAY_ENABLED(v3d)) { /* Viewport / Spheres size. */ - rcti rect; - ED_region_visible_rect(draw_ctx->ar, &rect); + const rcti *rect = ED_region_visible_rect(draw_ctx->ar); /* Make the viewport width scale the lookdev spheres a bit. * Scale between 1000px and 2000px. */ const float viewport_scale = clamp_f( - BLI_rcti_size_x(&rect) / (2000.0f * U.dpi_fac), 0.5f, 1.0f); + BLI_rcti_size_x(rect) / (2000.0f * U.dpi_fac), 0.5f, 1.0f); const int sphere_size = U.lookdev_sphere_size * U.dpi_fac * viewport_scale; - if (sphere_size != effects->sphere_size || rect.xmax != effects->anchor[0] || - rect.ymin != effects->anchor[1]) { + if (sphere_size != effects->sphere_size || rect->xmax != effects->anchor[0] || + rect->ymin != effects->anchor[1]) { /* If sphere size or anchor point moves, reset TAA to avoid ghosting issue. * This needs to happen early because we are changing taa_current_sample. */ effects->sphere_size = sphere_size; - effects->anchor[0] = rect.xmax; - effects->anchor[1] = rect.ymin; + effects->anchor[0] = rect->xmax; + effects->anchor[1] = rect->ymin; EEVEE_temporal_sampling_reset(vedata); } } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 16162645f3d..efe67e1ead0 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -564,6 +564,8 @@ static void gpencil_add_draw_data(void *vedata, Object *ob) GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; int i = stl->g_data->gp_cache_used - 1; tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; @@ -580,7 +582,9 @@ static void gpencil_add_draw_data(void *vedata, Object *ob) /* FX passses */ cache_ob->has_fx = false; - if ((!stl->storage->simplify_fx) && (!ELEM(cache_ob->shading_type[0], OB_WIRE, OB_SOLID)) && + if ((!stl->storage->simplify_fx) && + ((!ELEM(cache_ob->shading_type[0], OB_WIRE, OB_SOLID)) || + ((v3d->spacetype != SPACE_VIEW3D))) && (BKE_shaderfx_has_gpencil(ob))) { cache_ob->has_fx = true; if ((!stl->storage->simplify_fx) && (!is_multiedit)) { diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c index b65a158cdcf..268cd60a8aa 100644 --- a/source/blender/draw/engines/select/select_draw_utils.c +++ b/source/blender/draw/engines/select/select_draw_utils.c @@ -23,6 +23,8 @@ */ #include "BKE_editmesh.h" +#include "BKE_mesh.h" +#include "BKE_object.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" @@ -42,7 +44,7 @@ /** \name Draw Utilities * \{ */ -void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *select_ctx) +static void select_id_framebuffer_setup(struct SELECTID_Context *select_ctx) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); int size[2]; @@ -73,6 +75,32 @@ void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *select_ctx } } +/* Remove all tags from drawn or culled objects. */ +void select_id_context_clear(struct SELECTID_Context *select_ctx) +{ + select_ctx->objects_drawn_len = 0; + select_ctx->index_drawn_len = 1; + select_id_framebuffer_setup(select_ctx); + GPU_framebuffer_bind(select_ctx->framebuffer_select_id); + GPU_framebuffer_clear_color_depth( + select_ctx->framebuffer_select_id, (const float[4]){0.0f}, 1.0f); +} + +void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3]) +{ + BoundBox *bb; + BMEditMesh *em = BKE_editmesh_from_object(obj); + if (em) { + /* Use Object Texture Space. */ + bb = BKE_mesh_texspace_get(em->mesh_eval_cage, NULL, NULL, NULL); + } + else { + bb = BKE_object_boundbox_get(obj); + } + copy_v3_v3(r_min, bb->vec[0]); + copy_v3_v3(r_max, bb->vec[6]); +} + short select_id_get_object_select_mode(Scene *scene, Object *ob) { short r_select_mode = 0; @@ -132,7 +160,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, if (draw_facedot) { struct GPUBatch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); - DRW_shgroup_call(face_shgrp, geom_facedots, ob); + DRW_shgroup_call_no_cull(face_shgrp, geom_facedots, ob); } *r_face_offset = initial_offset + em->bm->totface; } @@ -141,14 +169,14 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, face_shgrp = stl->g_data->shgrp_face_unif; *r_face_offset = initial_offset; } - DRW_shgroup_call(face_shgrp, geom_faces, ob); + DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob); /* Unlike faces, only draw edges if edge select mode. */ if (select_mode & SCE_SELECT_EDGE) { struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge); DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset); - DRW_shgroup_call(edge_shgrp, geom_edges, ob); + DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob); *r_edge_offset = *r_face_offset + em->bm->totedge; } else { @@ -162,7 +190,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *(int *)r_edge_offset); - DRW_shgroup_call(vert_shgrp, geom_verts, ob); + DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob); *r_vert_offset = *r_edge_offset + em->bm->totvert; } else { @@ -192,13 +220,13 @@ static void draw_select_id_mesh(SELECTID_StorageList *stl, face_shgrp = stl->g_data->shgrp_face_unif; *r_face_offset = initial_offset; } - DRW_shgroup_call(face_shgrp, geom_faces, ob); + DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob); if (select_mode & SCE_SELECT_EDGE) { struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge); DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset); - DRW_shgroup_call(edge_shgrp, geom_edges, ob); + DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob); *r_edge_offset = *r_face_offset + me->totedge; } else { @@ -209,7 +237,7 @@ static void draw_select_id_mesh(SELECTID_StorageList *stl, struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *r_edge_offset); - DRW_shgroup_call(vert_shgrp, geom_verts, ob); + DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob); *r_vert_offset = *r_edge_offset + me->totvert; } else { diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index 67e926452b9..4c158312e0f 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -24,13 +24,14 @@ #include "DNA_screen_types.h" -#include "GPU_shader.h" - #include "UI_resources.h" #include "DRW_engine.h" #include "DRW_select_buffer.h" +#include "draw_cache_impl.h" +#include "draw_manager.h" + #include "select_private.h" #include "select_engine.h" @@ -41,6 +42,7 @@ static struct { SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN]; struct SELECTID_Context context; + uint runtime_new_objects; } e_data = {{{NULL}}}; /* Engine data */ /* Shaders */ @@ -90,8 +92,23 @@ static void select_engine_init(void *vedata) } { + /* Create view from a subregion */ + const DRWView *view_default = DRW_view_default_get(); + float viewmat[4][4], winmat[4][4], winmat_subregion[4][4]; + DRW_view_viewmat_get(view_default, viewmat, false); + DRW_view_winmat_get(view_default, winmat, false); + projmat_from_subregion(winmat, + (int[2]){draw_ctx->ar->winx, draw_ctx->ar->winy}, + e_data.context.last_rect.xmin, + e_data.context.last_rect.xmax, + e_data.context.last_rect.ymin, + e_data.context.last_rect.ymax, + winmat_subregion); + + stl->g_data->view_subregion = DRW_view_create(viewmat, winmat_subregion, NULL, NULL, NULL); + /* Create view with depth offset */ - stl->g_data->view_faces = (DRWView *)DRW_view_default_get(); + stl->g_data->view_faces = (DRWView *)view_default; stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); stl->g_data->view_verts = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.1f); } @@ -107,11 +124,19 @@ static void select_cache_init(void *vedata) if (e_data.context.select_mode == -1) { e_data.context.select_mode = select_id_get_object_select_mode(draw_ctx->scene, - OBACT(draw_ctx->view_layer)); + draw_ctx->obact); BLI_assert(e_data.context.select_mode != 0); } { + psl->depth_only_pass = DRW_pass_create("Depth Only Pass", DRW_STATE_DEFAULT); + stl->g_data->shgrp_depth_only = DRW_shgroup_create(sh_data->select_id_uniform, + psl->depth_only_pass); + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_state_enable(stl->g_data->shgrp_depth_only, DRW_STATE_CLIP_PLANES); + } + psl->select_id_face_pass = DRW_pass_create("Face Pass", DRW_STATE_DEFAULT); if (e_data.context.select_mode & SCE_SELECT_FACE) { @@ -157,29 +182,82 @@ static void select_cache_init(void *vedata) } } - e_data.context.last_object_drawn = 0; - e_data.context.last_index_drawn = 1; + /* Check if the viewport has changed. */ + float(*persmat)[4] = draw_ctx->rv3d->persmat; + e_data.context.is_dirty = !compare_m4m4(e_data.context.persmat, persmat, FLT_EPSILON); + if (e_data.context.is_dirty) { + copy_m4_m4(e_data.context.persmat, persmat); + select_id_context_clear(&e_data.context); + } + e_data.runtime_new_objects = 0; } static void select_cache_populate(void *vedata, Object *ob) { + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); - struct ObjectOffsets *base_ofs = - &e_data.context.index_offsets[e_data.context.last_object_drawn++]; - - uint offset = e_data.context.last_index_drawn; - - select_id_draw_object(vedata, - draw_ctx->v3d, - ob, - e_data.context.select_mode, - offset, - &base_ofs->vert, - &base_ofs->edge, - &base_ofs->face); - - base_ofs->offset = offset; - e_data.context.last_index_drawn = base_ofs->vert; + + SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get( + &ob->id, &draw_engine_select_type); + + if (!e_data.context.is_dirty && sel_data && sel_data->is_drawn) { + /* The object indices have already been drawn. Fill depth pass. + * Opti: Most of the time this depth pass is not used. */ + struct Mesh *me = ob->data; + struct GPUBatch *geom_faces; + if (e_data.context.select_mode & SCE_SELECT_FACE) { + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + } + else { + geom_faces = DRW_mesh_batch_cache_get_surface(me); + } + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat); + + if (e_data.context.select_mode & SCE_SELECT_EDGE) { + struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->obmat); + } + + if (e_data.context.select_mode & SCE_SELECT_VERTEX) { + struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->obmat); + } + return; + } + + float min[3], max[3]; + select_id_object_min_max(ob, min, max); + + if (DRW_culling_min_max_test(stl->g_data->view_subregion, ob->obmat, min, max)) { + if (sel_data == NULL) { + sel_data = (SELECTID_ObjectData *)DRW_drawdata_ensure( + &ob->id, &draw_engine_select_type, sizeof(SELECTID_ObjectData), NULL, NULL); + } + sel_data->drawn_index = e_data.context.objects_drawn_len; + sel_data->is_drawn = true; + + struct ObjectOffsets *ob_offsets = + &e_data.context.index_offsets[e_data.context.objects_drawn_len]; + + uint offset = e_data.context.index_drawn_len; + select_id_draw_object(vedata, + draw_ctx->v3d, + ob, + e_data.context.select_mode, + offset, + &ob_offsets->vert, + &ob_offsets->edge, + &ob_offsets->face); + + ob_offsets->offset = offset; + e_data.context.index_drawn_len = ob_offsets->vert; + e_data.context.objects_drawn[e_data.context.objects_drawn_len] = ob; + e_data.context.objects_drawn_len++; + e_data.runtime_new_objects++; + } + else if (sel_data) { + sel_data->is_drawn = false; + } } static void select_draw_scene(void *vedata) @@ -187,17 +265,26 @@ static void select_draw_scene(void *vedata) SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl; - /* Setup framebuffer */ - draw_select_framebuffer_select_id_setup(&e_data.context); - GPU_framebuffer_bind(e_data.context.framebuffer_select_id); + if (!e_data.runtime_new_objects) { + /* Nothing new needs to be drawn. */ + return; + } /* dithering and AA break color coding, so disable */ glDisable(GL_DITHER); - GPU_framebuffer_clear_color_depth( - e_data.context.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); - DRW_view_set_active(stl->g_data->view_faces); + + if (!DRW_pass_is_empty(psl->depth_only_pass)) { + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + GPU_framebuffer_bind(dfbl->depth_only_fb); + GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0f); + DRW_draw_pass(psl->depth_only_pass); + } + + /* Setup framebuffer */ + GPU_framebuffer_bind(e_data.context.framebuffer_select_id); + DRW_draw_pass(psl->select_id_face_pass); if (e_data.context.select_mode & SCE_SELECT_EDGE) { @@ -221,7 +308,9 @@ static void select_engine_free(void) DRW_TEXTURE_FREE_SAFE(e_data.context.texture_u32); GPU_FRAMEBUFFER_FREE_SAFE(e_data.context.framebuffer_select_id); + MEM_SAFE_FREE(e_data.context.objects); MEM_SAFE_FREE(e_data.context.index_offsets); + MEM_SAFE_FREE(e_data.context.objects_drawn); } /** \} */ diff --git a/source/blender/draw/engines/select/select_private.h b/source/blender/draw/engines/select/select_private.h index d95b14ff2b6..e48ce4314ae 100644 --- a/source/blender/draw/engines/select/select_private.h +++ b/source/blender/draw/engines/select/select_private.h @@ -32,6 +32,7 @@ typedef struct SELECTID_StorageList { } SELECTID_StorageList; typedef struct SELECTID_PassList { + struct DRWPass *depth_only_pass; struct DRWPass *select_id_face_pass; struct DRWPass *select_id_edge_pass; struct DRWPass *select_id_vert_pass; @@ -52,18 +53,21 @@ typedef struct SELECTID_Shaders { } SELECTID_Shaders; typedef struct SELECTID_PrivateData { + DRWShadingGroup *shgrp_depth_only; DRWShadingGroup *shgrp_face_unif; DRWShadingGroup *shgrp_face_flat; DRWShadingGroup *shgrp_edge; DRWShadingGroup *shgrp_vert; + DRWView *view_subregion; DRWView *view_faces; DRWView *view_edges; DRWView *view_verts; } SELECTID_PrivateData; /* Transient data */ /* select_draw_utils.c */ -void draw_select_framebuffer_select_id_setup(struct SELECTID_Context *r_select_ctx); +void select_id_context_clear(struct SELECTID_Context *select_ctx); +void select_id_object_min_max(struct Object *obj, float r_min[3], float r_max[3]); short select_id_get_object_select_mode(Scene *scene, Object *ob); void select_id_draw_object(void *vedata, View3D *v3d, diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index a8f67e10a4d..3379aa28d0f 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -597,6 +597,7 @@ bool DRW_view_is_persp_get(const DRWView *view); bool DRW_culling_sphere_test(const DRWView *view, const BoundSphere *bsphere); bool DRW_culling_box_test(const DRWView *view, const BoundBox *bbox); bool DRW_culling_plane_test(const DRWView *view, const float plane[4]); +bool DRW_culling_min_max_test(const DRWView *view, float obmat[4][4], float min[3], float max[3]); void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners); void DRW_culling_frustum_planes_get(const DRWView *view, float planes[6][4]); diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 129b180957a..5dadcdc1457 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -27,6 +27,7 @@ struct GPUBatch; struct GPUMaterial; struct ModifierData; struct Object; +struct ParticleSystem; struct PTCacheEdit; void DRW_shape_cache_free(void); @@ -58,7 +59,7 @@ struct GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob, char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count); -struct GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob); +struct GPUBatch *DRW_cache_object_face_wireframe_get(struct Object *ob); /* Empties */ struct GPUBatch *DRW_cache_plain_axes_get(void); @@ -152,7 +153,7 @@ struct GPUBatch **DRW_cache_curve_surface_shaded_get(struct Object *ob, uint gpumat_array_len); struct GPUBatch *DRW_cache_curve_loose_edges_get(struct Object *ob); struct GPUBatch *DRW_cache_curve_edge_wire_get(struct Object *ob); -struct GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob); +struct GPUBatch *DRW_cache_curve_face_wireframe_get(struct Object *ob); struct GPUBatch *DRW_cache_curve_edge_detection_get(struct Object *ob, bool *r_is_manifold); /* edit-mode */ struct GPUBatch *DRW_cache_curve_edge_normal_get(struct Object *ob); @@ -161,13 +162,13 @@ struct GPUBatch *DRW_cache_curve_vert_overlay_get(struct Object *ob, bool handle /* Font */ struct GPUBatch *DRW_cache_text_surface_get(struct Object *ob); -struct GPUBatch *DRW_cache_text_edge_detection_get(Object *ob, bool *r_is_manifold); +struct GPUBatch *DRW_cache_text_edge_detection_get(struct Object *ob, bool *r_is_manifold); struct GPUBatch *DRW_cache_text_loose_edges_get(struct Object *ob); struct GPUBatch *DRW_cache_text_edge_wire_get(struct Object *ob); struct GPUBatch **DRW_cache_text_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); -struct GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob); +struct GPUBatch *DRW_cache_text_face_wireframe_get(struct Object *ob); /* Surface */ struct GPUBatch *DRW_cache_surf_surface_get(struct Object *ob); @@ -176,7 +177,7 @@ struct GPUBatch *DRW_cache_surf_loose_edges_get(struct Object *ob); struct GPUBatch **DRW_cache_surf_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); -struct GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob); +struct GPUBatch *DRW_cache_surf_face_wireframe_get(struct Object *ob); struct GPUBatch *DRW_cache_surf_edge_detection_get(struct Object *ob, bool *r_is_manifold); /* Lattice */ @@ -206,7 +207,7 @@ struct GPUBatch *DRW_cache_mball_surface_get(struct Object *ob); struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); -struct GPUBatch *DRW_cache_mball_face_wireframe_get(Object *ob); +struct GPUBatch *DRW_cache_mball_face_wireframe_get(struct Object *ob); struct GPUBatch *DRW_cache_mball_edge_detection_get(struct Object *ob, bool *r_is_manifold); #endif /* __DRAW_CACHE_H__ */ diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index 5a06210fe8e..9305dc6eef7 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -86,7 +86,8 @@ typedef struct MeshBufferCache { GPUVertBuf *lnor; /* extend */ GPUVertBuf *edge_fac; /* extend */ GPUVertBuf *weights; /* extend */ - GPUVertBuf *uv_tan; + GPUVertBuf *uv; + GPUVertBuf *tan; GPUVertBuf *vcol; GPUVertBuf *orco; /* Only for edit mode. */ diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index f9d6c9ed582..95b984747bd 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -1554,39 +1554,28 @@ const MeshExtract extract_lnor = {extract_lnor_init, /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract UV / Tangent layers +/** \name Extract UV layers * \{ */ -static void *extract_uv_tan_init(const MeshRenderData *mr, void *buf) +static void *extract_uv_init(const MeshRenderData *mr, void *buf) { GPUVertFormat format = {0}; GPU_vertformat_deinterleave(&format); CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; - CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; uint32_t uv_layers = mr->cache->cd_used.uv; - uint32_t tan_layers = mr->cache->cd_used.tan; - float(*orco)[3] = CustomData_get_layer(cd_vdata, CD_ORCO); - bool orco_allocated = false; - const bool use_orco_tan = mr->cache->cd_used.tan_orco != 0; - /* XXX FIXME XXX */ - /* We use a hash to identify each data layer based on its name. - * Gawain then search for this name in the current shader and bind if it exists. - * NOTE : This is prone to hash collision. - * One solution to hash collision would be to format the cd layer name - * to a safe glsl var name, but without name clash. - * NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */ for (int i = 0; i < MAX_MTFACE; i++) { if (uv_layers & (1 << i)) { - char attr_name[32]; + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); - uint hash = BLI_ghashutil_strhash_p(layer_name); + + GPU_vertformat_safe_attrib_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); /* UV layer name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "u%u", hash); + BLI_snprintf(attr_name, sizeof(attr_name), "u%s", attr_safe_name); GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); /* Auto layer name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "a%u", hash); + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); GPU_vertformat_alias_add(&format, attr_name); /* Active render layer name. */ if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) { @@ -1605,16 +1594,75 @@ static void *extract_uv_tan_init(const MeshRenderData *mr, void *buf) } } + int v_len = mr->loop_len; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + /* VBO will not be used, only allocate minimum of memory. */ + v_len = 1; + } + + GPUVertBuf *vbo = buf; + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, v_len); + + float(*uv_data)[2] = (float(*)[2])vbo->data; + for (int i = 0; i < MAX_MTFACE; i++) { + if (uv_layers & (1 << i)) { + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i); + BMIter f_iter, l_iter; + BMFace *efa; + BMLoop *loop; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs); + memcpy(uv_data, luv->uv, sizeof(*uv_data)); + uv_data++; + } + } + } + else { + MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i); + for (int l = 0; l < mr->loop_len; l++, uv_data++, layer_data++) { + memcpy(uv_data, layer_data->uv, sizeof(*uv_data)); + } + } + } + } + + return NULL; +} + +const MeshExtract extract_uv = { + extract_uv_init, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, false}; +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Extract Tangent layers + * \{ */ + +static void *extract_tan_init(const MeshRenderData *mr, void *buf) +{ + GPUVertFormat format = {0}; + GPU_vertformat_deinterleave(&format); + + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; + uint32_t tan_layers = mr->cache->cd_used.tan; + float(*orco)[3] = CustomData_get_layer(cd_vdata, CD_ORCO); + bool orco_allocated = false; + const bool use_orco_tan = mr->cache->cd_used.tan_orco != 0; + int tan_len = 0; char tangent_names[MAX_MTFACE][MAX_CUSTOMDATA_LAYER_NAME]; for (int i = 0; i < MAX_MTFACE; i++) { if (tan_layers & (1 << i)) { - char attr_name[32]; + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); - uint hash = BLI_ghashutil_strhash_p(layer_name); + GPU_vertformat_safe_attrib_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); /* Tangent layer name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "t%u", hash); + BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name); GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT); /* Active render layer name. */ if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) { @@ -1687,10 +1735,10 @@ static void *extract_uv_tan_init(const MeshRenderData *mr, void *buf) } if (use_orco_tan) { - char attr_name[32]; + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_TANGENT, 0); - uint hash = BLI_ghashutil_strhash_p(layer_name); - BLI_snprintf(attr_name, sizeof(*attr_name), "t%u", hash); + GPU_vertformat_safe_attrib_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); + BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name); GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT); GPU_vertformat_alias_add(&format, "t"); GPU_vertformat_alias_add(&format, "at"); @@ -1711,32 +1759,7 @@ static void *extract_uv_tan_init(const MeshRenderData *mr, void *buf) GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, v_len); - float(*uv_data)[2] = (float(*)[2])vbo->data; - for (int i = 0; i < MAX_MTFACE; i++) { - if (uv_layers & (1 << i)) { - if (mr->extract_type == MR_EXTRACT_BMESH) { - int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i); - BMIter f_iter, l_iter; - BMFace *efa; - BMLoop *loop; - BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs); - memcpy(uv_data, luv->uv, sizeof(*uv_data)); - uv_data++; - } - } - } - else { - MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i); - for (int l = 0; l < mr->loop_len; l++, uv_data++, layer_data++) { - memcpy(uv_data, layer_data->uv, sizeof(*uv_data)); - } - } - } - } - /* Start tan_data after uv_data. */ - float(*tan_data)[4] = (float(*)[4])uv_data; + float(*tan_data)[4] = (float(*)[4])vbo->data; for (int i = 0; i < tan_len; i++) { void *layer_data = CustomData_get_layer_named(cd_ldata, CD_TANGENT, tangent_names[i]); memcpy(tan_data, layer_data, sizeof(*tan_data) * mr->loop_len); @@ -1752,18 +1775,18 @@ static void *extract_uv_tan_init(const MeshRenderData *mr, void *buf) return NULL; } -const MeshExtract extract_uv_tan = {extract_uv_tan_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, - false}; +const MeshExtract extract_tan = {extract_tan_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + false}; /** \} */ @@ -1779,20 +1802,13 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) CustomData *cd_ldata = &mr->me->ldata; uint32_t vcol_layers = mr->cache->cd_used.vcol; - /* XXX FIXME XXX */ - /* We use a hash to identify each data layer based on its name. - * Gawain then search for this name in the current shader and bind if it exists. - * NOTE : This is prone to hash collision. - * One solution to hash collision would be to format the cd layer name - * to a safe glsl var name, but without name clash. - * NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */ for (int i = 0; i < 8; i++) { if (vcol_layers & (1 << i)) { - char attr_name[32]; + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i); - uint hash = BLI_ghashutil_strhash_p(layer_name); + GPU_vertformat_safe_attrib_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); - BLI_snprintf(attr_name, sizeof(attr_name), "c%u", hash); + BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) { @@ -1804,7 +1820,7 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) /* Gather number of auto layers. */ /* We only do vcols that are not overridden by uvs */ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { - BLI_snprintf(attr_name, sizeof(attr_name), "a%u", hash); + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); GPU_vertformat_alias_add(&format, attr_name); } } @@ -4162,7 +4178,8 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, TEST_ASSIGN(VBO, vbo, pos_nor); TEST_ASSIGN(VBO, vbo, lnor); - TEST_ASSIGN(VBO, vbo, uv_tan); + TEST_ASSIGN(VBO, vbo, uv); + TEST_ASSIGN(VBO, vbo, tan); TEST_ASSIGN(VBO, vbo, vcol); TEST_ASSIGN(VBO, vbo, orco); TEST_ASSIGN(VBO, vbo, edge_fac); @@ -4227,7 +4244,8 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, EXTRACT(vbo, pos_nor); EXTRACT(vbo, lnor); - EXTRACT(vbo, uv_tan); + EXTRACT(vbo, uv); + EXTRACT(vbo, tan); EXTRACT(vbo, vcol); EXTRACT(vbo, orco); EXTRACT(vbo, edge_fac); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index f498771b596..12c6a715685 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -244,10 +244,12 @@ static void mesh_cd_extract_auto_layers_names_and_srgb(Mesh *me, for (int i = 0; i < uv_len; i++) { if ((cd_used.uv & (1 << i)) != 0) { const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); - uint hash = BLI_ghashutil_strhash_p(name); + char safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; + GPU_vertformat_safe_attrib_name(name, safe_name, GPU_MAX_SAFE_ATTRIB_NAME); + auto_ofs += BLI_snprintf_rlen( + auto_names + auto_ofs, auto_names_len - auto_ofs, "ba%s", safe_name); /* +1 to include '\0' terminator. */ - auto_ofs += 1 + BLI_snprintf_rlen( - auto_names + auto_ofs, auto_names_len - auto_ofs, "ba%u", hash); + auto_ofs += 1; } } @@ -257,10 +259,12 @@ static void mesh_cd_extract_auto_layers_names_and_srgb(Mesh *me, const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i); /* We only do vcols that are not overridden by a uv layer with same name. */ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) { - uint hash = BLI_ghashutil_strhash_p(name); + char safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; + GPU_vertformat_safe_attrib_name(name, safe_name, GPU_MAX_SAFE_ATTRIB_NAME); + auto_ofs += BLI_snprintf_rlen( + auto_names + auto_ofs, auto_names_len - auto_ofs, "ba%s", safe_name); /* +1 to include '\0' terminator. */ - auto_ofs += 1 + BLI_snprintf_rlen( - auto_names + auto_ofs, auto_names_len - auto_ofs, "ba%u", hash); + auto_ofs += 1; auto_is_srgb[auto_is_srgb_ofs] = true; auto_is_srgb_ofs++; } @@ -460,7 +464,8 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor); - GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv_tan); + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv); + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.tan); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.vcol); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.orco); } @@ -488,7 +493,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.stretch_angle); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.stretch_area); - GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv_tan); + GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_uv); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data); @@ -964,7 +969,10 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) void DRW_mesh_batch_cache_create_requested( Object *ob, Mesh *me, const Scene *scene, const bool is_paint_mode, const bool use_hide) { - const ToolSettings *ts = scene->toolsettings; + const ToolSettings *ts = NULL; + if (scene) { + ts = scene->toolsettings; + } MeshBatchCache *cache = mesh_batch_cache_get(me); /* Early out */ @@ -1009,10 +1017,12 @@ void DRW_mesh_batch_cache_create_requested( if (cd_overlap == false) { FOREACH_MESH_BUFFER_CACHE(cache, mbuffercache) { - if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv || - (cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan || + if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv) { + GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv); + } + if ((cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan || cache->cd_used.tan_orco != cache->cd_needed.tan_orco) { - GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv_tan); + GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.tan); } if (cache->cd_used.orco != cache->cd_needed.orco) { GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.orco); @@ -1046,7 +1056,7 @@ void DRW_mesh_batch_cache_create_requested( GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data); GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.stretch_angle); GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.stretch_area); - GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv_tan); + GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv); GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv); GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris); GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_lines); @@ -1090,7 +1100,7 @@ void DRW_mesh_batch_cache_create_requested( DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.lnor); DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.pos_nor); if (cache->cd_used.uv != 0) { - DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.uv_tan); + DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.uv); } if (cache->cd_used.vcol != 0) { DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.vcol); @@ -1129,7 +1139,7 @@ void DRW_mesh_batch_cache_create_requested( DRW_ibo_request(cache->batch.wire_loops_uvs, &mbufcache->ibo.edituv_lines); /* For paint overlay. Active layer should have been queried. */ if (cache->cd_used.uv != 0) { - DRW_vbo_request(cache->batch.wire_loops_uvs, &mbufcache->vbo.uv_tan); + DRW_vbo_request(cache->batch.wire_loops_uvs, &mbufcache->vbo.uv); } } if (DRW_batch_requested(cache->batch.edit_mesh_analysis, GPU_PRIM_TRIS)) { @@ -1145,9 +1155,11 @@ void DRW_mesh_batch_cache_create_requested( /* Order matters. First ones override latest vbos' attribs. */ DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.lnor); DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.pos_nor); - if ((cache->cd_used.uv != 0) || (cache->cd_used.tan != 0) || - (cache->cd_used.tan_orco != 0)) { - DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.uv_tan); + if (cache->cd_used.uv != 0) { + DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.uv); + } + if ((cache->cd_used.tan != 0) || (cache->cd_used.tan_orco != 0)) { + DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.tan); } if (cache->cd_used.vcol != 0) { DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.vcol); @@ -1223,29 +1235,29 @@ void DRW_mesh_batch_cache_create_requested( /* Edit UV */ if (DRW_batch_requested(cache->batch.edituv_faces, GPU_PRIM_TRIS)) { DRW_ibo_request(cache->batch.edituv_faces, &mbufcache->ibo.edituv_tris); - DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.uv_tan); + DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.uv); DRW_vbo_request(cache->batch.edituv_faces, &mbufcache->vbo.edituv_data); } if (DRW_batch_requested(cache->batch.edituv_faces_strech_area, GPU_PRIM_TRIS)) { DRW_ibo_request(cache->batch.edituv_faces_strech_area, &mbufcache->ibo.edituv_tris); - DRW_vbo_request(cache->batch.edituv_faces_strech_area, &mbufcache->vbo.uv_tan); + DRW_vbo_request(cache->batch.edituv_faces_strech_area, &mbufcache->vbo.uv); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &mbufcache->vbo.edituv_data); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &mbufcache->vbo.stretch_area); } if (DRW_batch_requested(cache->batch.edituv_faces_strech_angle, GPU_PRIM_TRIS)) { DRW_ibo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->ibo.edituv_tris); - DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->vbo.uv_tan); + DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->vbo.uv); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->vbo.edituv_data); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &mbufcache->vbo.stretch_angle); } if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) { DRW_ibo_request(cache->batch.edituv_edges, &mbufcache->ibo.edituv_lines); - DRW_vbo_request(cache->batch.edituv_edges, &mbufcache->vbo.uv_tan); + DRW_vbo_request(cache->batch.edituv_edges, &mbufcache->vbo.uv); DRW_vbo_request(cache->batch.edituv_edges, &mbufcache->vbo.edituv_data); } if (DRW_batch_requested(cache->batch.edituv_verts, GPU_PRIM_POINTS)) { DRW_ibo_request(cache->batch.edituv_verts, &mbufcache->ibo.edituv_points); - DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.uv_tan); + DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.uv); DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.edituv_data); } if (DRW_batch_requested(cache->batch.edituv_fdots, GPU_PRIM_POINTS)) { diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 070713ad404..a2bbb368caa 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1725,9 +1725,9 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, if (G.debug_value > 20 && G.debug_value < 30) { GPU_depth_test(false); - rcti rect; /* local coordinate visible rect inside region, to accommodate overlapping ui */ - ED_region_visible_rect(DST.draw_ctx.ar, &rect); - DRW_stats_draw(&rect); + /* local coordinate visible rect inside region, to accommodate overlapping ui */ + const rcti *rect = ED_region_visible_rect(DST.draw_ctx.ar); + DRW_stats_draw(rect); GPU_depth_test(true); } @@ -2555,20 +2555,11 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, DRW_opengl_context_disable(); } -void DRW_draw_select_id(Depsgraph *depsgraph, - ARegion *ar, - View3D *v3d, - Base **bases, - const uint bases_len, - short select_mode) +void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rcti *rect) { Scene *scene = DEG_get_evaluated_scene(depsgraph); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - DRW_select_buffer_context_create(bases, bases_len, select_mode); - - DRW_opengl_context_enable(); - /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); DST.buffer_finish_called = true; @@ -2584,7 +2575,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, .depsgraph = depsgraph, }; - use_drw_engine(&draw_engine_select_type); drw_context_state_init(); /* Setup viewport */ @@ -2594,16 +2584,18 @@ void DRW_draw_select_id(Depsgraph *depsgraph, /* Update ubos */ DRW_globals_update(); - /* Init engines */ - drw_engines_init(); + /* Init Select Engine */ + struct SELECTID_Context *sel_ctx = DRW_select_engine_context_get(); + sel_ctx->last_rect = *rect; + use_drw_engine(&draw_engine_select_type); + drw_engines_init(); { drw_engines_cache_init(); - /* Keep `base_index` in sync with `e_data.context.last_base_drawn`. - * So don't skip objects. */ - for (uint base_index = 0; base_index < bases_len; base_index++) { - Object *obj_eval = DEG_get_evaluated_object(depsgraph, bases[base_index]->object); + Object **obj = &sel_ctx->objects[0]; + for (uint remaining = sel_ctx->objects_len; remaining--; obj++) { + Object *obj_eval = DEG_get_evaluated_object(depsgraph, *obj); drw_engines_cache_populate(obj_eval); } @@ -2621,10 +2613,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, /* Avoid accidental reuse. */ drw_state_ensure_not_reused(&DST); #endif - - /* Changin context */ - GPU_framebuffer_restore(); - DRW_opengl_context_disable(); } /** See #DRW_shgroup_world_clip_planes_from_rv3d. */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 949d3e1d38b..3bf442b4f39 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -22,6 +22,7 @@ #include "draw_manager.h" +#include "BLI_math.h" #include "BLI_math_bits.h" #include "BLI_memblock.h" @@ -488,6 +489,26 @@ bool DRW_culling_plane_test(const DRWView *view, const float plane[4]) return draw_culling_plane_test(&view->frustum_corners, plane); } +/* Return True if the given box intersect the current view frustum. + * This function will have to be replaced when world space bb per objects is implemented. */ +bool DRW_culling_min_max_test(const DRWView *view, float obmat[4][4], float min[3], float max[3]) +{ + view = view ? view : DST.view_default; + float tobmat[4][4]; + transpose_m4_m4(tobmat, obmat); + for (int i = 6; i--;) { + float frustum_plane_local[4], bb_near[3], bb_far[3]; + mul_v4_m4v4(frustum_plane_local, tobmat, view->frustum_planes[i]); + aabb_get_near_far_from_plane(frustum_plane_local, min, max, bb_near, bb_far); + + if (plane_point_side_v3(frustum_plane_local, bb_far) < 0.0f) { + return false; + } + } + + return true; +} + void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners) { view = view ? view : DST.view_default; diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c index 5e21e5e576c..bab69cf7a57 100644 --- a/source/blender/draw/intern/draw_manager_profiling.c +++ b/source/blender/draw/intern/draw_manager_profiling.c @@ -200,7 +200,7 @@ void DRW_stats_reset(void) } } -static void draw_stat_5row(rcti *rect, int u, int v, const char *txt, const int size) +static void draw_stat_5row(const rcti *rect, int u, int v, const char *txt, const int size) { BLF_draw_default_ascii(rect->xmin + (1 + u * 5) * U.widget_unit, rect->ymax - (3 + v) * U.widget_unit, @@ -209,13 +209,13 @@ static void draw_stat_5row(rcti *rect, int u, int v, const char *txt, const int size); } -static void draw_stat(rcti *rect, int u, int v, const char *txt, const int size) +static void draw_stat(const rcti *rect, int u, int v, const char *txt, const int size) { BLF_draw_default_ascii( rect->xmin + (1 + u) * U.widget_unit, rect->ymax - (3 + v) * U.widget_unit, 0.0f, txt, size); } -void DRW_stats_draw(rcti *rect) +void DRW_stats_draw(const rcti *rect) { char stat_string[64]; int lvl_index[MAX_NESTED_TIMER]; diff --git a/source/blender/draw/intern/draw_manager_profiling.h b/source/blender/draw/intern/draw_manager_profiling.h index 7fe2280f9b2..3da6a4c8b1c 100644 --- a/source/blender/draw/intern/draw_manager_profiling.h +++ b/source/blender/draw/intern/draw_manager_profiling.h @@ -35,6 +35,6 @@ void DRW_stats_group_end(void); void DRW_stats_query_start(const char *name); void DRW_stats_query_end(void); -void DRW_stats_draw(rcti *rect); +void DRW_stats_draw(const rcti *rect); #endif /* __DRAW_MANAGER_PROFILING_H__ */ diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c index cd876b7b068..974ea22ccea 100644 --- a/source/blender/draw/intern/draw_select_buffer.c +++ b/source/blender/draw/intern/draw_select_buffer.c @@ -32,58 +32,81 @@ #include "GPU_select.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "DRW_engine.h" #include "DRW_select_buffer.h" #include "draw_manager.h" +#include "../engines/select/select_engine.h" + /* -------------------------------------------------------------------- */ /** \name Buffer of select ID's * \{ */ -/* Read a block of pixels from the select frame buffer. */ -uint *DRW_select_buffer_read(const rcti *rect, uint *r_buf_len) +/* Main function to read a block of pixels from the select frame buffer. */ +uint *DRW_select_buffer_read(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const rcti *rect, + uint *r_buf_len) { - struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); + uint *r_buf = NULL; + uint buf_len = 0; - /* clamp rect by texture */ + /* Clamp rect. */ rcti r = { .xmin = 0, - .xmax = GPU_texture_width(select_ctx->texture_u32), + .xmax = ar->winx, .ymin = 0, - .ymax = GPU_texture_height(select_ctx->texture_u32), + .ymax = ar->winy, }; + /* Make sure that the rect is within the bounds of the viewport. + * Some GPUs have problems reading pixels off limits. */ rcti rect_clamp = *rect; if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) { - uint buf_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); - uint *r_buf = MEM_mallocN(buf_len * sizeof(*r_buf), __func__); + struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); DRW_opengl_context_enable(); - GPU_framebuffer_bind(select_ctx->framebuffer_select_id); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(rect_clamp.xmin, - rect_clamp.ymin, - BLI_rcti_size_x(&rect_clamp), - BLI_rcti_size_y(&rect_clamp), - GL_RED_INTEGER, - GL_UNSIGNED_INT, - r_buf); + /* Update the drawing. */ + DRW_draw_select_id(depsgraph, ar, v3d, rect); + + if (select_ctx->index_drawn_len > 1) { + BLI_assert(ar->winx == GPU_texture_width(select_ctx->texture_u32) && + ar->winy == GPU_texture_height(select_ctx->texture_u32)); + + /* Read the UI32 pixels. */ + buf_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); + r_buf = MEM_mallocN(buf_len * sizeof(*r_buf), __func__); + + GPU_framebuffer_bind(select_ctx->framebuffer_select_id); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(rect_clamp.xmin, + rect_clamp.ymin, + BLI_rcti_size_x(&rect_clamp), + BLI_rcti_size_y(&rect_clamp), + GL_RED_INTEGER, + GL_UNSIGNED_INT, + r_buf); + + if (!BLI_rcti_compare(rect, &rect_clamp)) { + /* The rect has been clamped so you need to realign the buffer and fill in the blanks */ + GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); + } + } GPU_framebuffer_restore(); DRW_opengl_context_disable(); + } - if (!BLI_rcti_compare(rect, &rect_clamp)) { - GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); - } - - if (r_buf_len) { - *r_buf_len = buf_len; - } - - return r_buf; + if (r_buf_len) { + *r_buf_len = buf_len; } - return NULL; + + return r_buf; } /** \} */ @@ -101,25 +124,27 @@ uint *DRW_select_buffer_read(const rcti *rect, uint *r_buf_len) * \param mask: Specifies the rect pixels (optional). * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. */ -uint *DRW_select_buffer_bitmap_from_rect(const rcti *rect, uint *r_bitmap_len) +uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const rcti *rect, + uint *r_bitmap_len) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - rcti rect_px = *rect; rect_px.xmax += 1; rect_px.ymax += 1; uint buf_len; - uint *buf = DRW_select_buffer_read(&rect_px, &buf_len); + uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect_px, &buf_len); if (buf == NULL) { return NULL; } + BLI_assert(select_ctx->index_drawn_len > 0); + const uint bitmap_len = select_ctx->index_drawn_len - 1; + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); const uint *buf_iter = buf; while (buf_len--) { @@ -144,17 +169,15 @@ uint *DRW_select_buffer_bitmap_from_rect(const rcti *rect, uint *r_bitmap_len) * \param radius: Circle radius. * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. */ -uint *DRW_select_buffer_bitmap_from_circle(const int center[2], +uint *DRW_select_buffer_bitmap_from_circle(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const int radius, uint *r_bitmap_len) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - const rcti rect = { .xmin = center[0] - radius, .xmax = center[0] + radius + 1, @@ -162,15 +185,17 @@ uint *DRW_select_buffer_bitmap_from_circle(const int center[2], .ymax = center[1] + radius + 1, }; - const uint *buf = DRW_select_buffer_read(&rect, NULL); + const uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect, NULL); if (buf == NULL) { return NULL; } - const uint *buf_iter = buf; + BLI_assert(select_ctx->index_drawn_len > 0); + const uint bitmap_len = select_ctx->index_drawn_len - 1; BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + const uint *buf_iter = buf; const int radius_sq = radius * radius; for (int yc = -radius; yc <= radius; yc++) { for (int xc = -radius; xc <= radius; xc++, buf_iter++) { @@ -214,21 +239,22 @@ static void drw_select_mask_px_cb(int x, int x_end, int y, void *user_data) * \param rect: Polygon boundaries. * \returns a #BLI_bitmap. */ -uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len, const rcti *rect) +uint *DRW_select_buffer_bitmap_from_poly(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int poly[][2], + const int poly_len, + const rcti *rect, + uint *r_bitmap_len) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - const uint bitmap_len = select_ctx->last_index_drawn; - if (bitmap_len == 0) { - return NULL; - } - rcti rect_px = *rect; rect_px.xmax += 1; rect_px.ymax += 1; uint buf_len; - uint *buf = DRW_select_buffer_read(&rect_px, &buf_len); + uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect_px, &buf_len); if (buf == NULL) { return NULL; } @@ -248,6 +274,9 @@ uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len drw_select_mask_px_cb, &poly_mask_data); + BLI_assert(select_ctx->index_drawn_len > 0); + const uint bitmap_len = select_ctx->index_drawn_len - 1; + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); const uint *buf_iter = buf; int i = 0; @@ -262,6 +291,10 @@ uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len MEM_freeN((void *)buf); MEM_freeN(buf_mask); + if (r_bitmap_len) { + *r_bitmap_len = bitmap_len; + } + return bitmap_buf; } @@ -277,8 +310,13 @@ uint *DRW_select_buffer_bitmap_from_poly(const int poly[][2], const int poly_len /** * Samples a single pixel. */ -uint DRW_select_buffer_sample_point(const int center[2]) +uint DRW_select_buffer_sample_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2]) { + uint ret = 0; + const rcti rect = { .xmin = center[0], .xmax = center[0] + 1, @@ -287,10 +325,13 @@ uint DRW_select_buffer_sample_point(const int center[2]) }; uint buf_len; - uint *buf = DRW_select_buffer_read(&rect, &buf_len); - BLI_assert(0 != buf_len); - uint ret = buf[0]; - MEM_freeN(buf); + uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect, &buf_len); + if (buf) { + BLI_assert(0 != buf_len); + ret = buf[0]; + MEM_freeN(buf); + } + return ret; } @@ -299,7 +340,10 @@ uint DRW_select_buffer_sample_point(const int center[2]) * \param dist[in,out]: Use to initialize the distance, * when found, this value is set to the distance of the selection that's returned. */ -uint DRW_select_buffer_find_nearest_to_point(const int center[2], +uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + const int center[2], const uint id_min, const uint id_max, uint *dist) @@ -324,7 +368,7 @@ uint DRW_select_buffer_find_nearest_to_point(const int center[2], /* Read from selection framebuffer. */ uint buf_len; - const uint *buf = DRW_select_buffer_read(&rect, &buf_len); + const uint *buf = DRW_select_buffer_read(depsgraph, ar, v3d, &rect, &buf_len); if (buf == NULL) { return index; @@ -401,10 +445,10 @@ bool DRW_select_buffer_elem_get(const uint sel_id, struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); char elem_type = 0; - uint elem_id; + uint elem_id = 0; uint base_index = 0; - for (; base_index < select_ctx->objects_len; base_index++) { + for (; base_index < select_ctx->objects_drawn_len; base_index++) { struct ObjectOffsets *base_ofs = &select_ctx->index_offsets[base_index]; if (base_ofs->face > sel_id) { @@ -424,14 +468,15 @@ bool DRW_select_buffer_elem_get(const uint sel_id, } } - if (base_index == select_ctx->objects_len) { + if (base_index == select_ctx->objects_drawn_len) { return false; } *r_elem = elem_id; if (r_base_index) { - *r_base_index = base_index; + Object *obj_orig = DEG_get_original_object(select_ctx->objects_drawn[base_index]); + *r_base_index = obj_orig->runtime.select_id; } if (r_elem_type) { @@ -441,19 +486,31 @@ bool DRW_select_buffer_elem_get(const uint sel_id, return true; } -uint DRW_select_buffer_context_offset_for_object_elem(const uint base_index, char elem_type) +uint DRW_select_buffer_context_offset_for_object_elem(Depsgraph *depsgraph, + Object *object, + char elem_type) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - struct ObjectOffsets *base_ofs = &select_ctx->index_offsets[base_index]; + + Object *ob_eval = DEG_get_evaluated_object(depsgraph, object); + + SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get( + &ob_eval->id, &draw_engine_select_type); + + if (!sel_data || !sel_data->is_drawn) { + return 0; + } + + struct ObjectOffsets *base_ofs = &select_ctx->index_offsets[sel_data->drawn_index]; if (elem_type == SCE_SELECT_VERTEX) { - return base_ofs->vert_start - 1; + return base_ofs->vert_start; } if (elem_type == SCE_SELECT_EDGE) { - return base_ofs->edge_start - 1; + return base_ofs->edge_start; } if (elem_type == SCE_SELECT_FACE) { - return base_ofs->face_start - 1; + return base_ofs->face_start; } BLI_assert(0); return 0; @@ -465,35 +522,29 @@ uint DRW_select_buffer_context_offset_for_object_elem(const uint base_index, cha /** \name Context * \{ */ -void DRW_select_buffer_context_create(Base **UNUSED(bases), - const uint bases_len, - short select_mode) +void DRW_select_buffer_context_create(Base **bases, const uint bases_len, short select_mode) { struct SELECTID_Context *select_ctx = DRW_select_engine_context_get(); - select_ctx->select_mode = select_mode; - select_ctx->objects_len = bases_len; + select_ctx->objects = MEM_reallocN(select_ctx->objects, + sizeof(*select_ctx->objects) * bases_len); - MEM_SAFE_FREE(select_ctx->index_offsets); - select_ctx->index_offsets = MEM_mallocN(sizeof(*select_ctx->index_offsets) * bases_len, - __func__); -} + select_ctx->index_offsets = MEM_reallocN(select_ctx->index_offsets, + sizeof(*select_ctx->index_offsets) * bases_len); -/** \} */ + select_ctx->objects_drawn = MEM_reallocN(select_ctx->objects_drawn, + sizeof(*select_ctx->objects_drawn) * bases_len); -/* -------------------------------------------------------------------- */ -/** \name Legacy - * \{ */ + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obj = bases[base_index]->object; + select_ctx->objects[base_index] = obj; -void DRW_draw_select_id_object(Depsgraph *depsgraph, - ViewLayer *view_layer, - ARegion *ar, - View3D *v3d, - Object *ob, - short select_mode) -{ - Base *base = BKE_view_layer_base_find(view_layer, ob); - DRW_draw_select_id(depsgraph, ar, v3d, &base, 1, select_mode); -} + /* Weak but necessary for `DRW_select_buffer_elem_get`. */ + obj->runtime.select_id = base_index; + } + select_ctx->objects_len = bases_len; + select_ctx->select_mode = select_mode; + memset(select_ctx->persmat, 0, sizeof(select_ctx->persmat)); +} /** \} */ diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index dce6ed29c05..697d06aa098 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -936,7 +936,6 @@ static void annotation_draw_data_layers( /* draw a short status message in the top-right corner */ static void annotation_draw_status_text(const bGPdata *gpd, ARegion *ar) { - rcti rect; /* Cannot draw any status text when drawing OpenGL Renders */ if (G.f & G_FLAG_RENDER_VIEWPORT) { @@ -944,7 +943,7 @@ static void annotation_draw_status_text(const bGPdata *gpd, ARegion *ar) } /* Get bounds of region - Necessary to avoid problems with region overlap */ - ED_region_visible_rect(ar, &rect); + const rcti *rect = ED_region_visible_rect(ar); /* for now, this should only be used to indicate when we are in stroke editmode */ if (gpd->flag & GP_DATA_STROKE_EDITMODE) { @@ -956,8 +955,8 @@ static void annotation_draw_status_text(const bGPdata *gpd, ARegion *ar) BLF_width_and_height( font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; - int yco = (rect.ymax - U.widget_unit); + int xco = (rect->xmax - U.widget_unit) - (int)printable_size[0]; + int yco = (rect->ymax - U.widget_unit); /* text label */ UI_FontThemeColor(font_id, TH_TEXT_HI); diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index c9c4a67644e..07b61751b22 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -2242,11 +2242,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (p->ar) { - rcti region_rect; - - /* Perform bounds check using */ - ED_region_visible_rect(p->ar, ®ion_rect); - in_bounds = BLI_rcti_isect_pt_v(®ion_rect, event->mval); + /* Perform bounds check. */ + const rcti *region_rect = ED_region_visible_rect(p->ar); + in_bounds = BLI_rcti_isect_pt_v(region_rect, event->mval); } else { /* No region */ diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 2b31af5ff1f..7c76f3aeab6 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -1173,15 +1173,14 @@ void ED_gp_draw_fill(tGPDdraw *tgpw) /* draw a short status message in the top-right corner */ static void UNUSED_FUNCTION(gp_draw_status_text)(const bGPdata *gpd, ARegion *ar) { - rcti rect; /* Cannot draw any status text when drawing OpenGL Renders */ if (G.f & G_FLAG_RENDER_VIEWPORT) { return; } - /* Get bounds of region - Necessary to avoid problems with region overlap */ - ED_region_visible_rect(ar, &rect); + /* Get bounds of region - Necessary to avoid problems with region overlap. */ + const rcti *rect = ED_region_visible_rect(ar); /* for now, this should only be used to indicate when we are in stroke editmode */ if (gpd->flag & GP_DATA_STROKE_EDITMODE) { @@ -1193,8 +1192,8 @@ static void UNUSED_FUNCTION(gp_draw_status_text)(const bGPdata *gpd, ARegion *ar BLF_width_and_height( font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; - int yco = (rect.ymax - U.widget_unit); + int xco = (rect->xmax - U.widget_unit) - (int)printable_size[0]; + int yco = (rect->ymax - U.widget_unit); /* text label */ UI_FontThemeColor(font_id, TH_TEXT_HI); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 894fb6eced4..a5425d64c2e 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -3629,11 +3629,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (p->ar) { - rcti region_rect; - /* Perform bounds check using */ - ED_region_visible_rect(p->ar, ®ion_rect); - in_bounds = BLI_rcti_isect_pt_v(®ion_rect, event->mval); + const rcti *region_rect = ED_region_visible_rect(p->ar); + in_bounds = BLI_rcti_isect_pt_v(region_rect, event->mval); } else { /* No region */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index e67a3b003fc..c7ee7be49b5 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -124,7 +124,8 @@ void ED_region_image_metadata_draw( void ED_region_image_metadata_panel_draw(struct ImBuf *ibuf, struct uiLayout *layout); void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_alpha(struct ARegion *ar); -void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); +void ED_region_visible_rect_calc(struct ARegion *ar, struct rcti *rect); +const rcti *ED_region_visible_rect(ARegion *ar); bool ED_region_is_overlap(int spacetype, int regiontype); int ED_region_snap_size_test(const struct ARegion *ar); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index f9c65249918..7a123599be5 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2553,8 +2553,8 @@ void ui_but_string_get_ex(uiBut *but, } } else { + const int int_digits_num = integer_digits_f(value); if (use_exp_float) { - const int int_digits_num = integer_digits_f(value); if (int_digits_num < -6 || int_digits_num > 12) { BLI_snprintf(str, maxlen, "%.*g", prec, value); if (r_use_exp_float) { @@ -2568,10 +2568,8 @@ void ui_but_string_get_ex(uiBut *but, } } else { -#if 0 /* TODO, but will likely break some stuff, so better after 2.79 release. */ prec -= int_digits_num; CLAMP(prec, 0, UI_PRECISION_FLOAT_MAX); -#endif BLI_snprintf(str, maxlen, "%.*f", prec, value); } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6ae7793509d..0cb0dbdc85c 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4800,37 +4800,24 @@ static int ui_do_but_NUM( if (click) { /* we can click on the side arrows to increment/decrement, * or click inside to edit the value directly */ - float tempf, softmin, softmax; - int temp; - - softmin = but->softmin; - softmax = but->softmax; + const float softmin = but->softmin; + const float softmax = but->softmax; if (!ui_but_is_float(but)) { - if (but->drawflag & UI_BUT_ACTIVE_LEFT) { + /* Integer Value. */ + if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - temp = (int)data->value - 1; - if (temp >= softmin && temp <= softmax) { - data->value = (double)temp; + const int value_step = (int)but->a1; + BLI_assert(value_step > 0); + const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ? + (double)max_ii((int)softmin, (int)data->value - value_step) : + (double)min_ii((int)softmax, (int)data->value + value_step); + if (value_test != data->value) { + data->value = (double)value_test; } else { data->cancel = true; } - - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) { - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - temp = (int)data->value + 1; - if (temp >= softmin && temp <= softmax) { - data->value = (double)temp; - } - else { - data->cancel = true; - } - button_activate_state(C, but, BUTTON_STATE_EXIT); } else { @@ -4838,26 +4825,20 @@ static int ui_do_but_NUM( } } else { - if (but->drawflag & UI_BUT_ACTIVE_LEFT) { + /* Float Value. */ + if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - tempf = (float)data->value - (UI_PRECISION_FLOAT_SCALE * but->a1); - if (tempf < softmin) { - tempf = softmin; + const double value_step = (double)but->a1 * UI_PRECISION_FLOAT_SCALE; + BLI_assert(value_step > 0.0f); + const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ? + (double)max_ff(softmin, (float)(data->value - value_step)) : + (double)min_ff(softmax, (float)(data->value + value_step)); + if (value_test != data->value) { + data->value = value_test; } - data->value = tempf; - - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else if (but->drawflag & UI_BUT_ACTIVE_RIGHT) { - button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - - tempf = (float)data->value + (UI_PRECISION_FLOAT_SCALE * but->a1); - if (tempf > softmax) { - tempf = softmax; + else { + data->cancel = true; } - data->value = tempf; - button_activate_state(C, but, BUTTON_STATE_EXIT); } else { diff --git a/source/blender/editors/interface/view2d_gizmo_navigate.c b/source/blender/editors/interface/view2d_gizmo_navigate.c index 883f16c63f2..9b15f2309a1 100644 --- a/source/blender/editors/interface/view2d_gizmo_navigate.c +++ b/source/blender/editors/interface/view2d_gizmo_navigate.c @@ -201,21 +201,20 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g struct NavigateWidgetGroup *navgroup = gzgroup->customdata; ARegion *ar = CTX_wm_region(C); - rcti rect_visible; - ED_region_visible_rect(ar, &rect_visible); + const rcti *rect_visible = ED_region_visible_rect(ar); - if ((navgroup->state.rect_visible.xmax == rect_visible.xmax) && - (navgroup->state.rect_visible.ymax == rect_visible.ymax)) { + if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) && + (navgroup->state.rect_visible.ymax == rect_visible->ymax)) { return; } - navgroup->state.rect_visible = rect_visible; + navgroup->state.rect_visible = *rect_visible; const float icon_size = GIZMO_SIZE; const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC; const float co[2] = { - rect_visible.xmax - (icon_offset_mini * 0.75f), - rect_visible.ymax - (icon_offset_mini * 0.75f), + rect_visible->xmax - (icon_offset_mini * 0.75f), + rect_visible->ymax - (icon_offset_mini * 0.75f), }; wmGizmo *gz; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 2f4688e2de7..94ffd9a34d6 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -317,9 +317,10 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, SCE_SELECT_VERTEX); + DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_VERTEX); - index = DRW_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); + index = DRW_select_buffer_find_nearest_to_point( + vc->depsgraph, vc->ar, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px); if (index) { eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, &base_index); @@ -539,9 +540,10 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, SCE_SELECT_EDGE); + DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_EDGE); - index = DRW_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); + index = DRW_select_buffer_find_nearest_to_point( + vc->depsgraph, vc->ar, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px); if (index) { eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, &base_index); @@ -745,9 +747,9 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, BMFace *efa; { - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, SCE_SELECT_FACE); + DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_FACE); - index = DRW_select_buffer_sample_point(vc->mval); + index = DRW_select_buffer_sample_point(vc->depsgraph, vc->ar, vc->v3d, vc->mval); if (index) { efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 0bdc59c7185..8d9d0e40f44 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1116,11 +1116,12 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, if (dist_px) { /* sample rect to increase chances of selecting, so that when clicking * on an edge in the backbuf, we can still select a face */ - *r_index = DRW_select_buffer_find_nearest_to_point(mval, 1, me->totpoly + 1, &dist_px); + *r_index = DRW_select_buffer_find_nearest_to_point( + vc.depsgraph, vc.ar, vc.v3d, mval, 1, me->totpoly + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = DRW_select_buffer_sample_point(mval); + *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.ar, vc.v3d, mval); } if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) { @@ -1297,11 +1298,12 @@ bool ED_mesh_pick_vert( if (dist_px > 0) { /* sample rect to increase chances of selecting, so that when clicking * on an face in the backbuf, we can still select a vert */ - *r_index = DRW_select_buffer_find_nearest_to_point(mval, 1, me->totvert + 1, &dist_px); + *r_index = DRW_select_buffer_find_nearest_to_point( + vc.depsgraph, vc.ar, vc.v3d, mval, 1, me->totvert + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = DRW_select_buffer_sample_point(mval); + *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.ar, vc.v3d, mval); } if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) { diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 2234b3875b7..1bcac9b4739 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -47,7 +47,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_customdata.h" -#include "BKE_remesh.h" +#include "BKE_mesh_remesh_voxel.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -102,7 +102,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) ED_sculpt_undo_geometry_begin(ob); } - new_mesh = BKE_remesh_voxel_to_mesh_nomain(mesh, mesh->remesh_voxel_size); + new_mesh = BKE_mesh_remesh_voxel_to_mesh_nomain(mesh, mesh->remesh_voxel_size); if (!new_mesh) { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index a43ac59c9b8..08fe5e818b2 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1139,7 +1139,7 @@ static bool vgroup_normalize(Object *ob) int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = vertex_group_use_vert_sel(ob); + const bool use_vert_sel = vertex_group_use_vert_sel(ob); if (!BLI_findlink(&ob->defbase, def_nr)) { return false; @@ -1623,7 +1623,7 @@ static bool vgroup_normalize_all(Object *ob, int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = vertex_group_use_vert_sel(ob); + const bool use_vert_sel = vertex_group_use_vert_sel(ob); if (subset_count == 0) { BKE_report(reports, RPT_ERROR, "No vertex groups to operate on"); @@ -2047,7 +2047,7 @@ static int vgroup_limit_total_subset(Object *ob, { MDeformVert *dv, **dvert_array = NULL; int i, dvert_tot = 0; - const int use_vert_sel = vertex_group_use_vert_sel(ob); + const bool use_vert_sel = vertex_group_use_vert_sel(ob); int remove_tot = 0; ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 5099c370a85..1775a0c55a2 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -188,51 +188,17 @@ void ED_area_do_refresh(bContext *C, ScrArea *sa) /** * \brief Corner widget use for quitting fullscreen. */ -static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, float alpha) +static void area_draw_azone_fullscreen( + short UNUSED(x1), short UNUSED(y1), short x2, short y2, float alpha) { - int x = x2 - ((float)x2 - x1) * 0.5f / UI_DPI_FAC; - int y = y2 - ((float)y2 - y1) * 0.5f / UI_DPI_FAC; - - /* adjust the icon distance from the corner */ - x += 36.0f / UI_DPI_FAC; - y += 36.0f / UI_DPI_FAC; - - /* draws from the left bottom corner of the icon */ - x -= UI_DPI_ICON_SIZE; - y -= UI_DPI_ICON_SIZE; - - alpha = min_ff(alpha, 0.75f); - - UI_icon_draw_ex(x, y, ICON_FULLSCREEN_EXIT, 0.7f * U.inv_dpi_fac, 0.0f, alpha, NULL, false); - - /* debug drawing : - * The click_rect is the same as defined in fullscreen_click_rcti_init - * Keep them both in sync */ - - if (G.debug_value == 101) { - rcti click_rect; - float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC; - - BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size); - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - immUniformColor4f(1.0f, 0.0f, 0.0f, alpha); - imm_draw_box_wire_2d(pos, click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax); - - immUniformColor4f(0.0f, 1.0f, 1.0f, alpha); - immBegin(GPU_PRIM_LINES, 4); - immVertex2f(pos, click_rect.xmin, click_rect.ymin); - immVertex2f(pos, click_rect.xmax, click_rect.ymax); - immVertex2f(pos, click_rect.xmin, click_rect.ymax); - immVertex2f(pos, click_rect.xmax, click_rect.ymin); - immEnd(); - - immUnbindProgram(); - } + UI_icon_draw_ex(x2 - U.widget_unit, + y2 - U.widget_unit, + ICON_FULLSCREEN_EXIT, + U.inv_dpi_fac, + min_ff(alpha, 0.75f), + 0.0f, + NULL, + false); } /** @@ -368,7 +334,9 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) } } else if (az->type == AZONE_FULLSCREEN) { - area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha); + if (az->alpha > 0.0f) { + area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha); + } } } if (!IS_EQF(az->alpha, 0.0f) && ELEM(az->type, AZONE_FULLSCREEN, AZONE_REGION_SCROLL)) { @@ -906,10 +874,18 @@ static void fullscreen_azone_initialize(ScrArea *sa, ARegion *ar) az->ar = ar; az->alpha = 0.0f; - az->x1 = ar->winrct.xmax - (AZONEFADEOUT - 1); - az->y1 = ar->winrct.ymax - (AZONEFADEOUT - 1); - az->x2 = ar->winrct.xmax; - az->y2 = ar->winrct.ymax; + if (U.uiflag2 & USER_REGION_OVERLAP) { + const rcti *rect_visible = ED_region_visible_rect(ar); + az->x2 = ar->winrct.xmin + rect_visible->xmax; + az->y2 = ar->winrct.ymin + rect_visible->ymax; + } + else { + az->x2 = ar->winrct.xmax; + az->y2 = ar->winrct.ymax; + } + az->x1 = az->x2 - AZONEFADEOUT; + az->y1 = az->y2 - AZONEFADEOUT; + BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2); } @@ -1515,6 +1491,9 @@ static void region_rect_recursive( if (ar->winx != prev_winx || ar->winy != prev_winy) { ED_region_tag_redraw(ar); } + + /* Clear, initialize on demand. */ + memset(&ar->runtime.visible_rect, 0, sizeof(ar->runtime.visible_rect)); } static void area_calc_totrct(ScrArea *sa, const rcti *window_rect) @@ -2809,11 +2788,10 @@ void ED_region_info_draw_multiline(ARegion *ar, uiStyle *style = UI_style_get_dpi(); int fontid = style->widget.uifont_id; int scissor[4]; - rcti rect; int num_lines = 0; /* background box */ - ED_region_visible_rect(ar, &rect); + rcti rect = *ED_region_visible_rect(ar); /* Box fill entire width or just around text. */ if (!full_redraw) { @@ -3291,7 +3269,7 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) /* If the area has overlapping regions, it returns visible rect for Region *ar */ /* rect gets returned in local region coordinates */ -void ED_region_visible_rect(ARegion *ar, rcti *rect) +static void region_visible_rect_calc(ARegion *ar, rcti *rect) { ARegion *arn = ar; @@ -3338,6 +3316,15 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect) BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin); } +const rcti *ED_region_visible_rect(ARegion *ar) +{ + rcti *rect = &ar->runtime.visible_rect; + if (rect->xmin == 0 && rect->ymin == 0 && rect->xmax == 0 && rect->ymax == 0) { + region_visible_rect_calc(ar, rect); + } + return rect; +} + /* Cache display helpers */ void ED_region_cache_draw_background(const ARegion *ar) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 4fb5e0c1af3..8377fd0e128 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -696,21 +696,9 @@ static bool actionzone_area_poll(bContext *C) /* the debug drawing of the click_rect is in area_draw_azone_fullscreen, keep both in sync */ static void fullscreen_click_rcti_init( - rcti *rect, const short x1, const short y1, const short x2, const short y2) + rcti *rect, const short UNUSED(x1), const short UNUSED(y1), const short x2, const short y2) { - int x = x2 - ((float)x2 - x1) * 0.5f / UI_DPI_FAC; - int y = y2 - ((float)y2 - y1) * 0.5f / UI_DPI_FAC; - float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC; - - /* adjust the icon distance from the corner */ - x += 36.0f / UI_DPI_FAC; - y += 36.0f / UI_DPI_FAC; - - /* draws from the left bottom corner of the icon */ - x -= UI_DPI_ICON_SIZE; - y -= UI_DPI_ICON_SIZE; - - BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size); + BLI_rcti_init(rect, x2 - U.widget_unit, x2, y2 - U.widget_unit, y2); } static bool azone_clipped_rect_calc(const AZone *az, rcti *r_rect_clip) diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c index c7ec4f3f2b9..93dcd3ad0f6 100644 --- a/source/blender/editors/sculpt_paint/paint_image_undo.c +++ b/source/blender/editors/sculpt_paint/paint_image_undo.c @@ -75,7 +75,8 @@ typedef struct UndoImageTile { * adds unnecessary overhead restoring undo steps when most tiles share the same image. */ UndoRefID_Image image_ref; - short source, use_float; + short source; + bool use_float; char gen_type; bool valid; @@ -172,7 +173,7 @@ void *image_undo_find_tile(ListBase *undo_tiles, bool validate) { UndoImageTile *tile; - short use_float = ibuf->rect_float ? 1 : 0; + const bool use_float = (ibuf->rect_float != NULL); for (tile = undo_tiles->first; tile; tile = tile->next) { if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && @@ -214,7 +215,7 @@ void *image_undo_push_tile(ListBase *undo_tiles, { UndoImageTile *tile; int allocsize; - short use_float = ibuf->rect_float ? 1 : 0; + const bool use_float = (ibuf->rect_float != NULL); void *data; /* check if tile is already pushed */ @@ -315,7 +316,6 @@ static void image_undo_restore_list(ListBase *lb) IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect); for (UndoImageTile *tile = lb->first; tile; tile = tile->next) { - short use_float; Image *ima = tile->image_ref.ptr; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); @@ -341,7 +341,7 @@ static void image_undo_restore_list(ListBase *lb) continue; } - use_float = ibuf->rect_float ? 1 : 0; + const bool use_float = (ibuf->rect_float != NULL); if (use_float != tile->use_float) { BKE_image_release_ibuf(ima, ibuf, NULL); @@ -450,7 +450,7 @@ static bool image_undosys_step_encode(struct bContext *C, tile = tmp_tile; } else { - us->step.data_size += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char)); + us->step.data_size += allocsize * (tile->use_float ? sizeof(float) : sizeof(char)); tile = tile->next; } } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 806b7c471c6..4b9d9a2cc01 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -392,7 +392,7 @@ static int imapaint_pick_face(ViewContext *vc, /* sample only on the exact position */ ED_view3d_select_id_validate(vc); - *r_index = DRW_select_buffer_sample_point(mval); + *r_index = DRW_select_buffer_sample_point(vc->depsgraph, vc->ar, vc->v3d, mval); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; 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 72fc08cc38d..4aa9dc8a295 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -580,7 +580,7 @@ typedef struct WPGradient_userData { BLI_bitmap *vert_visit; /* options */ - short use_select; + bool use_select; short type; float weightpaint; } WPGradient_userData; @@ -786,7 +786,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) data.sco_end = sco_end; data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end); data.def_nr = ob->actdef - 1; - data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)); + data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0; data.vert_cache = vert_cache; data.vert_visit = NULL; data.type = RNA_enum_get(op->ptr, "type"); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index efaac6e97cf..440c4d42cae 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -92,6 +92,240 @@ #include <stdlib.h> #include <string.h> +/* Sculpt PBVH abstraction API */ + +/* Do not use these functions while working with PBVH_GRIDS data in SculptSession */ + +/* TODO: why is this kept, should it be removed? */ +#if 0 /* UNUSED */ + +static int sculpt_active_vertex_get(SculptSession *ss) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + return ss->active_vertex_index; + case PBVH_BMESH: + return ss->active_vertex_index; + default: + return 0; + } +} + +static int sculpt_vertex_count_get(SculptSession *ss) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + return ss->totvert; + case PBVH_BMESH: + return BM_mesh_elem_count(BKE_pbvh_get_bmesh(ss->pbvh), BM_VERT); + default: + return 0; + } +} + +static void sculpt_vertex_normal_get(SculptSession *ss, int index, float no[3]) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + normal_short_to_float_v3(no, ss->mvert[index].no); + return; + case PBVH_BMESH: + copy_v3_v3(no, BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->no); + default: + return; + } +} + +static float *sculpt_vertex_co_get(SculptSession *ss, int index) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + return ss->mvert[index].co; + case PBVH_BMESH: + return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co; + default: + return NULL; + } +} + +static void sculpt_vertex_co_set(SculptSession *ss, int index, float co[3]) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + copy_v3_v3(ss->mvert[index].co, co); + return; + case PBVH_BMESH: + copy_v3_v3(BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co, co); + return; + default: + return; + } +} + +static void sculpt_vertex_mask_set(SculptSession *ss, int index, float mask) +{ + BMVert *v; + float *mask_p; + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + ss->vmask[index] = mask; + return; + case PBVH_BMESH: + v = BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index); + mask_p = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK)); + *(mask_p) = mask; + return; + default: + return; + } +} + +static float sculpt_vertex_mask_get(SculptSession *ss, int index) +{ + BMVert *v; + float *mask; + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + return ss->vmask[index]; + case PBVH_BMESH: + v = BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index); + mask = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK)); + return *mask; + default: + return 0; + } +} + +static void sculpt_vertex_tag_update(SculptSession *ss, int index) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + ss->mvert[index].flag |= ME_VERT_PBVH_UPDATE; + return; + case PBVH_BMESH: + return; + default: + return; + } +} + +# define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256 + +typedef struct SculptVertexNeighborIter { + int *neighbors; + int size; + int capacity; + + int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY]; + + int index; + int i; +} SculptVertexNeighborIter; + +static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neighbor_index) +{ + for (int i = 0; i < iter->size; i++) { + if (iter->neighbors[i] == neighbor_index) { + return; + } + } + + if (iter->size >= iter->capacity) { + iter->capacity += SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; + + if (iter->neighbors == iter->neighbors_fixed) { + iter->neighbors = MEM_mallocN(iter->capacity * sizeof(int), "neighbor array"); + memcpy(iter->neighbors, iter->neighbors_fixed, sizeof(int) * iter->size); + } + else { + iter->neighbors = MEM_reallocN_id( + iter->neighbors, iter->capacity * sizeof(int), "neighbor array"); + } + } + + iter->neighbors[iter->size] = neighbor_index; + iter->size++; +} + +static void sculpt_vertex_neighbors_get_bmesh(SculptSession *ss, + int index, + SculptVertexNeighborIter *iter) +{ + BMVert *v = BM_vert_at_index(ss->bm, index); + BMIter liter; + BMLoop *l; + iter->size = 0; + iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; + iter->neighbors = iter->neighbors_fixed; + + int i = 0; + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + const BMVert *adj_v[2] = {l->prev->v, l->next->v}; + for (i = 0; i < ARRAY_SIZE(adj_v); i++) { + const BMVert *v_other = adj_v[i]; + if (BM_elem_index_get(v_other) != (int)index) { + sculpt_vertex_neighbor_add(iter, BM_elem_index_get(v_other)); + } + } + } +} + +static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, + int index, + SculptVertexNeighborIter *iter) +{ + int i; + MeshElemMap *vert_map = &ss->pmap[(int)index]; + iter->size = 0; + iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; + iter->neighbors = iter->neighbors_fixed; + + for (i = 0; i < ss->pmap[(int)index].count; i++) { + const MPoly *p = &ss->mpoly[vert_map->indices[i]]; + unsigned f_adj_v[2]; + if (poly_get_adj_loops_from_vert(p, ss->mloop, (int)index, f_adj_v) != -1) { + int j; + for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { + if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) { + if (f_adj_v[j] != (int)index) { + sculpt_vertex_neighbor_add(iter, f_adj_v[j]); + } + } + } + } + } +} + +static void sculpt_vertex_neighbors_get(SculptSession *ss, + int index, + SculptVertexNeighborIter *iter) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + sculpt_vertex_neighbors_get_faces(ss, index, iter); + return; + case PBVH_BMESH: + sculpt_vertex_neighbors_get_bmesh(ss, index, iter); + return; + default: + break; + } +} + +# define sculpt_vertex_neighbors_iter_begin(ss, v_index, neighbor_iterator) \ + sculpt_vertex_neighbors_get(ss, v_index, &neighbor_iterator); \ + for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \ + neighbor_iterator.i++) { \ + neighbor_iterator.index = ni.neighbors[ni.i]; + +# define sculpt_vertex_neighbors_iter_end(neighbor_iterator) \ + } \ + if (neighbor_iterator.neighbors != neighbor_iterator.neighbors_fixed) { \ + MEM_freeN(neighbor_iterator.neighbors); \ + } + +#endif /* UNUSED */ + /** \name Tool Capabilities * * Avoid duplicate checks, internal logic only, diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index fde8b8f85f8..bb381e0dd1e 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -785,11 +785,11 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r SpaceProperties *sbuts = CTX_wm_space_properties(C); ButsContextPath *path = sbuts ? sbuts->path : NULL; - if (sbuts->mainb == BCONTEXT_TOOL) { + if (!path) { return 0; } - if (!path) { + if (sbuts->mainb == BCONTEXT_TOOL) { return 0; } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 97a3c7f2480..9a2b0d95c20 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -156,9 +156,8 @@ void ED_image_draw_info(Scene *scene, char str[256]; int dx = 6; /* local coordinate visible rect inside region, to accommodate overlapping ui */ - rcti rect; - ED_region_visible_rect(ar, &rect); - const int ymin = rect.ymin; + const rcti *rect = ED_region_visible_rect(ar); + const int ymin = rect->ymin; const int dy = ymin + 0.3f * UI_UNIT_Y; /* text colors */ diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 17f808f727d..33e77d3623e 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -501,11 +501,10 @@ static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar) int winy = BLI_rcti_size_y(&ar->winrct) + 1; /* For region overlap, move center so image doesn't overlap header. */ - rcti visible_rect; - ED_region_visible_rect(ar, &visible_rect); - const int visible_winy = BLI_rcti_size_y(&visible_rect) + 1; + const rcti *visible_rect = ED_region_visible_rect(ar); + const int visible_winy = BLI_rcti_size_y(visible_rect) + 1; int visible_centerx = 0; - int visible_centery = visible_rect.ymin + (visible_winy - winy) / 2; + int visible_centery = visible_rect->ymin + (visible_winy - winy) / 2; ar->v2d.tot.xmin = 0; ar->v2d.tot.ymin = 0; diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 03c83305618..f8c30f9a688 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -71,6 +71,10 @@ if(WITH_COMPOSITOR) add_definitions(-DWITH_COMPOSITOR) endif() +if(WITH_OPENIMAGEDENOISE) + add_definitions(-DWITH_OPENIMAGEDENOISE) +endif() + add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 704d878e620..748e485f614 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2691,6 +2691,15 @@ static void node_composit_buts_brightcontrast(uiLayout *layout, uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE); } +static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ +#ifndef WITH_OPENIMAGEDENOISE + uiItemL(layout, IFACE_("Disabled, built without OpenImageDenoise"), ICON_ERROR); +#endif + + uiItemR(layout, ptr, "use_hdr", 0, NULL, ICON_NONE); +} + /* only once called */ static void node_composit_set_butfunc(bNodeType *ntype) { @@ -2924,6 +2933,10 @@ static void node_composit_set_butfunc(bNodeType *ntype) break; case CMP_NODE_BRIGHTCONTRAST: ntype->draw_buttons = node_composit_buts_brightcontrast; + break; + case CMP_NODE_DENOISE: + ntype->draw_buttons = node_composit_buts_denoise; + break; } } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 19fd4511e50..531dd583d34 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -1384,8 +1384,15 @@ static int outliner_item_do_activate_from_cursor(bContext *C, } else { outliner_item_select(soops, activate_te, extend, extend); - do_outliner_item_activate_tree_element( - C, scene, view_layer, soops, activate_te, activate_tselem, extend, false); + + /* Only change modes when clicking on the icon/text, + * otherwise we can't easily select without changing modes. */ + if ((te->flag & TE_ICONROW) == 0) { + if (view_mval[0] >= te->xs && view_mval[0] <= te->xend) { + do_outliner_item_activate_tree_element( + C, scene, view_layer, soops, activate_te, activate_tselem, extend, false); + } + } } changed = true; diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 12b446c3f4c..9aa9d14cbc8 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -675,10 +675,9 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *ar) WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D); if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { - rcti rect; - ED_region_visible_rect(ar, &rect); - int xoffset = rect.xmin + U.widget_unit; - int yoffset = rect.ymax; + const rcti *rect = ED_region_visible_rect(ar); + int xoffset = rect->xmin + U.widget_unit; + int yoffset = rect->ymax; ED_scene_draw_fps(scene, xoffset, &yoffset); } } diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c index a6393291f9a..4a628cf70e4 100644 --- a/source/blender/editors/space_text/text_undo.c +++ b/source/blender/editors/space_text/text_undo.c @@ -187,6 +187,7 @@ static bool text_undosys_step_encode(struct bContext *C, Text *text = us->text_ref.ptr; BLI_assert(text == CTX_data_edit_text(C)); + UNUSED_VARS_NDEBUG(C); us->step.data_size += text_undosys_step_encode_to_state(&us->states[1], text); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 8844428b1bf..6c534ee1b98 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1382,8 +1382,7 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar) ED_region_pixelspace(ar); /* local coordinate visible rect inside region, to accommodate overlapping ui */ - rcti rect; - ED_region_visible_rect(ar, &rect); + const rcti *rect = ED_region_visible_rect(ar); view3d_draw_border(C, ar); view3d_draw_grease_pencil(C); @@ -1399,14 +1398,14 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar) /* The gizmo handles it's own drawing. */ break; case USER_MINI_AXIS_TYPE_MINIMAL: - draw_view_axis(rv3d, &rect); + draw_view_axis(rv3d, rect); case USER_MINI_AXIS_TYPE_NONE: break; } } - int xoffset = rect.xmin + U.widget_unit; - int yoffset = rect.ymax; + int xoffset = rect->xmin + U.widget_unit; + int yoffset = rect->ymax; if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 040b257bb90..02ad481e6ce 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -185,7 +185,8 @@ static void validate_object_select_id( } if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { - DRW_draw_select_id_object(depsgraph, view_layer, ar, v3d, obact, -1); + Base *base = BKE_view_layer_base_find(view_layer, obact); + DRW_select_buffer_context_create(&base, 1, -1); } /* TODO: Create a flag in `DRW_manager` because the drawing is no longer diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index ec7c1c0b3b9..9a9fe81a13e 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -517,9 +517,6 @@ static void viewops_data_create(bContext *C, static void viewops_data_free(bContext *C, wmOperator *op) { ARegion *ar; -#if 0 - Paint *p = BKE_paint_get_active_from_context(C); -#endif if (op->customdata) { ViewOpsData *vod = op->customdata; ar = vod->ar; @@ -536,12 +533,9 @@ static void viewops_data_free(bContext *C, wmOperator *op) ar = CTX_wm_region(C); } -#if 0 - if (p && (p->flags & PAINT_FAST_NAVIGATE)) -#endif - { - ED_region_tag_redraw(ar); - } + /* Need to redraw because drawing code uses RV3D_NAVIGATING to draw + * faster while navigation operator runs. */ + ED_region_tag_redraw(ar); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c index ad1a57eb71f..3c911e266a9 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c @@ -246,18 +246,17 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]); } - rcti rect_visible; - ED_region_visible_rect(ar, &rect_visible); + const rcti *rect_visible = ED_region_visible_rect(ar); - if ((navgroup->state.rect_visible.xmax == rect_visible.xmax) && - (navgroup->state.rect_visible.ymax == rect_visible.ymax) && + if ((navgroup->state.rect_visible.xmax == rect_visible->xmax) && + (navgroup->state.rect_visible.ymax == rect_visible->ymax) && (navgroup->state.rv3d.is_persp == rv3d->is_persp) && (navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) && (navgroup->state.rv3d.viewlock == rv3d->viewlock)) { return; } - navgroup->state.rect_visible = rect_visible; + navgroup->state.rect_visible = *rect_visible; navgroup->state.rv3d.is_persp = rv3d->is_persp; navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB); navgroup->state.rv3d.viewlock = rv3d->viewlock; @@ -268,8 +267,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC; const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC; const float co_rotate[2] = { - rect_visible.xmax - icon_offset, - rect_visible.ymax - icon_offset, + rect_visible->xmax - icon_offset, + rect_visible->ymax - icon_offset, }; float icon_offset_from_axis = 0.0f; @@ -286,8 +285,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g } const float co[2] = { - rect_visible.xmax - icon_offset_from_axis, - rect_visible.ymax - icon_offset_mini * 0.75f, + rect_visible->xmax - icon_offset_from_axis, + rect_visible->ymax - icon_offset_mini * 0.75f, }; wmGizmo *gz; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index bb2d3654d4a..37ea10773bf 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -198,43 +198,31 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) * \{ */ struct EditSelectBuf_Cache { - Base **bases; - uint bases_len; BLI_bitmap *select_bitmap; }; -static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, - ViewContext *vc, - short select_mode) +static void editselect_buf_cache_init(ViewContext *vc, short select_mode) { if (vc->obedit) { - esel->bases = BKE_view_layer_array_from_bases_in_edit_mode( - vc->view_layer, vc->v3d, &esel->bases_len); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc->view_layer, vc->v3d, &bases_len); + + DRW_select_buffer_context_create(bases, bases_len, select_mode); + MEM_freeN(bases); } else { /* Use for paint modes, currently only a single object at a time. */ if (vc->obact) { - esel->bases = MEM_mallocN(sizeof(esel->bases), __func__); - esel->bases[0] = BKE_view_layer_base_find(vc->view_layer, vc->obact); - esel->bases_len = 1; - } - else { - esel->bases = NULL; - esel->bases_len = 0; + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + DRW_select_buffer_context_create(&base, 1, select_mode); } } - - DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, esel->bases, esel->bases_len, select_mode); - - for (int i = 0; i < esel->bases_len; i++) { - esel->bases[i]->object->runtime.select_id = i; - } } static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel) { MEM_SAFE_FREE(esel->select_bitmap); - MEM_SAFE_FREE(esel->bases); } static void editselect_buf_cache_free_voidp(void *esel_voidp) @@ -251,7 +239,7 @@ static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *w wm_userdata->data = esel; wm_userdata->free_fn = editselect_buf_cache_free_voidp; wm_userdata->use_free = true; - editselect_buf_cache_init(esel, vc, select_mode); + editselect_buf_cache_init(vc, select_mode); } /** \} */ @@ -261,6 +249,7 @@ static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *w * \{ */ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel, + Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) @@ -270,9 +259,12 @@ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = DRW_select_buffer_context_offset_for_object_elem(ob->runtime.select_id, - SCE_SELECT_VERTEX); + uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_VERTEX); + if (index == 0) { + return false; + } + index -= 1; BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); @@ -289,6 +281,7 @@ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel } static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel, + Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) @@ -298,9 +291,12 @@ static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = DRW_select_buffer_context_offset_for_object_elem(ob->runtime.select_id, - SCE_SELECT_EDGE); + uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); + if (index == 0) { + return false; + } + index -= 1; BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); @@ -317,6 +313,7 @@ static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel } static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel, + Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) @@ -326,9 +323,12 @@ static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = DRW_select_buffer_context_offset_for_object_elem(ob->runtime.select_id, - SCE_SELECT_FACE); + uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_FACE); + if (index == 0) { + return false; + } + index -= 1; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); @@ -738,10 +738,12 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, { struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; LassoSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && @@ -762,10 +764,12 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, { struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; LassoSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords, data->moves, @@ -832,13 +836,15 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(mcords, moves, &rect); + esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( + vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL); } } if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_verts( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -851,7 +857,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, .data = &data, .esel = use_zbuf ? esel : NULL, .backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( - vc->obedit->runtime.select_id, SCE_SELECT_EDGE) : + vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : 0, }; @@ -867,7 +873,8 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_faces( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -1142,7 +1149,8 @@ static bool do_lasso_select_paintvert(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(mcords, moves, &rect); + esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( + vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL); } } @@ -1200,7 +1208,8 @@ static bool do_lasso_select_paintface(ViewContext *vc, if (esel == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(mcords, moves, &rect); + esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( + vc->depsgraph, vc->ar, vc->v3d, mcords, moves, &rect, NULL); } if (esel->select_bitmap) { @@ -2579,7 +2588,8 @@ static bool do_paintvert_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(rect, NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->ar, vc->v3d, rect, NULL); } if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); @@ -2633,7 +2643,8 @@ static bool do_paintface_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(rect, NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->ar, vc->v3d, rect, NULL); } if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); @@ -2756,10 +2767,12 @@ static void do_mesh_box_select__doSelectEdge_pass0( { struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; BoxSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); @@ -2775,10 +2788,12 @@ static void do_mesh_box_select__doSelectEdge_pass1( { struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; BoxSelectUserData *data = data_for_edge->data; - const bool is_visible = (data_for_edge->esel ? - BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, - data_for_edge->backbuf_offset + index) : - true); + bool is_visible = true; + if (data_for_edge->backbuf_offset) { + uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; + is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); + } + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -2830,13 +2845,15 @@ static bool do_mesh_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_rect(rect, NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->ar, vc->v3d, rect, NULL); } } if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_verts( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -2849,7 +2866,7 @@ static bool do_mesh_box_select(ViewContext *vc, .data = &data, .esel = use_zbuf ? esel : NULL, .backbuf_offset = use_zbuf ? DRW_select_buffer_context_offset_for_object_elem( - vc->obedit->runtime.select_id, SCE_SELECT_EDGE) : + vc->depsgraph, vc->obedit, SCE_SELECT_EDGE) : 0, }; @@ -2865,7 +2882,8 @@ static bool do_mesh_box_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_faces( + esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -3425,7 +3443,8 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap == NULL) { - esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(mval, (int)(rad + 1.0f), NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( + vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL); } } @@ -3433,7 +3452,7 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_verts( - esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { @@ -3445,7 +3464,7 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_edges( - esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { @@ -3458,7 +3477,7 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_faces( - esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { @@ -3496,7 +3515,8 @@ static bool paint_facesel_circle_select(ViewContext *vc, { struct EditSelectBuf_Cache *esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(mval, (int)(rad + 1.0f), NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( + vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL); if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); MEM_freeN(esel->select_bitmap); @@ -3550,7 +3570,8 @@ static bool paint_vertsel_circle_select(ViewContext *vc, if (use_zbuf) { struct EditSelectBuf_Cache *esel = wm_userdata->data; - esel->select_bitmap = DRW_select_buffer_bitmap_from_circle(mval, (int)(rad + 1.0f), NULL); + esel->select_bitmap = DRW_select_buffer_bitmap_from_circle( + vc->depsgraph, vc->ar, vc->v3d, mval, (int)(rad + 1.0f), NULL); if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); MEM_freeN(esel->select_bitmap); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 98203a7e316..14995144c5c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2009,19 +2009,18 @@ static void drawTransformView(const struct bContext *C, ARegion *ar, void *arg) * to warn that autokeying is enabled */ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) { - rcti rect; const char *printable = IFACE_("Auto Keying On"); float printable_size[2]; int xco, yco; - ED_region_visible_rect(ar, &rect); + const rcti *rect = ED_region_visible_rect(ar); const int font_id = BLF_default(); BLF_width_and_height( font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; - yco = (rect.ymax - U.widget_unit); + xco = (rect->xmax - U.widget_unit) - (int)printable_size[0]; + yco = (rect->ymax - U.widget_unit); /* warning text (to clarify meaning of overlays) * - original color was red to match the icon, but that clashes badly with a less nasty border diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index d45a0588003..dbcc6c1b04a 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -1150,12 +1150,19 @@ static void TargetSnapMedian(TransInfo *t) add_v3_v3(v, td->center); } + if (i == 0) { + /* Is this possible? */ + continue; + } + + mul_v3_fl(v, 1.0 / i); + if (tc->use_local_mat) { mul_m4_v3(tc->mat, v); } add_v3_v3(t->tsnap.snapTarget, v); - i_accum += i; + i_accum++; } mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum); diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index c65ca5d905e..175033f70d9 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -40,7 +40,7 @@ typedef enum { GPU_BATCH_READY_TO_DRAW, } GPUBatchPhase; -#define GPU_BATCH_VBO_MAX_LEN 5 +#define GPU_BATCH_VBO_MAX_LEN 6 #define GPU_BATCH_VAO_STATIC_LEN 3 #define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16 diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 124f1f1ff8a..f4a94c7759a 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -396,7 +396,9 @@ void GPU_shader_free_builtin_shaders(void); /* Vertex attributes for shaders */ -#define GPU_MAX_ATTR 32 +/* Hardware limit is 16. Position attribute is always needed so we reduce to 15. + * This makes sure the GPUVertexFormat name buffer does not overflow. */ +#define GPU_MAX_ATTR 15 typedef struct GPUVertAttrLayers { struct { diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h index dc60c52122c..8c22e3e1104 100644 --- a/source/blender/gpu/GPU_vertex_format.h +++ b/source/blender/gpu/GPU_vertex_format.h @@ -32,8 +32,10 @@ #define GPU_VERT_ATTR_MAX_LEN 16 #define GPU_VERT_ATTR_MAX_NAMES 6 -#define GPU_VERT_ATTR_NAME_AVERAGE_LEN 11 -#define GPU_VERT_ATTR_NAMES_BUF_LEN ((GPU_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GPU_VERT_ATTR_MAX_LEN) +#define GPU_VERT_ATTR_NAMES_BUF_LEN 256 +#define GPU_VERT_FORMAT_MAX_NAMES 63 /* More than enough, actual max is ~30. */ +/* Computed as GPU_VERT_ATTR_NAMES_BUF_LEN / 30 (actual max format name). */ +#define GPU_MAX_SAFE_ATTRIB_NAME 12 typedef enum { GPU_COMP_I8, @@ -80,8 +82,8 @@ BLI_STATIC_ASSERT(GPU_VERT_ATTR_NAMES_BUF_LEN <= 256, typedef struct GPUVertFormat { /** 0 to 16 (GPU_VERT_ATTR_MAX_LEN). */ uint attr_len : 5; - /** Total count of active vertex attribute. */ - uint name_len : 5; + /** Total count of active vertex attribute names. (max GPU_VERT_FORMAT_MAX_NAMES) */ + uint name_len : 6; /** Stride in bytes, 1 to 1024. */ uint stride : 11; /** Has the format been packed. */ @@ -117,6 +119,8 @@ BLI_INLINE const char *GPU_vertformat_attr_name_get(const GPUVertFormat *format, return format->names + attr->names[n_idx]; } +void GPU_vertformat_safe_attrib_name(const char *attrib_name, char *r_safe_name, uint max_len); + /* format conversion */ typedef struct GPUPackedNormal { @@ -164,9 +168,9 @@ BLI_INLINE int gpu_convert_i16_to_i10(short x) BLI_INLINE GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3]) { GPUPackedNormal n = { - .x = gpu_convert_normalized_f32_to_i10(data[0]), - .y = gpu_convert_normalized_f32_to_i10(data[1]), - .z = gpu_convert_normalized_f32_to_i10(data[2]), + gpu_convert_normalized_f32_to_i10(data[0]), + gpu_convert_normalized_f32_to_i10(data[1]), + gpu_convert_normalized_f32_to_i10(data[2]), }; return n; } @@ -174,9 +178,9 @@ BLI_INLINE GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3]) BLI_INLINE GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3]) { GPUPackedNormal n = { - .x = gpu_convert_i16_to_i10(data[0]), - .y = gpu_convert_i16_to_i10(data[1]), - .z = gpu_convert_i16_to_i10(data[2]), + gpu_convert_i16_to_i10(data[0]), + gpu_convert_i16_to_i10(data[1]), + gpu_convert_i16_to_i10(data[2]), }; return n; } diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 3e635b3198a..0e15fdd000b 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -46,6 +46,7 @@ #include "GPU_shader.h" #include "GPU_texture.h" #include "GPU_uniformbuffer.h" +#include "GPU_vertex_format.h" #include "BLI_sys_types.h" /* for intptr_t support */ @@ -1011,19 +1012,24 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u ds, "#define att%d %s\n", input->attr_id, attr_prefix_get(input->attr_type)); } else { - uint hash = BLI_ghashutil_strhash_p(input->attr_name); + char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME]; + GPU_vertformat_safe_attrib_name( + input->attr_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); BLI_dynstr_appendf(ds, - "DEFINE_ATTR(%s, %s%u);\n", + "DEFINE_ATTR(%s, %s%s);\n", GPU_DATATYPE_STR[input->type], attr_prefix_get(input->attr_type), - hash); - BLI_dynstr_appendf( - ds, "#define att%d %s%u\n", input->attr_id, attr_prefix_get(input->attr_type), hash); + attr_safe_name); + BLI_dynstr_appendf(ds, + "#define att%d %s%s\n", + input->attr_id, + attr_prefix_get(input->attr_type), + attr_safe_name); /* Auto attribute can be vertex color byte buffer. * We need to know and convert them to linear space in VS. */ if (input->attr_type == CD_AUTO_FROM_NAME) { - BLI_dynstr_appendf(ds, "uniform bool ba%u;\n", hash); - BLI_dynstr_appendf(ds, "#define att%d_is_srgb ba%u\n", input->attr_id, hash); + BLI_dynstr_appendf(ds, "uniform bool ba%s;\n", attr_safe_name); + BLI_dynstr_appendf(ds, "#define att%d_is_srgb ba%s\n", input->attr_id, attr_safe_name); } } BLI_dynstr_appendf(ds, diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c index f672d350afa..11df86c0b3a 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.c +++ b/source/blender/gpu/intern/gpu_vertex_format.c @@ -31,6 +31,8 @@ #include <string.h> #include "BLI_utildefines.h" +#include "BLI_string.h" +#include "BLI_ghash.h" #define PACK_DEBUG 0 @@ -149,9 +151,9 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format, GPUVertFetchMode fetch_mode) { #if TRUST_NO_ONE - assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ - assert(format->attr_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ - assert(!format->packed); /* packed means frozen/locked */ + assert(format->name_len < GPU_VERT_FORMAT_MAX_NAMES); /* there's room for more */ + assert(format->attr_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ + assert(!format->packed); /* packed means frozen/locked */ assert((comp_len >= 1 && comp_len <= 4) || comp_len == 8 || comp_len == 12 || comp_len == 16); switch (comp_type) { @@ -197,7 +199,7 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias) { GPUVertAttr *attr = &format->attrs[format->attr_len - 1]; #if TRUST_NO_ONE - assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ + assert(format->name_len < GPU_VERT_FORMAT_MAX_NAMES); /* there's room for more */ assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); #endif format->name_len++; /* multiname support */ @@ -218,6 +220,56 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name) return -1; } +/* Encode 8 original bytes into 11 safe bytes. */ +static void safe_bytes(char out[11], const char data[8]) +{ + char safe_chars[63] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; + + uint64_t in = *(uint64_t *)data; + for (int i = 0; i < 11; i++) { + /* Encoding in base63 */ + out[i] = safe_chars[in % 63lu]; + in /= 63lu; + } +} + +/* Warning: Always add a prefix to the result of this function as + * the generated string can start with a number and not be a valid attribute name. */ +void GPU_vertformat_safe_attrib_name(const char *attrib_name, + char *r_safe_name, + uint UNUSED(max_len)) +{ + char data[8] = {0}; + uint len = strlen(attrib_name); + + if (len > 8) { + /* Start with the first 4 chars of the name; */ + for (int i = 0; i < 4; i++) { + data[i] = attrib_name[i]; + } + /* We use a hash to identify each data layer based on its name. + * NOTE: This is still prone to hash collision but the risks are very low.*/ + /* Start hashing after the first 2 chars. */ + *(uint *)&data[4] = BLI_ghashutil_strhash_p_murmur(attrib_name + 4); + } + else { + /* Copy the whole name. Collision is barelly possible + * (hash would have to be equal to the last 4 bytes). */ + for (int i = 0; i < 8 && attrib_name[i] != '\0'; i++) { + data[i] = attrib_name[i]; + } + } + /* Convert to safe bytes characters. */ + safe_bytes(r_safe_name, data); + /* End the string */ + r_safe_name[11] = '\0'; + + BLI_assert(GPU_MAX_SAFE_ATTRIB_NAME >= 12); +#if 0 /* For debugging */ + printf("%s > %lx > %s\n", attrib_name, *(uint64_t *)data, r_safe_name); +#endif +} + /* Make attribute layout non-interleaved. * Warning! This does not change data layout! * Use direct buffer access to fill the data. diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 04a42cb146c..3ad857ac7b7 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1012,6 +1012,11 @@ typedef struct NodeCryptomatte { char _pad[4]; } NodeCryptomatte; +typedef struct NodeDenoise { + char hdr; + char _pad[7]; +} NodeDenoise; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 0319993631c..aab71c15e44 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -375,6 +375,13 @@ typedef struct ScrArea { typedef struct ARegion_Runtime { /* Panel category to use between 'layout' and 'draw'. */ const char *category; + + /** + * The visible part of the region, use with region overlap not to draw + * on top of the overlapping regions. + * + * Lazy initialize, zero'd when unset, relative to #ARegion.winrct x/y min. */ + rcti visible_rect; } ARegion_Runtime; typedef struct ARegion { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 347be6b8a72..c9815a6cc37 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -7600,6 +7600,18 @@ static void def_cmp_cryptomatte(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeCryptomatte_update_remove"); } +static void def_cmp_denoise(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeDenoise", "storage"); + + prop = RNA_def_property(srna, "use_hdr", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "hdr", 0); + RNA_def_property_ui_text(prop, "HDR", "Process HDR images"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + /* -- Texture Nodes --------------------------------------------------------- */ static void def_tex_output(StructRNA *srna) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index e8d5b2c6a39..284eaa8b70b 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC composite/nodes/node_composite_cryptomatte.c composite/nodes/node_composite_curves.c composite/nodes/node_composite_defocus.c + composite/nodes/node_composite_denoise.c composite/nodes/node_composite_despeckle.c composite/nodes/node_composite_diffMatte.c composite/nodes/node_composite_dilate.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index e6d9ed6f70e..534e9012693 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -74,6 +74,7 @@ void register_node_type_cmp_dilateerode(void); void register_node_type_cmp_inpaint(void); void register_node_type_cmp_despeckle(void); void register_node_type_cmp_defocus(void); +void register_node_type_cmp_denoise(void); void register_node_type_cmp_valtorgb(void); void register_node_type_cmp_rgbtobw(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 796ad9e5d5b..c72e97642a2 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -216,6 +216,7 @@ DefNode(CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLAN DefNode(CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" ) DefNode(CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" ) DefNode(CompositorNode, CMP_NODE_CRYPTOMATTE, def_cmp_cryptomatte, "CRYPTOMATTE", Cryptomatte, "Cryptomatte", "" ) +DefNode(CompositorNode, CMP_NODE_DENOISE, def_cmp_denoise, "DENOISE", Denoise, "Denoise", "" ) DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_denoise.c b/source/blender/nodes/composite/nodes/node_composite_denoise.c new file mode 100644 index 00000000000..e2fdb08816a --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_denoise.c @@ -0,0 +1,58 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Stefan Werner + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_denoise.c + * \ingroup cmpnodes + */ + +#include "node_composite_util.h" + +static bNodeSocketTemplate cmp_node_denoise_in[] = { + {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, + {SOCK_RGBA, 1, N_("Albedo"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, + {SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, + {-1, 0, ""}}; +static bNodeSocketTemplate cmp_node_denoise_out[] = {{SOCK_RGBA, 0, N_("Image")}, {-1, 0, ""}}; + +static void node_composit_init_denonise(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeDenoise *ndg = MEM_callocN(sizeof(NodeDenoise), "node denoise data"); + ndg->hdr = true; + node->storage = ndg; +} + +void register_node_type_cmp_denoise(void) +{ + static bNodeType ntype; + + cmp_node_type_base(&ntype, CMP_NODE_DENOISE, "Denoise", NODE_CLASS_OP_FILTER, 0); + node_type_socket_templates(&ntype, cmp_node_denoise_in, cmp_node_denoise_out); + node_type_init(&ntype, node_composit_init_denonise); + node_type_storage(&ntype, "NodeDenoise", node_free_standard_storage, node_copy_standard_storage); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c index 6795f48edb3..478b9524737 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tangent.c +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -42,7 +42,8 @@ static int node_shader_gpu_tangent(GPUMaterial *mat, NodeShaderTangent *attr = node->storage; if (attr->direction_type == SHD_TANGENT_UVMAP) { - return GPU_stack_link(mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, "")); + return GPU_stack_link( + mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, attr->uv_map)); } else { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); diff --git a/source/creator/creator.c b/source/creator/creator.c index d6e1d7e7f5f..9eb1578001c 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -442,7 +442,7 @@ int main(int argc, "this is not intended for typical usage\n\n"); #endif - CTX_py_init_set(C, 1); + CTX_py_init_set(C, true); WM_keyconfig_init(C); #ifdef WITH_FREESTYLE diff --git a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc index 220c0a4100d..ce84baf802a 100644 --- a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc +++ b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc @@ -616,6 +616,33 @@ TEST(delaunay, OverlapFaces) BLI_delaunay_2d_cdt_free(out); } +TEST(delaunay, TwoSquaresOverlap) +{ + CDT_input in; + CDT_result *out; + float p[][2] = { + {1.0f, -1.0f}, + {-1.0f, -1.0f}, + {-1.0f, 1.0f}, + {1.0f, 1.0f}, + {-1.5f, 1.5f}, + {0.5f, 1.5f}, + {0.5f, -0.5f}, + {-1.5f, -0.5f}, + }; + int f[] = {/* 0 */ 7, 6, 5, 4, /* 1 */ 3, 2, 1, 0}; + int fstart[] = {0, 4}; + int flen[] = {4, 4}; + + fill_input_verts(&in, p, 8); + add_input_faces(&in, f, fstart, flen, 2); + out = BLI_delaunay_2d_cdt_calc(&in, CDT_CONSTRAINTS_VALID_BMESH); + EXPECT_EQ(out->verts_len, 10); + EXPECT_EQ(out->edges_len, 12); + EXPECT_EQ(out->faces_len, 3); + BLI_delaunay_2d_cdt_free(out); +} + enum { RANDOM_PTS, RANDOM_SEGS, @@ -623,7 +650,10 @@ enum { }; // #define DO_TIMING -static void rand_delaunay_test(int test_kind, int max_lg_size, int reps_per_size) +static void rand_delaunay_test(int test_kind, + int max_lg_size, + int reps_per_size, + CDT_output_type otype) { CDT_input in; CDT_result *out; @@ -679,7 +709,7 @@ static void rand_delaunay_test(int test_kind, int max_lg_size, int reps_per_size add_input_edges(&in, e, size - 1 + (test_kind == RANDOM_POLY)); } tstart = PIL_check_seconds_timer(); - out = BLI_delaunay_2d_cdt_calc(&in, CDT_FULL); + out = BLI_delaunay_2d_cdt_calc(&in, otype); EXPECT_NE(out->verts_len, 0); BLI_delaunay_2d_cdt_free(out); times[lg_size] += PIL_check_seconds_timer() - tstart; @@ -700,17 +730,32 @@ static void rand_delaunay_test(int test_kind, int max_lg_size, int reps_per_size TEST(delaunay, randompts) { - rand_delaunay_test(RANDOM_PTS, 7, 1); + rand_delaunay_test(RANDOM_PTS, 7, 1, CDT_FULL); } TEST(delaunay, randomsegs) { - rand_delaunay_test(RANDOM_SEGS, 7, 1); + rand_delaunay_test(RANDOM_SEGS, 7, 1, CDT_FULL); } TEST(delaunay, randompoly) { - rand_delaunay_test(RANDOM_POLY, 7, 1); + rand_delaunay_test(RANDOM_POLY, 7, 1, CDT_FULL); +} + +TEST(delaunay, randompoly_inside) +{ + rand_delaunay_test(RANDOM_POLY, 7, 1, CDT_INSIDE); +} + +TEST(delaunay, randompoly_constraints) +{ + rand_delaunay_test(RANDOM_POLY, 7, 1, CDT_CONSTRAINTS); +} + +TEST(delaunay, randompoly_validbmesh) +{ + rand_delaunay_test(RANDOM_POLY, 7, 1, CDT_CONSTRAINTS_VALID_BMESH); } #if 0 |