UI: Region polling support #105088

Merged
Julian Eisel merged 39 commits from JulianEisel/blender:temp-region-poll into main 2023-04-05 15:30:46 +02:00
51 changed files with 693 additions and 1111 deletions
Showing only changes of commit 2c2515d465 - Show all commits

View File

@ -53,7 +53,18 @@ This package provides Blender as a Python module for use in studio pipelines, we
[System requirements](https://www.blender.org/download/requirements/) are the same as Blender.
Each Blender release supports one Python version, and the package is only compatible with that version."""
Each Blender release supports one Python version, and the package is only compatible with that version.
## Source Code
* [Releases](https://download.blender.org/source/)
* Repository: [git.blender.org/blender.git](https://git.blender.org/gitweb/gitweb.cgi/blender.git)
## Credits
Created by the [Blender developer community](https://www.blender.org/about/credits/).
Thanks to Tyler Alden Gubala for maintaining the original version of this package."""
# ------------------------------------------------------------------------------
# Generic Functions

View File

@ -1085,11 +1085,11 @@ static void create_subd_mesh(Scene *scene,
const int edges_num = b_mesh.edges.length();
if (edges_num != 0 && b_mesh.edge_creases.length() > 0) {
size_t num_creases = 0;
const float *creases = static_cast<float *>(b_mesh.edge_creases[0].ptr.data);
BL::MeshEdgeCreaseLayer creases = b_mesh.edge_creases[0];
size_t num_creases = 0;
for (int i = 0; i < edges_num; i++) {
if (creases[i] != 0.0f) {
if (creases.data[i].value() != 0.0f) {
num_creases++;
}
}
@ -1098,17 +1098,18 @@ static void create_subd_mesh(Scene *scene,
const MEdge *edges = static_cast<MEdge *>(b_mesh.edges[0].ptr.data);
for (int i = 0; i < edges_num; i++) {
if (creases[i] != 0.0f) {
const float crease = creases.data[i].value();
if (crease != 0.0f) {
const MEdge &b_edge = edges[i];
mesh->add_edge_crease(b_edge.v1, b_edge.v2, creases[i]);
mesh->add_edge_crease(b_edge.v1, b_edge.v2, crease);
}
}
}
for (BL::MeshVertexCreaseLayer &c : b_mesh.vertex_creases) {
for (int i = 0; i < c.data.length(); ++i) {
if (c.data[i].value() != 0.0f) {
mesh->add_vertex_crease(i, c.data[i].value());
}
for (BL::MeshVertexCreaseLayer &c : b_mesh.vertex_creases) {
for (int i = 0; i < c.data.length(); ++i) {
if (c.data[i].value() != 0.0f) {
mesh->add_vertex_crease(i, c.data[i].value());
}
}
}

View File

@ -1,584 +1,6 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
###########################################################################
# Helper macros
###########################################################################
macro(_set_default variable value)
if(NOT ${variable})
set(${variable} ${value})
endif()
endmacro()
###########################################################################
# Precompiled libraries detection
#
# Use precompiled libraries from Blender repository
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(APPLE)
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")
set(_cycles_lib_dir "${CMAKE_SOURCE_DIR}/../lib/darwin")
else()
set(_cycles_lib_dir "${CMAKE_SOURCE_DIR}/../lib/darwin_arm64")
endif()
# Always use system zlib
find_package(ZLIB REQUIRED)
elseif(WIN32)
if(CMAKE_CL_64)
set(_cycles_lib_dir "${CMAKE_SOURCE_DIR}/../lib/win64_vc15")
else()
message(FATAL_ERROR "Unsupported Visual Studio Version")
endif()
else()
# Path to a locally compiled libraries.
set(LIBDIR_NAME ${CMAKE_SYSTEM_NAME}_${CMAKE_SYSTEM_PROCESSOR})
string(TOLOWER ${LIBDIR_NAME} LIBDIR_NAME)
set(LIBDIR_NATIVE_ABI ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME})
# Path to precompiled libraries with known CentOS 7 ABI.
set(LIBDIR_CENTOS7_ABI ${CMAKE_SOURCE_DIR}/../lib/linux_centos7_x86_64)
# Choose the best suitable libraries.
if(EXISTS ${LIBDIR_NATIVE_ABI})
set(_cycles_lib_dir ${LIBDIR_NATIVE_ABI})
elseif(EXISTS ${LIBDIR_CENTOS7_ABI})
set(_cycles_lib_dir ${LIBDIR_CENTOS7_ABI})
set(WITH_CXX11_ABI OFF)
if(CMAKE_COMPILER_IS_GNUCC AND
CMAKE_C_COMPILER_VERSION VERSION_LESS 9.3)
message(FATAL_ERROR "GCC version must be at least 9.3 for precompiled libraries, found ${CMAKE_C_COMPILER_VERSION}")
endif()
endif()
if(DEFINED _cycles_lib_dir)
message(STATUS "Using precompiled libraries at ${_cycles_lib_dir}")
endif()
# Avoid namespace pollustion.
unset(LIBDIR_NATIVE_ABI)
unset(LIBDIR_CENTOS7_ABI)
endif()
if(EXISTS ${_cycles_lib_dir})
_set_default(ALEMBIC_ROOT_DIR "${_cycles_lib_dir}/alembic")
_set_default(BOOST_ROOT "${_cycles_lib_dir}/boost")
_set_default(BLOSC_ROOT_DIR "${_cycles_lib_dir}/blosc")
_set_default(EMBREE_ROOT_DIR "${_cycles_lib_dir}/embree")
_set_default(EPOXY_ROOT_DIR "${_cycles_lib_dir}/epoxy")
_set_default(IMATH_ROOT_DIR "${_cycles_lib_dir}/imath")
_set_default(GLEW_ROOT_DIR "${_cycles_lib_dir}/glew")
_set_default(JPEG_ROOT "${_cycles_lib_dir}/jpeg")
_set_default(LLVM_ROOT_DIR "${_cycles_lib_dir}/llvm")
_set_default(CLANG_ROOT_DIR "${_cycles_lib_dir}/llvm")
_set_default(NANOVDB_ROOT_DIR "${_cycles_lib_dir}/openvdb")
_set_default(OPENCOLORIO_ROOT_DIR "${_cycles_lib_dir}/opencolorio")
_set_default(OPENEXR_ROOT_DIR "${_cycles_lib_dir}/openexr")
_set_default(OPENIMAGEDENOISE_ROOT_DIR "${_cycles_lib_dir}/openimagedenoise")
_set_default(OPENIMAGEIO_ROOT_DIR "${_cycles_lib_dir}/openimageio")
_set_default(OPENJPEG_ROOT_DIR "${_cycles_lib_dir}/openjpeg")
_set_default(OPENSUBDIV_ROOT_DIR "${_cycles_lib_dir}/opensubdiv")
_set_default(OPENVDB_ROOT_DIR "${_cycles_lib_dir}/openvdb")
_set_default(OSL_ROOT_DIR "${_cycles_lib_dir}/osl")
_set_default(PNG_ROOT "${_cycles_lib_dir}/png")
_set_default(PUGIXML_ROOT_DIR "${_cycles_lib_dir}/pugixml")
_set_default(SDL2_ROOT_DIR "${_cycles_lib_dir}/sdl")
_set_default(TBB_ROOT_DIR "${_cycles_lib_dir}/tbb")
_set_default(TIFF_ROOT "${_cycles_lib_dir}/tiff")
_set_default(USD_ROOT_DIR "${_cycles_lib_dir}/usd")
_set_default(WEBP_ROOT_DIR "${_cycles_lib_dir}/webp")
_set_default(ZLIB_ROOT "${_cycles_lib_dir}/zlib")
if(WIN32)
set(LEVEL_ZERO_ROOT_DIR ${_cycles_lib_dir}/level_zero)
else()
set(LEVEL_ZERO_ROOT_DIR ${_cycles_lib_dir}/level-zero)
endif()
_set_default(SYCL_ROOT_DIR "${_cycles_lib_dir}/dpcpp")
# Ignore system libraries
set(CMAKE_IGNORE_PATH "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES};${CMAKE_SYSTEM_INCLUDE_PATH};${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES};${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}")
else()
unset(_cycles_lib_dir)
endif()
endif()
###########################################################################
# Zlib
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(ZLIB_INCLUDE_DIRS ${_cycles_lib_dir}/zlib/include)
set(ZLIB_LIBRARIES ${_cycles_lib_dir}/zlib/lib/libz_st.lib)
set(ZLIB_INCLUDE_DIR ${_cycles_lib_dir}/zlib/include)
set(ZLIB_LIBRARY ${_cycles_lib_dir}/zlib/lib/libz_st.lib)
set(ZLIB_DIR ${_cycles_lib_dir}/zlib)
set(ZLIB_FOUND ON)
elseif(NOT APPLE)
find_package(ZLIB REQUIRED)
endif()
endif()
###########################################################################
# PThreads
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(PTHREADS_LIBRARIES "${_cycles_lib_dir}/pthreads/lib/pthreadVC3.lib")
include_directories("${_cycles_lib_dir}/pthreads/include")
else()
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif()
endif()
###########################################################################
# OpenImageIO and image libraries
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
add_definitions(
# OIIO changed the name of this define in newer versions
# we define both, so it would work with both old and new
# versions.
-DOIIO_STATIC_BUILD
-DOIIO_STATIC_DEFINE
)
set(OPENIMAGEIO_INCLUDE_DIR ${OPENIMAGEIO_ROOT_DIR}/include)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR} ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO)
# Special exceptions for libraries which needs explicit debug version
set(OPENIMAGEIO_LIBRARIES
optimized ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO.lib
optimized ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_Util.lib
debug ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_d.lib
debug ${OPENIMAGEIO_ROOT_DIR}/lib/OpenImageIO_Util_d.lib
)
set(PUGIXML_INCLUDE_DIR ${PUGIXML_ROOT_DIR}/include)
set(PUGIXML_LIBRARIES
optimized ${PUGIXML_ROOT_DIR}/lib/pugixml.lib
debug ${PUGIXML_ROOT_DIR}/lib/pugixml_d.lib
)
else()
find_package(OpenImageIO REQUIRED)
if(OPENIMAGEIO_PUGIXML_FOUND)
set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO")
set(PUGIXML_LIBRARIES "")
else()
find_package(PugiXML REQUIRED)
endif()
endif()
# Dependencies
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENJPEG_INCLUDE_DIR ${OPENJPEG}/include/openjpeg-2.3)
set(OPENJPEG_LIBRARIES ${_cycles_lib_dir}/openjpeg/lib/openjp2${CMAKE_STATIC_LIBRARY_SUFFIX})
else()
find_package(OpenJPEG REQUIRED)
endif()
find_package(JPEG REQUIRED)
find_package(TIFF REQUIRED)
find_package(WebP)
if(EXISTS ${_cycles_lib_dir})
set(PNG_NAMES png16 libpng16 png libpng)
endif()
find_package(PNG REQUIRED)
endif()
###########################################################################
# OpenEXR
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENEXR_INCLUDE_DIR ${OPENEXR_ROOT_DIR}/include)
set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_ROOT_DIR}/include/OpenEXR ${IMATH_ROOT_DIR}/include ${IMATH_ROOT_DIR}/include/Imath)
set(OPENEXR_LIBRARIES
optimized ${OPENEXR_ROOT_DIR}/lib/OpenEXR_s.lib
optimized ${OPENEXR_ROOT_DIR}/lib/OpenEXRCore_s.lib
optimized ${OPENEXR_ROOT_DIR}/lib/Iex_s.lib
optimized ${IMATH_ROOT_DIR}/lib/Imath_s.lib
optimized ${OPENEXR_ROOT_DIR}/lib/IlmThread_s.lib
debug ${OPENEXR_ROOT_DIR}/lib/OpenEXR_s_d.lib
debug ${OPENEXR_ROOT_DIR}/lib/OpenEXRCore_s_d.lib
debug ${OPENEXR_ROOT_DIR}/lib/Iex_s_d.lib
debug ${IMATH_ROOT_DIR}/lib/Imath_s_d.lib
debug ${OPENEXR_ROOT_DIR}/lib/IlmThread_s_d.lib
)
else()
find_package(OpenEXR REQUIRED)
endif()
endif()
###########################################################################
# OpenShadingLanguage & LLVM
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OSL)
if(EXISTS ${_cycles_lib_dir})
set(LLVM_STATIC ON)
endif()
if(MSVC AND EXISTS ${_cycles_lib_dir})
# TODO(sergey): On Windows llvm-config doesn't give proper results for the
# library names, use hardcoded libraries for now.
file(GLOB _llvm_libs_release ${LLVM_ROOT_DIR}/lib/*.lib)
file(GLOB _llvm_libs_debug ${LLVM_ROOT_DIR}/debug/lib/*.lib)
set(_llvm_libs)
foreach(_llvm_lib_path ${_llvm_libs_release})
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
list(APPEND _llvm_libs optimized ${_llvm_lib_name})
endforeach()
foreach(_llvm_lib_path ${_llvm_libs_debug})
get_filename_component(_llvm_lib_name ${_llvm_lib_path} ABSOLUTE)
list(APPEND _llvm_libs debug ${_llvm_lib_name})
endforeach()
set(LLVM_LIBRARY ${_llvm_libs})
unset(_llvm_lib_name)
unset(_llvm_lib_path)
unset(_llvm_libs)
unset(_llvm_libs_debug)
unset(_llvm_libs_release)
set(OSL_INCLUDE_DIR ${OSL_ROOT_DIR}/include)
set(OSL_LIBRARIES
optimized ${OSL_ROOT_DIR}/lib/oslcomp.lib
optimized ${OSL_ROOT_DIR}/lib/oslexec.lib
optimized ${OSL_ROOT_DIR}/lib/oslquery.lib
debug ${OSL_ROOT_DIR}/lib/oslcomp_d.lib
debug ${OSL_ROOT_DIR}/lib/oslexec_d.lib
debug ${OSL_ROOT_DIR}/lib/oslquery_d.lib
${PUGIXML_LIBRARIES}
)
find_program(OSL_COMPILER NAMES oslc PATHS ${OSL_ROOT_DIR}/bin)
else()
find_package(OSL REQUIRED)
find_package(LLVM REQUIRED)
find_package(Clang REQUIRED)
endif()
endif()
###########################################################################
# OpenPGL
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_PATH_GUIDING)
if(NOT openpgl_DIR AND EXISTS ${_cycles_lib_dir})
set(openpgl_DIR ${_cycles_lib_dir}/openpgl/lib/cmake/openpgl)
endif()
find_package(openpgl QUIET)
if(openpgl_FOUND)
if(WIN32)
get_target_property(OPENPGL_LIBRARIES_RELEASE openpgl::openpgl LOCATION_RELEASE)
get_target_property(OPENPGL_LIBRARIES_DEBUG openpgl::openpgl LOCATION_DEBUG)
set(OPENPGL_LIBRARIES optimized ${OPENPGL_LIBRARIES_RELEASE} debug ${OPENPGL_LIBRARIES_DEBUG})
else()
get_target_property(OPENPGL_LIBRARIES openpgl::openpgl LOCATION)
endif()
get_target_property(OPENPGL_INCLUDE_DIR openpgl::openpgl INTERFACE_INCLUDE_DIRECTORIES)
else()
set_and_warn_library_found("OpenPGL" openpgl_FOUND WITH_CYCLES_PATH_GUIDING)
endif()
endif()
###########################################################################
# OpenColorIO
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENCOLORIO)
set(WITH_OPENCOLORIO ON)
if(NOT USD_OVERRIDE_OPENCOLORIO)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO_ROOT_DIR}/include)
set(OPENCOLORIO_LIBRARIES
optimized ${OPENCOLORIO_ROOT_DIR}/lib/OpenColorIO.lib
optimized ${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp.lib
optimized ${OPENCOLORIO_ROOT_DIR}/lib/libexpatMD.lib
optimized ${OPENCOLORIO_ROOT_DIR}/lib/pystring.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/OpencolorIO_d.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/libyaml-cpp_d.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/libexpatdMD.lib
debug ${OPENCOLORIO_ROOT_DIR}/lib/pystring_d.lib
)
else()
find_package(OpenColorIO REQUIRED)
endif()
endif()
endif()
###########################################################################
# Boost
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(EXISTS ${_cycles_lib_dir})
if(MSVC)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_LIBS ON)
else()
set(BOOST_LIBRARYDIR ${_cycles_lib_dir}/boost/lib)
set(Boost_NO_BOOST_CMAKE ON)
set(Boost_NO_SYSTEM_PATHS ON)
endif()
endif()
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(BOOST_INCLUDE_DIR ${BOOST_ROOT}/include)
set(BOOST_VERSION_HEADER ${BOOST_INCLUDE_DIR}/boost/version.hpp)
if(EXISTS ${BOOST_VERSION_HEADER})
file(STRINGS "${BOOST_VERSION_HEADER}" BOOST_LIB_VERSION REGEX "#define BOOST_LIB_VERSION ")
if(BOOST_LIB_VERSION MATCHES "#define BOOST_LIB_VERSION \"([0-9_]+)\"")
set(BOOST_VERSION "${CMAKE_MATCH_1}")
endif()
endif()
if(NOT BOOST_VERSION)
message(FATAL_ERROR "Unable to determine Boost version")
endif()
set(BOOST_POSTFIX "vc142-mt-x64-${BOOST_VERSION}.lib")
set(BOOST_DEBUG_POSTFIX "vc142-mt-gd-x64-${BOOST_VERSION}.lib")
set(BOOST_LIBRARIES
optimized ${BOOST_ROOT}/lib/libboost_date_time-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_iostreams-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_filesystem-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_regex-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_system-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_thread-${BOOST_POSTFIX}
optimized ${BOOST_ROOT}/lib/libboost_chrono-${BOOST_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_date_time-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_iostreams-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_filesystem-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_regex-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_system-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_thread-${BOOST_DEBUG_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_chrono-${BOOST_DEBUG_POSTFIX}
)
if(WITH_CYCLES_OSL)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
optimized ${BOOST_ROOT}/lib/libboost_wave-${BOOST_POSTFIX}
debug ${BOOST_ROOT}/lib/libboost_wave-${BOOST_DEBUG_POSTFIX})
endif()
else()
set(__boost_packages iostreams filesystem regex system thread date_time)
if(WITH_CYCLES_OSL)
list(APPEND __boost_packages wave)
endif()
find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
if(NOT Boost_FOUND)
# Try to find non-multithreaded if -mt not found, this flag
# doesn't matter for us, it has nothing to do with thread
# safety, but keep it to not disturb build setups.
set(Boost_USE_MULTITHREADED OFF)
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
endif()
unset(__boost_packages)
set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
endif()
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB ${BOOST_DEFINITIONS}")
endif()
###########################################################################
# Embree
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_EMBREE)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(EMBREE_INCLUDE_DIRS ${EMBREE_ROOT_DIR}/include)
set(EMBREE_LIBRARIES
optimized ${EMBREE_ROOT_DIR}/lib/embree3.lib
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx2.lib
optimized ${EMBREE_ROOT_DIR}/lib/embree_avx.lib
optimized ${EMBREE_ROOT_DIR}/lib/embree_sse42.lib
optimized ${EMBREE_ROOT_DIR}/lib/lexers.lib
optimized ${EMBREE_ROOT_DIR}/lib/math.lib
optimized ${EMBREE_ROOT_DIR}/lib/simd.lib
optimized ${EMBREE_ROOT_DIR}/lib/tasking.lib
optimized ${EMBREE_ROOT_DIR}/lib/sys.lib
debug ${EMBREE_ROOT_DIR}/lib/embree3_d.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_avx2_d.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_avx_d.lib
debug ${EMBREE_ROOT_DIR}/lib/embree_sse42_d.lib
debug ${EMBREE_ROOT_DIR}/lib/lexers_d.lib
debug ${EMBREE_ROOT_DIR}/lib/math_d.lib
debug ${EMBREE_ROOT_DIR}/lib/simd_d.lib
debug ${EMBREE_ROOT_DIR}/lib/sys_d.lib
debug ${EMBREE_ROOT_DIR}/lib/tasking_d.lib
)
else()
find_package(Embree 3.8.0 REQUIRED)
endif()
endif()
###########################################################################
# Logging
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_LOGGING)
find_package(Glog REQUIRED)
find_package(Gflags REQUIRED)
endif()
###########################################################################
# OpenSubdiv
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENSUBDIV)
set(WITH_OPENSUBDIV ON)
if(NOT USD_OVERRIDE_OPENSUBDIV)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_ROOT_DIR}/include)
set(OPENSUBDIV_LIBRARIES
optimized ${OPENSUBDIV_ROOT_DIR}/lib/osdCPU.lib
optimized ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU.lib
debug ${OPENSUBDIV_ROOT_DIR}/lib/osdCPU_d.lib
debug ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU_d.lib
)
else()
find_package(OpenSubdiv REQUIRED)
endif()
endif()
endif()
###########################################################################
# OpenVDB
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENVDB)
set(WITH_OPENVDB ON)
set(OPENVDB_DEFINITIONS -DNOMINMAX -D_USE_MATH_DEFINES)
if(NOT USD_OVERRIDE_OPENVDB)
find_package(OpenVDB REQUIRED)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(BLOSC_LIBRARY
optimized ${BLOSC_ROOT_DIR}/lib/libblosc.lib
debug ${BLOSC_ROOT_DIR}/lib/libblosc_d.lib
)
else()
find_package(Blosc REQUIRED)
endif()
endif()
endif()
###########################################################################
# NanoVDB
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_NANOVDB)
set(WITH_NANOVDB ON)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(NANOVDB_INCLUDE_DIR ${NANOVDB_ROOT_DIR}/include)
set(NANOVDB_INCLUDE_DIRS ${NANOVDB_INCLUDE_DIR})
else()
find_package(NanoVDB REQUIRED)
endif()
endif()
###########################################################################
# OpenImageDenoise
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OPENIMAGEDENOISE)
set(WITH_OPENIMAGEDENOISE ON)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(OPENIMAGEDENOISE_INCLUDE_DIRS ${OPENIMAGEDENOISE_ROOT_DIR}/include)
set(OPENIMAGEDENOISE_LIBRARIES
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise.lib
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common.lib
optimized ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/OpenImageDenoise_d.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/common_d.lib
debug ${OPENIMAGEDENOISE_ROOT_DIR}/lib/dnnl_d.lib
)
else()
find_package(OpenImageDenoise REQUIRED)
endif()
endif()
###########################################################################
# TBB
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if(NOT USD_OVERRIDE_TBB)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(TBB_INCLUDE_DIRS ${TBB_ROOT_DIR}/include)
set(TBB_LIBRARIES
optimized ${TBB_ROOT_DIR}/lib/tbb.lib
debug ${TBB_ROOT_DIR}/lib/tbb_debug.lib
)
else()
find_package(TBB REQUIRED)
endif()
endif()
endif()
###########################################################################
# Epoxy
###########################################################################
if(CYCLES_STANDALONE_REPOSITORY)
if((WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) OR
WITH_CYCLES_HYDRA_RENDER_DELEGATE)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(Epoxy_LIBRARIES "${_cycles_lib_dir}/epoxy/lib/epoxy.lib")
set(Epoxy_INCLUDE_DIRS "${_cycles_lib_dir}/epoxy/include")
else()
find_package(Epoxy REQUIRED)
endif()
endif()
endif()
###########################################################################
# Alembic
###########################################################################
if(WITH_CYCLES_ALEMBIC)
if(CYCLES_STANDALONE_REPOSITORY)
if(MSVC AND EXISTS ${_cycles_lib_dir})
set(ALEMBIC_INCLUDE_DIRS ${_cycles_lib_dir}/alembic/include)
set(ALEMBIC_LIBRARIES
optimized ${_cycles_lib_dir}/alembic/lib/Alembic.lib
debug ${_cycles_lib_dir}/alembic/lib/Alembic_d.lib)
else()
find_package(Alembic REQUIRED)
endif()
set(WITH_ALEMBIC ON)
endif()
endif()
###########################################################################
# System Libraries
###########################################################################
# Detect system libraries again
if(EXISTS ${_cycles_lib_dir})
unset(CMAKE_IGNORE_PATH)
unset(_cycles_lib_dir)
endif()
###########################################################################
# SDL
###########################################################################
@ -687,5 +109,3 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
set(WITH_CYCLES_DEVICE_ONEAPI OFF)
endif()
endif()
unset(_cycles_lib_dir)

View File

@ -157,4 +157,47 @@ ccl_device_inline void film_write_data_passes(KernelGlobals kg,
#endif
}
ccl_device_inline void film_write_data_passes_background(
KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
{
#ifdef __PASSES__
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
if (!(path_flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
return;
}
/* Don't write data passes for paths that were split off for shadow catchers
* to avoid double-counting. */
if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
return;
}
const int flag = kernel_data.film.pass_flag;
if (!(flag & PASS_ANY)) {
return;
}
if (!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
ccl_global float *buffer = film_pass_pixel_render_buffer(kg, state, render_buffer);
if (INTEGRATOR_STATE(state, path, sample) == 0) {
if (flag & PASSMASK(DEPTH)) {
film_overwrite_pass_float(buffer + kernel_data.film.pass_depth, 0.0f);
}
if (flag & PASSMASK(OBJECT_ID)) {
film_overwrite_pass_float(buffer + kernel_data.film.pass_object_id, 0.0f);
}
if (flag & PASSMASK(MATERIAL_ID)) {
film_overwrite_pass_float(buffer + kernel_data.film.pass_material_id, 0.0f);
}
if (flag & PASSMASK(POSITION)) {
film_overwrite_pass_float3(buffer + kernel_data.film.pass_position, zero_float3());
}
}
}
#endif
}
CCL_NAMESPACE_END

View File

@ -3,6 +3,7 @@
#pragma once
#include "kernel/film/data_passes.h"
#include "kernel/film/light_passes.h"
#include "kernel/integrator/guiding.h"
@ -131,6 +132,7 @@ ccl_device_inline void integrate_background(KernelGlobals kg,
/* Write to render buffer. */
film_write_background(kg, state, L, transparent, is_transparent_background_ray, render_buffer);
film_write_data_passes_background(kg, state, render_buffer);
}
ccl_device_inline void integrate_distant_lights(KernelGlobals kg,

View File

@ -282,8 +282,12 @@ class NLA_OT_bake(Operator):
def invoke(self, context, _event):
scene = context.scene
self.frame_start = scene.frame_start
self.frame_end = scene.frame_end
if scene.use_preview_range:
self.frame_start = scene.frame_preview_start
self.frame_end = scene.frame_preview_end
else:
self.frame_start = scene.frame_start
self.frame_end = scene.frame_end
self.bake_types = {'POSE'} if context.mode == 'POSE' else {'OBJECT'}
wm = context.window_manager

View File

@ -2073,6 +2073,7 @@ class _defs_gpencil_paint:
def draw_settings(_context, layout, tool):
props = tool.operator_properties("gpencil.interpolate")
layout.prop(props, "layers")
layout.prop(props, "exclude_breakdowns")
layout.prop(props, "flip")
layout.prop(props, "smooth_factor")
layout.prop(props, "smooth_steps")
@ -2256,6 +2257,7 @@ class _defs_gpencil_edit:
props = tool.operator_properties("gpencil.interpolate")
layout.prop(props, "layers")
layout.prop(props, "interpolate_selected_only")
layout.prop(props, "exclude_breakdowns")
layout.prop(props, "flip")
layout.prop(props, "smooth_factor")
layout.prop(props, "smooth_steps")

View File

@ -132,7 +132,8 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
/**
* Sets each output array element to the edge index if it is a real edge, or -1.
*/
void BKE_mesh_looptri_get_real_edges(const struct Mesh *mesh,
void BKE_mesh_looptri_get_real_edges(const struct MEdge *edges,
const struct MLoop *loops,
const struct MLoopTri *looptri,
int r_edges[3]);

View File

@ -22,7 +22,7 @@ namespace blender::meshintersect {
* It is allowed for the pointers to be null, meaning the transformation is the identity.
* \param material_remaps: An array of maps from material slot numbers in the corresponding mesh
* to the material slot in the first mesh. It is OK for material_remaps or any of its constituent
* arrays to be empty.
* arrays to be empty. A -1 value means that the original index should be used with no mapping.
* \param r_intersecting_edges: Array to store indices of edges on the resulting mesh in. These
* 'new' edges are the result of the intersections.
*/

View File

@ -351,6 +351,7 @@ namespace blender::bke::mesh_topology {
Array<int> build_loop_to_poly_map(Span<MPoly> polys, int loops_num);
Array<Vector<int>> build_vert_to_edge_map(Span<MEdge> edges, int verts_num);
Array<Vector<int>> build_vert_to_poly_map(Span<MPoly> polys, Span<MLoop> loops, int verts_num);
Array<Vector<int>> build_vert_to_loop_map(Span<MLoop> loops, int verts_num);
Array<Vector<int>> build_edge_to_loop_map(Span<MLoop> loops, int edges_num);
Vector<Vector<int>> build_edge_to_loop_map_resizable(Span<MLoop> loops, int edges_num);

View File

@ -156,15 +156,8 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float
/**
* Find per-corner coordinate with given per-face UV coord.
*/
int mdisp_rot_face_to_crn(struct MVert *mvert,
struct MPoly *mpoly,
struct MLoop *mloop,
const struct MLoopTri *lt,
int face_side,
float u,
float v,
float *x,
float *y);
int mdisp_rot_face_to_crn(
struct MPoly *mpoly, int face_side, float u, float v, float *x, float *y);
/* Reshaping, define in multires_reshape.c */

View File

@ -17,7 +17,6 @@
#include "DNA_meshdata_types.h"
namespace blender::bke::uv_islands {
struct MeshEdge;

View File

@ -1122,7 +1122,8 @@ static bool collection_object_remove(Main *bmain,
id_us_min(&ob->id);
}
collection_tag_update_parent_recursive(bmain, collection, ID_RECALC_COPY_ON_WRITE);
collection_tag_update_parent_recursive(
bmain, collection, ID_RECALC_COPY_ON_WRITE | ID_RECALC_GEOMETRY);
return true;
}

View File

@ -1490,13 +1490,13 @@ int BKE_mesh_edge_other_vert(const MEdge *e, int v)
return -1;
}
void BKE_mesh_looptri_get_real_edges(const Mesh *mesh, const MLoopTri *looptri, int r_edges[3])
void BKE_mesh_looptri_get_real_edges(const MEdge *edges,
const MLoop *loops,
const MLoopTri *tri,
int r_edges[3])
{
const Span<MEdge> edges = mesh->edges();
const Span<MLoop> loops = mesh->loops();
for (int i = 2, i_next = 0; i_next < 3; i = i_next++) {
const MLoop *l1 = &loops[looptri->tri[i]], *l2 = &loops[looptri->tri[i_next]];
const MLoop *l1 = &loops[tri->tri[i]], *l2 = &loops[tri->tri[i_next]];
const MEdge *e = &edges[l1->e];
bool is_real = (l1->v == e->v1 && l2->v == e->v2) || (l1->v == e->v2 && l2->v == e->v1);

View File

@ -430,12 +430,14 @@ static void copy_poly_attributes(Mesh *dest_mesh,
const VArray<int> src_material_indices = orig_me->attributes().lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
const int src_index = src_material_indices[index_in_orig_me];
if (material_remap.size() > 0 && material_remap.index_range().contains(src_index)) {
dst_material_indices[mp_index] = material_remap[src_index];
if (material_remap.index_range().contains(src_index)) {
const int remapped_index = material_remap[src_index];
dst_material_indices[mp_index] = remapped_index >= 0 ? remapped_index : src_index;
}
else {
dst_material_indices[mp_index] = src_index;
}
BLI_assert(dst_material_indices[mp_index] >= 0);
}
/* Similar to copy_vert_attributes but for edge attributes. */

View File

@ -577,6 +577,20 @@ Array<Vector<int>> build_vert_to_edge_map(const Span<MEdge> edges, const int ver
return map;
}
Array<Vector<int>> build_vert_to_poly_map(const Span<MPoly> polys,
const Span<MLoop> loops,
int verts_num)
{
Array<Vector<int>> map(verts_num);
for (const int64_t i : polys.index_range()) {
const MPoly &poly = polys[i];
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
map[loop.v].append(int(i));
}
}
return map;
}
Array<Vector<int>> build_vert_to_loop_map(const Span<MLoop> loops, const int verts_num)
{
Array<Vector<int>> map(verts_num);

View File

@ -260,45 +260,32 @@ void BKE_mesh_calc_poly_normal_coords(const MPoly *mpoly,
}
}
struct MeshCalcNormalsData_Poly {
const MVert *mvert;
const MLoop *mloop;
const MPoly *mpoly;
/** Polygon normal output. */
float (*pnors)[3];
};
static void mesh_calc_normals_poly_fn(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict /*tls*/)
static void calculate_normals_poly(const Span<MVert> verts,
const Span<MPoly> polys,
const Span<MLoop> loops,
MutableSpan<float3> poly_normals)
{
const MeshCalcNormalsData_Poly *data = (MeshCalcNormalsData_Poly *)userdata;
const MPoly *mp = &data->mpoly[pidx];
BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mvert, data->pnors[pidx]);
using namespace blender;
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int poly_i : range) {
const MPoly &poly = polys[poly_i];
BKE_mesh_calc_poly_normal(&poly, &loops[poly.loopstart], verts.data(), poly_normals[poly_i]);
}
});
}
void BKE_mesh_calc_normals_poly(const MVert *mvert,
int /*mvert_len*/,
const int mvert_len,
const MLoop *mloop,
int /*mloop_len*/,
const int mloop_len,
const MPoly *mpoly,
int mpoly_len,
float (*r_poly_normals)[3])
{
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = 1024;
BLI_assert((r_poly_normals != nullptr) || (mpoly_len == 0));
MeshCalcNormalsData_Poly data = {};
data.mpoly = mpoly;
data.mloop = mloop;
data.mvert = mvert;
data.pnors = r_poly_normals;
BLI_task_parallel_range(0, mpoly_len, &data, mesh_calc_normals_poly_fn, &settings);
calculate_normals_poly({mvert, mvert_len},
{mpoly, mpoly_len},
{mloop, mloop_len},
{reinterpret_cast<float3 *>(r_poly_normals), mpoly_len});
}
/** \} */
@ -310,123 +297,110 @@ void BKE_mesh_calc_normals_poly(const MVert *mvert,
* meshes can slow down high-poly meshes. For details on performance, see D11993.
* \{ */
struct MeshCalcNormalsData_PolyAndVertex {
const MVert *mvert;
const MLoop *mloop;
const MPoly *mpoly;
/** Polygon normal output. */
float (*pnors)[3];
/** Vertex normal output. */
float (*vnors)[3];
};
static void mesh_calc_normals_poly_and_vertex_accum_fn(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict /*tls*/)
static void calculate_normals_poly_and_vert(const Span<MVert> verts,
const Span<MPoly> polys,
const Span<MLoop> loops,
MutableSpan<float3> poly_normals,
MutableSpan<float3> vert_normals)
{
const MeshCalcNormalsData_PolyAndVertex *data = (MeshCalcNormalsData_PolyAndVertex *)userdata;
const MPoly *mp = &data->mpoly[pidx];
const MLoop *ml = &data->mloop[mp->loopstart];
const MVert *mverts = data->mvert;
float(*vnors)[3] = data->vnors;
using namespace blender;
float pnor_temp[3];
float *pnor = data->pnors ? data->pnors[pidx] : pnor_temp;
const int i_end = mp->totloop - 1;
/* Polygon Normal and edge-vector. */
/* Inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors. */
/* Zero the vertex normal array for accumulation. */
{
zero_v3(pnor);
/* Newell's Method */
const float *v_curr = mverts[ml[i_end].v].co;
for (int i_next = 0; i_next <= i_end; i_next++) {
const float *v_next = mverts[ml[i_next].v].co;
add_newell_cross_v3_v3v3(pnor, v_curr, v_next);
v_curr = v_next;
}
if (UNLIKELY(normalize_v3(pnor) == 0.0f)) {
pnor[2] = 1.0f; /* Other axes set to zero. */
}
memset(vert_normals.data(), 0, vert_normals.as_span().size_in_bytes());
}
/* Accumulate angle weighted face normal into the vertex normal. */
/* Inline version of #accumulate_vertex_normals_poly_v3. */
/* Compute poly normals, accumulating them into vertex normals. */
{
float edvec_prev[3], edvec_next[3], edvec_end[3];
const float *v_curr = mverts[ml[i_end].v].co;
sub_v3_v3v3(edvec_prev, mverts[ml[i_end - 1].v].co, v_curr);
normalize_v3(edvec_prev);
copy_v3_v3(edvec_end, edvec_prev);
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int poly_i : range) {
const MPoly &poly = polys[poly_i];
const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
for (int i_next = 0, i_curr = i_end; i_next <= i_end; i_curr = i_next++) {
const float *v_next = mverts[ml[i_next].v].co;
float3 &pnor = poly_normals[poly_i];
/* Skip an extra normalization by reusing the first calculated edge. */
if (i_next != i_end) {
sub_v3_v3v3(edvec_next, v_curr, v_next);
normalize_v3(edvec_next);
const int i_end = poly.totloop - 1;
/* Polygon Normal and edge-vector. */
/* Inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors. */
{
zero_v3(pnor);
/* Newell's Method */
const float *v_curr = verts[poly_loops[i_end].v].co;
for (int i_next = 0; i_next <= i_end; i_next++) {
const float *v_next = verts[poly_loops[i_next].v].co;
add_newell_cross_v3_v3v3(pnor, v_curr, v_next);
v_curr = v_next;
}
if (UNLIKELY(normalize_v3(pnor) == 0.0f)) {
pnor[2] = 1.0f; /* Other axes set to zero. */
}
}
/* Accumulate angle weighted face normal into the vertex normal. */
/* Inline version of #accumulate_vertex_normals_poly_v3. */
{
float edvec_prev[3], edvec_next[3], edvec_end[3];
const float *v_curr = verts[poly_loops[i_end].v].co;
sub_v3_v3v3(edvec_prev, verts[poly_loops[i_end - 1].v].co, v_curr);
normalize_v3(edvec_prev);
copy_v3_v3(edvec_end, edvec_prev);
for (int i_next = 0, i_curr = i_end; i_next <= i_end; i_curr = i_next++) {
const float *v_next = verts[poly_loops[i_next].v].co;
/* Skip an extra normalization by reusing the first calculated edge. */
if (i_next != i_end) {
sub_v3_v3v3(edvec_next, v_curr, v_next);
normalize_v3(edvec_next);
}
else {
copy_v3_v3(edvec_next, edvec_end);
}
/* Calculate angle between the two poly edges incident on this vertex. */
const float fac = saacos(-dot_v3v3(edvec_prev, edvec_next));
const float vnor_add[3] = {pnor[0] * fac, pnor[1] * fac, pnor[2] * fac};
float *vnor = vert_normals[poly_loops[i_curr].v];
add_v3_v3_atomic(vnor, vnor_add);
v_curr = v_next;
copy_v3_v3(edvec_prev, edvec_next);
}
}
}
else {
copy_v3_v3(edvec_next, edvec_end);
}
/* Calculate angle between the two poly edges incident on this vertex. */
const float fac = saacos(-dot_v3v3(edvec_prev, edvec_next));
const float vnor_add[3] = {pnor[0] * fac, pnor[1] * fac, pnor[2] * fac};
add_v3_v3_atomic(vnors[ml[i_curr].v], vnor_add);
v_curr = v_next;
copy_v3_v3(edvec_prev, edvec_next);
}
});
}
}
static void mesh_calc_normals_poly_and_vertex_finalize_fn(
void *__restrict userdata, const int vidx, const TaskParallelTLS *__restrict /*tls*/)
{
MeshCalcNormalsData_PolyAndVertex *data = (MeshCalcNormalsData_PolyAndVertex *)userdata;
/* Normalize and validate computed vertex normals. */
{
threading::parallel_for(verts.index_range(), 1024, [&](const IndexRange range) {
for (const int vert_i : range) {
float *no = vert_normals[vert_i];
const MVert *mv = &data->mvert[vidx];
float *no = data->vnors[vidx];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
/* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
normalize_v3_v3(no, mv->co);
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
/* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
normalize_v3_v3(no, verts[vert_i].co);
}
}
});
}
}
void BKE_mesh_calc_normals_poly_and_vertex(const MVert *mvert,
const int mvert_len,
const MLoop *mloop,
const int /*mloop_len*/,
const int mloop_len,
const MPoly *mpoly,
const int mpoly_len,
float (*r_poly_normals)[3],
float (*r_vert_normals)[3])
{
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = 1024;
memset(r_vert_normals, 0, sizeof(*r_vert_normals) * size_t(mvert_len));
MeshCalcNormalsData_PolyAndVertex data = {};
data.mpoly = mpoly;
data.mloop = mloop;
data.mvert = mvert;
data.pnors = r_poly_normals;
data.vnors = r_vert_normals;
/* Compute poly normals, accumulating them into vertex normals. */
BLI_task_parallel_range(
0, mpoly_len, &data, mesh_calc_normals_poly_and_vertex_accum_fn, &settings);
/* Normalize and validate computed vertex normals. */
BLI_task_parallel_range(
0, mvert_len, &data, mesh_calc_normals_poly_and_vertex_finalize_fn, &settings);
calculate_normals_poly_and_vert({mvert, mvert_len},
{mpoly, mpoly_len},
{mloop, mloop_len},
{reinterpret_cast<float3 *>(r_poly_normals), mpoly_len},
{reinterpret_cast<float3 *>(r_vert_normals), mvert_len});
}
/** \} */

View File

@ -288,7 +288,7 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source)
{
BVHTreeFromMesh bvhtree = {nullptr};
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
const Span<MVert> target_verts = target->verts();
const float *source_mask = (const float *)CustomData_get_layer(&source->vdata, CD_PAINT_MASK);
if (source_mask == nullptr) {
return;
@ -305,13 +305,11 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source)
blender::threading::parallel_for(IndexRange(target->totvert), 4096, [&](const IndexRange range) {
for (const int i : range) {
float from_co[3];
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
copy_v3_v3(from_co, target_verts[i].co);
BLI_bvhtree_find_nearest(
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
target_mask[i] = source_mask[nearest.index];
}
@ -326,9 +324,9 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
using namespace blender::bke;
const AttributeAccessor src_attributes = source->attributes();
MutableAttributeAccessor dst_attributes = target->attributes_for_write();
const MPoly *target_polys = (const MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY);
const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
const MLoop *target_loops = (const MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP);
const Span<MVert> target_verts = target->verts();
const Span<MPoly> target_polys = target->polys();
const Span<MLoop> target_loops = target->loops();
const VArray<int> src_face_sets = src_attributes.lookup<int>(".sculpt_face_set",
ATTR_DOMAIN_FACE);
@ -354,8 +352,9 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
const MPoly *mpoly = &target_polys[i];
BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co);
const MPoly &poly = target_polys[i];
BKE_mesh_calc_poly_center(
&poly, &target_loops[poly.loopstart], target_verts.data(), from_co);
BLI_bvhtree_find_nearest(
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) {
@ -403,7 +402,7 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
size_t data_size = CustomData_sizeof(layer->type);
void *target_data = target_cdata->layers[layer_i].data;
void *source_data = layer->data;
MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
const Span<MVert> target_verts = target->verts();
if (domain == ATTR_DOMAIN_POINT) {
blender::threading::parallel_for(

View File

@ -1522,15 +1522,8 @@ void multiresModifier_ensure_external_read(struct Mesh *mesh, const MultiresModi
/***************** Multires interpolation stuff *****************/
int mdisp_rot_face_to_crn(struct MVert * /*mvert*/,
struct MPoly *mpoly,
struct MLoop * /*mloop*/,
const struct MLoopTri * /*lt*/,
const int face_side,
const float u,
const float v,
float *x,
float *y)
int mdisp_rot_face_to_crn(
MPoly *mpoly, const int face_side, const float u, const float v, float *x, float *y)
{
const float offset = face_side * 0.5f - 0.5f;
int S = 0;

View File

@ -963,11 +963,9 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
* Checks the orientation of the loops to flip the x and y axis when extracting the grid if
* necessary.
*/
static bool multires_unsubdivide_flip_grid_x_axis(Mesh *mesh, int poly, int loop, int v_x)
static bool multires_unsubdivide_flip_grid_x_axis(
const MPoly *polys, const MLoop *loops, int poly, int loop, int v_x)
{
const MPoly *polys = BKE_mesh_polys(mesh);
const MLoop *loops = BKE_mesh_loops(mesh);
const MPoly *p = &polys[poly];
const MLoop *l_first = &loops[p->loopstart];
@ -1037,6 +1035,9 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
const int base_l_offset = CustomData_get_n_offset(
&bm_base_mesh->ldata, CD_PROP_INT32, base_l_layer_index);
const MPoly *polys = BKE_mesh_polys(base_mesh);
const MLoop *loops = BKE_mesh_loops(base_mesh);
/* Main loop for extracting the grids. Iterates over the base mesh vertices. */
BM_ITER_MESH (v, &iter, bm_base_mesh, BM_VERTS_OF_MESH) {
@ -1074,7 +1075,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
/* Check the orientation of the loops in case that is needed to flip the x and y axis
* when extracting the grid. */
const bool flip_grid = multires_unsubdivide_flip_grid_x_axis(
base_mesh, base_mesh_face_index, base_mesh_loop_index, corner_x_index);
polys, loops, base_mesh_face_index, base_mesh_loop_index, corner_x_index);
/* Extract the grid for that loop. */
context->base_mesh_grids[base_mesh_loop_index].grid_index = base_mesh_loop_index;

View File

@ -3765,7 +3765,6 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
}
case PBVH_GRIDS: {
const MPoly *mp = BKE_mesh_polys(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
CCGKey key = pbvh->gridkey;
bool *hide_poly = (bool *)CustomData_get_layer_named(
@ -3773,10 +3772,9 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
bool delete_hide_poly = true;
for (int face_index = 0; face_index < mesh->totpoly; face_index++, mp++) {
const MLoop *ml = mloop + mp->loopstart;
bool hidden = false;
for (int loop_index = 0; !hidden && loop_index < mp->totloop; loop_index++, ml++) {
for (int loop_index = 0; !hidden && loop_index < mp->totloop; loop_index++) {
int grid_index = mp->loopstart + loop_index;
if (pbvh->grid_hidden[grid_index] &&

View File

@ -239,7 +239,7 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
for (int i = 0; i < totlooptri; i++) {
int edges[3];
BKE_mesh_looptri_get_real_edges(mesh, &mlooptri[i], edges);
BKE_mesh_looptri_get_real_edges(medge, mloop, &mlooptri[i], edges);
for (int j = 0; j < 3; j++) {
if (edges[j] >= 0 && edge_mode[edges[j]]) {
@ -1049,7 +1049,7 @@ static void mesh_looptri_target_project(void *userdata,
const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary;
int edges[3];
BKE_mesh_looptri_get_real_edges(tree->mesh, lt, edges);
BKE_mesh_looptri_get_real_edges(data->edge, data->loop, lt, edges);
for (int i = 0; i < 3; i++) {
if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) {

View File

@ -67,6 +67,9 @@ BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution)
typedef struct SubdivForeachTaskContext {
const Mesh *coarse_mesh;
const MEdge *coarse_edges;
const MPoly *coarse_polys;
const MLoop *coarse_loops;
const SubdivToMeshSettings *settings;
/* Callbacks. */
const SubdivForeachContext *foreach_context;
@ -158,16 +161,14 @@ static void subdiv_foreach_ctx_count(SubdivForeachTaskContext *ctx)
const int num_inner_vertices_per_noquad_patch = (no_quad_patch_resolution - 2) *
(no_quad_patch_resolution - 2);
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
ctx->num_subdiv_vertices = coarse_mesh->totvert;
ctx->num_subdiv_edges = coarse_mesh->totedge * (num_subdiv_vertices_per_coarse_edge + 1);
/* Calculate extra vertices and edges created by non-loose geometry. */
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly);
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MLoop *loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const bool is_edge_used = BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, loop->e);
/* Edges which aren't counted yet. */
if (!is_edge_used) {
@ -225,12 +226,11 @@ static void subdiv_foreach_ctx_init_offsets(SubdivForeachTaskContext *ctx)
ctx->edge_inner_offset = ctx->edge_boundary_offset +
coarse_mesh->totedge * num_subdiv_edges_per_coarse_edge;
/* "Indexed" offsets. */
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
int vertex_offset = 0;
int edge_offset = 0;
int polygon_offset = 0;
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly);
ctx->subdiv_vertex_offset[poly_index] = vertex_offset;
ctx->subdiv_edge_offset[poly_index] = edge_offset;
@ -300,13 +300,10 @@ static void subdiv_foreach_corner_vertices_regular_do(
bool check_usage)
{
const float weights[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) {
continue;
@ -342,13 +339,10 @@ static void subdiv_foreach_corner_vertices_special_do(
SubdivForeachVertexFromCornerCb vertex_corner,
bool check_usage)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) {
continue;
@ -409,9 +403,8 @@ static void subdiv_foreach_every_corner_vertices(SubdivForeachTaskContext *ctx,
return;
}
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
if (coarse_poly->totloop == 4) {
subdiv_foreach_every_corner_vertices_regular(ctx, tls, coarse_poly);
}
@ -433,21 +426,16 @@ static void subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext *ct
const int resolution_1 = resolution - 1;
const float inv_resolution_1 = 1.0f / (float)resolution_1;
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_medge = BKE_mesh_edges(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int poly_index = coarse_poly - coarse_mpoly;
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const int coarse_edge_index = coarse_loop->e;
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) {
continue;
}
const MEdge *coarse_edge = &coarse_medge[coarse_edge_index];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index];
const bool flip = (coarse_edge->v2 == coarse_loop->v);
int subdiv_vertex_index = ctx->vertices_edge_offset +
coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
@ -500,22 +488,17 @@ static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ct
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
const int num_vertices_per_ptex_edge = ((resolution >> 1) + 1);
const float inv_ptex_resolution_1 = 1.0f / (float)(num_vertices_per_ptex_edge - 1);
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_medge = BKE_mesh_edges(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int poly_index = coarse_poly - coarse_mpoly;
const int ptex_face_start_index = ctx->face_ptex_offset[poly_index];
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
const int ptex_face_start_index = ctx->face_ptex_offset[coarse_poly_index];
int ptex_face_index = ptex_face_start_index;
for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const int coarse_edge_index = coarse_loop->e;
if (check_usage &&
BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) {
continue;
}
const MEdge *coarse_edge = &coarse_medge[coarse_edge_index];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index];
const bool flip = (coarse_edge->v2 == coarse_loop->v);
int subdiv_vertex_index = ctx->vertices_edge_offset +
coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
@ -597,9 +580,8 @@ static void subdiv_foreach_every_edge_vertices(SubdivForeachTaskContext *ctx, vo
return;
}
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
if (coarse_poly->totloop == 4) {
subdiv_foreach_every_edge_vertices_regular(ctx, tls, coarse_poly);
}
@ -617,9 +599,7 @@ static void subdiv_foreach_inner_vertices_regular(SubdivForeachTaskContext *ctx,
{
const int resolution = ctx->settings->resolution;
const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
const int start_vertex_index = ctx->subdiv_vertex_offset[coarse_poly_index];
int subdiv_vertex_index = ctx->vertices_inner_offset + start_vertex_index;
@ -646,9 +626,7 @@ static void subdiv_foreach_inner_vertices_special(SubdivForeachTaskContext *ctx,
const int resolution = ctx->settings->resolution;
const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution);
const float inv_ptex_face_resolution_1 = 1.0f / (float)(ptex_face_resolution - 1);
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
const int start_vertex_index = ctx->subdiv_vertex_offset[coarse_poly_index];
int subdiv_vertex_index = ctx->vertices_inner_offset + start_vertex_index;
@ -694,11 +672,8 @@ static void subdiv_foreach_inner_vertices(SubdivForeachTaskContext *ctx,
/* Traverse all vertices which are emitted from given coarse polygon. */
static void subdiv_foreach_vertices(SubdivForeachTaskContext *ctx, void *tls, const int poly_index)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
if (ctx->foreach_context->vertex_inner != NULL) {
subdiv_foreach_inner_vertices(ctx, tls, coarse_poly);
subdiv_foreach_inner_vertices(ctx, tls, &ctx->coarse_polys[poly_index]);
}
}
@ -778,11 +753,7 @@ static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *c
void *tls,
const MPoly *coarse_poly)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_medge = BKE_mesh_edges(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const int poly_index = coarse_poly - coarse_mpoly;
const int poly_index = coarse_poly - ctx->coarse_polys;
const int resolution = ctx->settings->resolution;
const int start_vertex_index = ctx->vertices_inner_offset +
ctx->subdiv_vertex_offset[poly_index];
@ -820,8 +791,8 @@ static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *c
}
/* Connect inner part of patch to boundary. */
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
@ -859,11 +830,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c
void *tls,
const MPoly *coarse_poly)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_medge = BKE_mesh_edges(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const int poly_index = coarse_poly - coarse_mpoly;
const int poly_index = coarse_poly - ctx->coarse_polys;
const int resolution = ctx->settings->resolution;
const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution);
const int ptex_face_inner_resolution = ptex_face_resolution - 2;
@ -932,11 +899,12 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c
}
}
/* Connect inner path of patch to boundary. */
const MLoop *prev_coarse_loop = &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
const MLoop *prev_coarse_loop =
&ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1];
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
{
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
@ -956,7 +924,7 @@ static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *c
}
}
if (ptex_face_resolution >= 3) {
const MEdge *coarse_edge = &coarse_medge[prev_coarse_loop->e];
const MEdge *coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e];
const int start_edge_vertex = ctx->vertices_edge_offset +
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
@ -987,19 +955,14 @@ static void subdiv_foreach_edges_all_patches(SubdivForeachTaskContext *ctx,
static void subdiv_foreach_edges(SubdivForeachTaskContext *ctx, void *tls, int poly_index)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
subdiv_foreach_edges_all_patches(ctx, tls, coarse_poly);
subdiv_foreach_edges_all_patches(ctx, tls, &ctx->coarse_polys[poly_index]);
}
static void subdiv_foreach_boundary_edges(SubdivForeachTaskContext *ctx,
void *tls,
int coarse_edge_index)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_medge = BKE_mesh_edges(coarse_mesh);
const MEdge *coarse_edge = &coarse_medge[coarse_edge_index];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index];
const int resolution = ctx->settings->resolution;
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
const int num_subdiv_edges_per_coarse_edge = resolution - 1;
@ -1128,11 +1091,7 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx,
{
const int resolution = ctx->settings->resolution;
/* Base/coarse mesh information. */
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_medge = BKE_mesh_edges(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
const int ptex_resolution = ptex_face_resolution_get(coarse_poly, resolution);
const int ptex_inner_resolution = ptex_resolution - 2;
const int num_subdiv_edges_per_coarse_edge = resolution - 1;
@ -1188,11 +1147,12 @@ static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx,
}
}
/* Loops for faces connecting inner ptex part with boundary. */
const MLoop *prev_coarse_loop = &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
const MLoop *prev_coarse_loop =
&ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1];
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const MEdge *prev_coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e];
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
const bool flip = (coarse_edge->v2 == coarse_loop->v);
@ -1322,11 +1282,7 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
{
const int resolution = ctx->settings->resolution;
/* Base/coarse mesh information. */
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_medge = BKE_mesh_edges(coarse_mesh);
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
const int coarse_poly_index = coarse_poly - coarse_mpoly;
const int coarse_poly_index = coarse_poly - ctx->coarse_polys;
const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution);
const int ptex_face_inner_resolution = ptex_face_resolution - 2;
const float inv_ptex_resolution_1 = 1.0f / (float)(ptex_face_resolution - 1);
@ -1493,12 +1449,13 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
}
}
/* Loops for faces connecting inner ptex part with boundary. */
const MLoop *prev_coarse_loop = &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
const MLoop *prev_coarse_loop =
&ctx->coarse_loops[coarse_poly->loopstart + coarse_poly->totloop - 1];
for (int prev_corner = coarse_poly->totloop - 1, corner = 0; corner < coarse_poly->totloop;
prev_corner = corner, corner++) {
const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
const MLoop *coarse_loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_loop->e];
const MEdge *prev_coarse_edge = &ctx->coarse_edges[prev_coarse_loop->e];
const bool flip = (coarse_edge->v2 == coarse_loop->v);
const int start_edge_vertex = ctx->vertices_edge_offset +
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
@ -1657,9 +1614,7 @@ static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
static void subdiv_foreach_loops(SubdivForeachTaskContext *ctx, void *tls, int poly_index)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
if (coarse_poly->totloop == 4) {
subdiv_foreach_loops_regular(ctx, tls, coarse_poly);
}
@ -1679,9 +1634,7 @@ static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int p
const int resolution = ctx->settings->resolution;
const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
/* Base/coarse mesh information. */
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly);
const int ptex_resolution = ptex_face_resolution_get(coarse_poly, resolution);
const int num_polys_per_ptex = num_polys_per_ptex_get(ptex_resolution);
@ -1734,9 +1687,7 @@ static void subdiv_foreach_vertices_of_loose_edges_task(void *__restrict userdat
const int resolution_1 = resolution - 1;
const float inv_resolution_1 = 1.0f / (float)resolution_1;
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_edges = BKE_mesh_edges(coarse_mesh);
const MEdge *coarse_edge = &coarse_edges[coarse_edge_index];
const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index];
/* Subdivision vertices which corresponds to edge's v1 and v2. */
const int subdiv_v1_index = ctx->vertices_corner_offset + coarse_edge->v1;
const int subdiv_v2_index = ctx->vertices_corner_offset + coarse_edge->v2;
@ -1773,9 +1724,8 @@ static void subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext *ct
return;
}
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
subdiv_foreach_corner_vertices(ctx, tls, coarse_poly);
subdiv_foreach_edge_vertices(ctx, tls, coarse_poly);
}
@ -1784,12 +1734,10 @@ static void subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext *ct
static void subdiv_foreach_mark_non_loose_geometry(SubdivForeachTaskContext *ctx)
{
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MPoly *coarse_mpoly = BKE_mesh_polys(coarse_mesh);
const MLoop *coarse_mloop = BKE_mesh_loops(coarse_mesh);
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
const MPoly *coarse_poly = &ctx->coarse_polys[poly_index];
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
const MLoop *loop = &coarse_mloop[coarse_poly->loopstart + corner];
const MLoop *loop = &ctx->coarse_loops[coarse_poly->loopstart + corner];
BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e);
BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, loop->v);
}
@ -1860,6 +1808,9 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
{
SubdivForeachTaskContext ctx = {0};
ctx.coarse_mesh = coarse_mesh;
ctx.coarse_edges = BKE_mesh_edges(coarse_mesh);
ctx.coarse_polys = BKE_mesh_polys(coarse_mesh);
ctx.coarse_loops = BKE_mesh_loops(coarse_mesh);
ctx.settings = mesh_settings;
ctx.foreach_context = context;
subdiv_foreach_ctx_init(subdiv, &ctx);

View File

@ -520,8 +520,10 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
* so don't try to preserve it and use memory. Crease values should also not be interpolated. */
CustomData_MeshMasks mask = CD_MASK_EVERYTHING;
mask.lmask &= ~CD_MASK_MULTIRES_GRIDS;
/* Propagate edge creases so they can be used in another subdivision modifier (maintaining
* existing behavior), but don't propagate vertex creases to avoid extra work when the result
* isn't useful anyway. */
mask.vmask &= ~CD_MASK_CREASE;
mask.emask &= ~CD_MASK_CREASE;
SubdivMeshContext *subdiv_context = static_cast<SubdivMeshContext *>(foreach_context->user_data);
subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template_ex(
@ -791,7 +793,6 @@ static void subdiv_copy_edge_data(SubdivMeshContext *ctx,
{
const int subdiv_edge_index = subdiv_edge - ctx->subdiv_edges;
if (coarse_edge == nullptr) {
/* TODO: Ensure crease layer isn't copied to result. */
subdiv_edge->flag = 0;
if (!ctx->settings->use_optimal_display) {
subdiv_edge->flag |= ME_EDGEDRAW;

View File

@ -24,6 +24,7 @@
#include "BLI_map.hh"
#include "BLI_math_color.h"
#include "BLI_math_vec_types.hh"
#include "BLI_timeit.hh"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
@ -374,12 +375,13 @@ struct PBVHBatches {
no = CCG_elem_no(&args->ccg_key, elems[0]);
}
else {
for (int j = 0; j < 4; j++) {
no += CCG_elem_no(&args->ccg_key, elems[j]);
}
normal_quad_v3(no,
CCG_elem_co(&args->ccg_key, elems[3]),
CCG_elem_co(&args->ccg_key, elems[2]),
CCG_elem_co(&args->ccg_key, elems[1]),
CCG_elem_co(&args->ccg_key, elems[0]));
}
normalize_v3(no);
short sno[3];
normal_float_to_short_v3(sno, no);
@ -959,6 +961,8 @@ struct PBVHBatches {
material_index = mat_index[poly_index];
}
const blender::Span<MEdge> edges = args->me->edges();
/* Calculate number of edges*/
int edge_count = 0;
for (int i = 0; i < args->totprim; i++) {
@ -969,7 +973,7 @@ struct PBVHBatches {
}
int r_edges[3];
BKE_mesh_looptri_get_real_edges(args->me, lt, r_edges);
BKE_mesh_looptri_get_real_edges(edges.data(), args->mloop, lt, r_edges);
if (r_edges[0] != -1) {
edge_count++;
@ -994,7 +998,7 @@ struct PBVHBatches {
}
int r_edges[3];
BKE_mesh_looptri_get_real_edges(args->me, lt, r_edges);
BKE_mesh_looptri_get_real_edges(edges.data(), args->mloop, lt, r_edges);
if (r_edges[0] != -1) {
GPU_indexbuf_add_line_verts(&elb_lines, vertex_i, vertex_i + 1);

View File

@ -412,15 +412,19 @@ static void gpencil_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgp
}
/* Helper: Get previous keyframe (exclude breakdown type). */
static bGPDframe *gpencil_get_previous_keyframe(bGPDlayer *gpl, int cfra)
static bGPDframe *gpencil_get_previous_keyframe(bGPDlayer *gpl,
int cfra,
const bool exclude_breakdowns)
{
if (gpl->actframe != NULL && gpl->actframe->framenum < cfra &&
gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN) {
return gpl->actframe;
if (gpl->actframe != NULL && gpl->actframe->framenum < cfra) {
if ((!exclude_breakdowns) ||
((exclude_breakdowns) && (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN))) {
return gpl->actframe;
}
}
LISTBASE_FOREACH_BACKWARD (bGPDframe *, gpf, &gpl->frames) {
if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
if ((exclude_breakdowns) && (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN)) {
continue;
}
if (gpf->framenum >= cfra) {
@ -433,10 +437,12 @@ static bGPDframe *gpencil_get_previous_keyframe(bGPDlayer *gpl, int cfra)
}
/* Helper: Get next keyframe (exclude breakdown type). */
static bGPDframe *gpencil_get_next_keyframe(bGPDlayer *gpl, int cfra)
static bGPDframe *gpencil_get_next_keyframe(bGPDlayer *gpl,
int cfra,
const bool exclude_breakdowns)
{
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
if ((exclude_breakdowns) && (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN)) {
continue;
}
if (gpf->framenum <= cfra) {
@ -455,6 +461,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
bGPdata *gpd = tgpi->gpd;
bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
bGPDframe *actframe = active_gpl->actframe;
const bool exclude_breakdowns = (tgpi->flag & GP_TOOLFLAG_INTERPOLATE_EXCLUDE_BREAKDOWNS) != 0;
/* save initial factor for active layer to define shift limits */
tgpi->init_factor = (float)(tgpi->cframe - actframe->framenum) /
@ -483,10 +490,10 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
tgpil->gpl = gpl;
bGPDframe *gpf = gpencil_get_previous_keyframe(gpl, scene->r.cfra);
bGPDframe *gpf = gpencil_get_previous_keyframe(gpl, scene->r.cfra, exclude_breakdowns);
tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpf, true);
gpf = gpencil_get_next_keyframe(gpl, scene->r.cfra);
gpf = gpencil_get_next_keyframe(gpl, scene->r.cfra, exclude_breakdowns);
tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpf, true);
BLI_addtail(&tgpi->ilayers, tgpil);
@ -692,6 +699,9 @@ static bool gpencil_interpolate_set_init_values(bContext *C, wmOperator *op, tGP
tgpi->flag,
(GPENCIL_EDIT_MODE(tgpi->gpd) && RNA_boolean_get(op->ptr, "interpolate_selected_only")),
GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED);
SET_FLAG_FROM_TEST(tgpi->flag,
RNA_boolean_get(op->ptr, "exclude_breakdowns"),
GP_TOOLFLAG_INTERPOLATE_EXCLUDE_BREAKDOWNS);
tgpi->flipmode = RNA_enum_get(op->ptr, "flip");
@ -751,8 +761,9 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent
/* Cannot interpolate if not between 2 frames. */
int cfra = scene->r.cfra;
bGPDframe *gpf_prv = gpencil_get_previous_keyframe(gpl, cfra);
bGPDframe *gpf_next = gpencil_get_next_keyframe(gpl, cfra);
const bool exclude_breakdowns = RNA_boolean_get(op->ptr, "exclude_breakdowns");
bGPDframe *gpf_prv = gpencil_get_previous_keyframe(gpl, cfra, exclude_breakdowns);
bGPDframe *gpf_next = gpencil_get_next_keyframe(gpl, cfra, exclude_breakdowns);
if (ELEM(NULL, gpf_prv, gpf_next)) {
BKE_report(
op->reports,
@ -972,6 +983,12 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot)
"Only Selected",
"Interpolate only selected strokes");
RNA_def_boolean(ot->srna,
"exclude_breakdowns",
false,
"Exclude Breakdowns",
"Exclude existing Breakdowns keyframes as interpolation extremes");
RNA_def_enum(ot->srna,
"flip",
flip_modes,
@ -1229,6 +1246,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
const bool all_layers = (bool)(RNA_enum_get(op->ptr, "layers") == 1);
const bool only_selected = (GPENCIL_EDIT_MODE(gpd) &&
(RNA_boolean_get(op->ptr, "interpolate_selected_only") != 0));
const bool exclude_breakdowns = RNA_boolean_get(op->ptr, "exclude_breakdowns");
eGP_InterpolateFlipMode flipmode = RNA_enum_get(op->ptr, "flip");
@ -1243,8 +1261,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
BKE_curvemapping_init(ipo_settings->custom_ipo);
/* Cannot interpolate if not between 2 frames. */
bGPDframe *gpf_prv = gpencil_get_previous_keyframe(active_gpl, cfra);
bGPDframe *gpf_next = gpencil_get_next_keyframe(active_gpl, cfra);
bGPDframe *gpf_prv = gpencil_get_previous_keyframe(active_gpl, cfra, exclude_breakdowns);
bGPDframe *gpf_next = gpencil_get_next_keyframe(active_gpl, cfra, exclude_breakdowns);
if (ELEM(NULL, gpf_prv, gpf_next)) {
BKE_report(
op->reports,
@ -1268,8 +1286,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
if (!BKE_gpencil_layer_is_editable(gpl)) {
continue;
}
gpf_prv = gpencil_get_previous_keyframe(gpl, cfra);
gpf_next = gpencil_get_next_keyframe(gpl, cfra);
gpf_prv = gpencil_get_previous_keyframe(gpl, cfra, exclude_breakdowns);
gpf_next = gpencil_get_next_keyframe(gpl, cfra, exclude_breakdowns);
/* Need a set of frames to interpolate. */
if ((gpf_prv == NULL) || (gpf_next == NULL)) {
@ -1433,6 +1451,9 @@ static void gpencil_interpolate_seq_ui(bContext *C, wmOperator *op)
uiItemR(row, op->ptr, "interpolate_selected_only", 0, NULL, ICON_NONE);
}
row = uiLayoutRow(layout, true);
uiItemR(row, op->ptr, "exclude_breakdowns", 0, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
uiItemR(row, op->ptr, "flip", 0, NULL, ICON_NONE);
@ -1602,6 +1623,12 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
"Only Selected",
"Interpolate only selected strokes");
RNA_def_boolean(ot->srna,
"exclude_breakdowns",
false,
"Exclude Breakdowns",
"Exclude existing Breakdowns keyframes as interpolation extremes");
RNA_def_enum(ot->srna,
"flip",
flip_modes,

View File

@ -1629,8 +1629,8 @@ static bool ui_drag_toggle_set_xy_xy(
bool changed = false;
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
float xy_a_block[2] = {float(xy_src[0]), float(xy_src[0])};
float xy_b_block[2] = {float(xy_dst[0]), float(xy_dst[0])};
float xy_a_block[2] = {float(xy_src[0]), float(xy_src[1])};
float xy_b_block[2] = {float(xy_dst[0]), float(xy_dst[1])};
ui_window_to_block_fl(region, block, &xy_a_block[0], &xy_a_block[1]);
ui_window_to_block_fl(region, block, &xy_b_block[0], &xy_b_block[1]);

View File

@ -3199,6 +3199,7 @@ void uiItemPopoverPanel_ptr(
Panel panel{};
panel.type = pt;
panel.layout = layout;
panel.flag = PNL_POPOVER;
pt->draw_header(C, &panel);
}
uiBut *but = ui_item_menu(

View File

@ -516,7 +516,7 @@ static ARegion *template_ID_search_menu_item_tooltip(
ID *active_id = static_cast<ID *>(active);
StructRNA *type = RNA_property_pointer_type(&template_ui->ptr, template_ui->prop);
uiSearchItemTooltipData tooltip_data = {0};
uiSearchItemTooltipData tooltip_data = {{0}};
tooltip_data.name = active_id->name + 2;
BLI_snprintf(tooltip_data.description,

View File

@ -1897,17 +1897,9 @@ static void knife_start_cut(KnifeTool_OpData *kcd)
kcd->mdata.is_stored = false;
if (kcd->prev.vert == NULL && kcd->prev.edge == NULL) {
float origin[3], origin_ofs[3];
float ofs_local[3];
negate_v3_v3(ofs_local, kcd->vc.rv3d->ofs);
knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
if (!isect_line_plane_v3(
kcd->prev.cage, origin, origin_ofs, ofs_local, kcd->vc.rv3d->viewinv[2])) {
zero_v3(kcd->prev.cage);
}
ED_view3d_win_to_3d(kcd->vc.v3d, kcd->region, ofs_local, kcd->curr.mval, kcd->prev.cage);
copy_v3_v3(kcd->prev.co, kcd->prev.cage); /* TODO: do we need this? */
copy_v3_v3(kcd->curr.cage, kcd->prev.cage);

View File

@ -1832,14 +1832,27 @@ SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss,
SculptBrushTest *test,
char falloff_shape)
{
if (!ss->cache && !ss->filter_cache) {
falloff_shape = PAINT_FALLOFF_SHAPE_SPHERE;
}
SCULPT_brush_test_init(ss, test);
SculptBrushTestFn sculpt_brush_test_sq_fn;
if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
sculpt_brush_test_sq_fn = SCULPT_brush_test_sphere_sq;
}
else {
float view_normal[3];
if (ss->cache) {
copy_v3_v3(view_normal, ss->cache->view_normal);
}
else {
copy_v3_v3(view_normal, ss->filter_cache->view_normal);
}
/* PAINT_FALLOFF_SHAPE_TUBE */
plane_from_point_normal_v3(test->plane_view, test->location, ss->cache->view_normal);
plane_from_point_normal_v3(test->plane_view, test->location, view_normal);
sculpt_brush_test_sq_fn = SCULPT_brush_test_circle_sq;
}
return sculpt_brush_test_sq_fn;

View File

@ -185,9 +185,8 @@ static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush
return true;
}
if (automasking_flags &
(BRUSH_AUTOMASKING_BOUNDARY_EDGES | BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS |
BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL)) {
if (automasking_flags & (BRUSH_AUTOMASKING_BOUNDARY_EDGES |
BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS | BRUSH_AUTOMASKING_VIEW_NORMAL)) {
return brush && brush->automasking_boundary_edges_propagation_steps != 1;
}
return false;
@ -507,6 +506,16 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
return 1.0f;
}
float mask = 1.0f;
/* Since brush normal mode depends on the current mirror symmery pass
* it is not folded into the factor cache (when it exists).
*/
if ((ss->cache || ss->filter_cache) &&
(automasking->settings.flags & BRUSH_AUTOMASKING_BRUSH_NORMAL)) {
mask *= automasking_brush_normal_factor(automasking, ss, vert, automask_data);
}
/* If the cache is initialized with valid info, use the cache. This is used when the
* automasking information can't be computed in real time per vertex and needs to be
* initialized for the whole mesh when the stroke starts. */
@ -517,7 +526,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
factor *= sculpt_automasking_cavity_factor(automasking, ss, vert);
}
return factor;
return factor * mask;
}
uchar stroke_id = ss->attrs.automasking_stroke_id ?
@ -554,13 +563,6 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
}
}
float mask = 1.0f;
if ((ss->cache || ss->filter_cache) &&
(automasking->settings.flags & BRUSH_AUTOMASKING_BRUSH_NORMAL)) {
mask *= automasking_brush_normal_factor(automasking, ss, vert, automask_data);
}
if ((ss->cache || ss->filter_cache) &&
(automasking->settings.flags & BRUSH_AUTOMASKING_VIEW_NORMAL)) {
mask *= automasking_view_normal_factor(automasking, ss, vert, automask_data);
@ -782,9 +784,6 @@ static void sculpt_normal_occlusion_automasking_fill(AutomaskingCache *automaski
float f = *(float *)SCULPT_vertex_attr_get(vertex, ss->attrs.automasking_factor);
if (int(mode) & BRUSH_AUTOMASKING_BRUSH_NORMAL) {
f *= automasking_brush_normal_factor(automasking, ss, vertex, &nodedata);
}
if (int(mode) & BRUSH_AUTOMASKING_VIEW_NORMAL) {
if (int(mode) & BRUSH_AUTOMASKING_VIEW_OCCLUSION) {
f *= automasking_view_occlusion_factor(automasking, ss, vertex, -1, &nodedata);
@ -940,8 +939,7 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object
/* Subtractive modes. */
int normal_bits = sculpt_automasking_mode_effective_bits(sd, brush) &
(BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL |
BRUSH_AUTOMASKING_VIEW_OCCLUSION);
(BRUSH_AUTOMASKING_VIEW_NORMAL | BRUSH_AUTOMASKING_VIEW_OCCLUSION);
if (normal_bits) {
sculpt_normal_occlusion_automasking_fill(automasking, ob, (eAutomasking_flag)normal_bits);

View File

@ -362,12 +362,18 @@ static void do_paint_pixels(void *__restrict userdata,
}
bool pixels_painted = false;
if (image_buffer->rect_float != nullptr) {
pixels_painted = kernel_float4.paint(
pbvh_data.geom_primitives, node_data.uv_primitives, pixel_row, image_buffer, &automask_data);
pixels_painted = kernel_float4.paint(pbvh_data.geom_primitives,
node_data.uv_primitives,
pixel_row,
image_buffer,
&automask_data);
}
else {
pixels_painted = kernel_byte4.paint(
pbvh_data.geom_primitives, node_data.uv_primitives, pixel_row, image_buffer, &automask_data);
pixels_painted = kernel_byte4.paint(pbvh_data.geom_primitives,
node_data.uv_primitives,
pixel_row,
image_buffer,
&automask_data);
}
if (pixels_painted) {

View File

@ -216,13 +216,25 @@ static bool outliner_operation_tree_element_poll(bContext *C)
}
static void unlink_action_fn(bContext *C,
ReportList * /*reports*/,
ReportList *reports,
Scene * /*scene*/,
TreeElement * /*te*/,
TreeStoreElem *tsep,
TreeStoreElem * /*tselem*/,
TreeStoreElem *tselem,
void * /*user_data*/)
{
if (!tsep || !TSE_IS_REAL_ID(tsep)) {
/* Valid case, no parent element of the action or it is not an ID (could be a #TSE_ID_BASE
* for example) so there's no data to unlink from. */
BKE_reportf(reports,
RPT_WARNING,
"Cannot unlink action '%s'. It's not clear which object or object-data it "
"should be unlinked from, there's no object or object-data as parent in the "
"Outliner tree",
tselem->id->name + 2);
return;
}
/* just set action to nullptr */
BKE_animdata_set_action(CTX_wm_reports(C), tsep->id, nullptr);
DEG_id_tag_update(tsep->id, ID_RECALC_ANIMATION);

View File

@ -175,53 +175,28 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
return status;
}
static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
static void apply_shear_value(TransInfo *t, const float value)
{
float smat[3][3], axismat[3][3], axismat_inv[3][3], mat_final[3][3];
float value;
int i;
char str[UI_MAX_DRAW_STR];
const bool is_local_center = transdata_check_local_center(t, t->around);
value = t->values[0] + t->values_modal_offset[0];
transform_snap_increment(t, &value);
applyNumInput(&t->num, &value);
t->values_final[0] = value;
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, sizeof(str), TIP_("Shear: %s %s"), c, t->proptext);
}
else {
/* default header print */
BLI_snprintf(str,
sizeof(str),
TIP_("Shear: %.3f %s (Press X or Y to set shear axis)"),
value,
t->proptext);
}
float smat[3][3];
unit_m3(smat);
smat[1][0] = value;
float axismat_inv[3][3];
copy_v3_v3(axismat_inv[0], t->spacemtx[t->orient_axis_ortho]);
copy_v3_v3(axismat_inv[2], t->spacemtx[t->orient_axis]);
cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]);
float axismat[3][3];
invert_m3_m3(axismat, axismat_inv);
float mat_final[3][3];
mul_m3_series(mat_final, axismat_inv, smat, axismat);
const bool is_local_center = transdata_check_local_center(t, t->around);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
for (int i = 0; i < tc->data_len; i++, td++) {
if (td->flag & TD_SKIP) {
continue;
}
@ -241,16 +216,117 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
BLI_task_parallel_range(0, tc->data_len, &data, transdata_elem_shear_fn, &settings);
}
}
}
static bool uv_shear_in_clip_bounds_test(const TransInfo *t, const float value)
{
const int axis = t->orient_axis_ortho;
if (axis < 0 || 1 < axis) {
return true; /* Non standard axis, nothing to do. */
}
const float *center = t->center_global;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (int i = 0; i < tc->data_len; i++, td++) {
if (td->flag & TD_SKIP) {
continue;
}
if (td->factor < 1.0f) {
continue; /* Proportional edit, will get picked up in next phase. */
}
float uv[2];
sub_v2_v2v2(uv, td->iloc, center);
uv[axis] = uv[axis] + value * uv[1 - axis] * (2 * axis - 1);
add_v2_v2(uv, center);
/* TODO: udim support. */
if (uv[axis] < 0.0f || 1.0f < uv[axis]) {
return false;
}
}
}
return true;
}
static bool clip_uv_transform_shear(const TransInfo *t, float *vec, float *vec_inside_bounds)
{
float value = vec[0];
if (uv_shear_in_clip_bounds_test(t, value)) {
vec_inside_bounds[0] = value; /* Store for next iteration. */
return false; /* Nothing to do. */
}
float value_inside_bounds = vec_inside_bounds[0];
if (!uv_shear_in_clip_bounds_test(t, value_inside_bounds)) {
return false; /* No known way to fix, may as well shear anyway. */
}
const int max_i = 32; /* Limit iteration, mainly for debugging. */
for (int i = 0; i < max_i; i++) {
/* Binary search. */
const float value_mid = (value_inside_bounds + value) / 2.0f;
if (value_mid == value_inside_bounds || value_mid == value) {
break; /* float precision reached. */
}
if (uv_shear_in_clip_bounds_test(t, value_mid)) {
value_inside_bounds = value_mid;
}
else {
value = value_mid;
}
}
vec_inside_bounds[0] = value_inside_bounds; /* Store for next iteration. */
vec[0] = value_inside_bounds; /* Update shear value. */
return true;
}
static void apply_shear(TransInfo *t, const int UNUSED(mval[2]))
{
float value = t->values[0] + t->values_modal_offset[0];
transform_snap_increment(t, &value);
applyNumInput(&t->num, &value);
t->values_final[0] = value;
apply_shear_value(t, value);
if (t->flag & T_CLIP_UV) {
if (clip_uv_transform_shear(t, t->values_final, t->values_inside_constraints)) {
apply_shear_value(t, t->values_final[0]);
}
/* In proportional edit it can happen that */
/* vertices in the radius of the brush end */
/* outside the clipping area */
/* XXX HACK - dg */
if (t->flag & T_PROP_EDIT) {
clipUVData(t);
}
}
recalcData(t);
char str[UI_MAX_DRAW_STR];
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c, &t->scene->unit);
BLI_snprintf(str, sizeof(str), TIP_("Shear: %s %s"), c, t->proptext);
}
else {
/* default header print */
BLI_snprintf(str,
sizeof(str),
TIP_("Shear: %.3f %s (Press X or Y to set shear axis)"),
value,
t->proptext);
}
ED_area_status_text(t->area, str);
}
void initShear(TransInfo *t)
{
t->mode = TFM_SHEAR;
t->transform = applyShear;
t->transform = apply_shear;
t->handleEvent = handleEventShear;
if (t->orient_axis == t->orient_axis_ortho) {

View File

@ -627,10 +627,9 @@ static eSnapFlag snap_flag_from_spacetype(TransInfo *t)
/* These editors have their own "Auto-Snap" activation option.
* See #getAnimEdit_SnapMode. */
return eSnapFlag(0);
default:
BLI_assert(false);
break;
}
/* #SPACE_EMPTY.
* It can happen when the operator is called via a handle in `bpy.app.handlers`. */
return eSnapFlag(0);
}

View File

@ -1474,6 +1474,9 @@ struct EdgeFeatData {
Object *ob_eval; /* For evaluated materials. */
const MLoopTri *mlooptri;
const int *material_indices;
blender::Span<MEdge> edges;
blender::Span<MLoop> loops;
blender::Span<MPoly> polys;
LineartTriangle *tri_array;
LineartVert *v_array;
float crease_threshold;
@ -1639,13 +1642,11 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
}
if (!only_contour) {
const MPoly *polys = BKE_mesh_polys(me);
if (ld->conf.use_crease) {
bool do_crease = true;
if (!ld->conf.force_crease && !e_feat_data->use_auto_smooth &&
(polys[mlooptri[f1].poly].flag & ME_SMOOTH) &&
(polys[mlooptri[f2].poly].flag & ME_SMOOTH)) {
(e_feat_data->polys[mlooptri[f1].poly].flag & ME_SMOOTH) &&
(e_feat_data->polys[mlooptri[f2].poly].flag & ME_SMOOTH)) {
do_crease = false;
}
if (do_crease && (dot_v3v3_db(tri1->gn, tri2->gn) < e_feat_data->crease_threshold)) {
@ -1677,13 +1678,12 @@ static void lineart_identify_mlooptri_feature_edges(void *__restrict userdata,
}
}
const MEdge *edges = BKE_mesh_edges(me);
int real_edges[3];
BKE_mesh_looptri_get_real_edges(me, &mlooptri[i / 3], real_edges);
BKE_mesh_looptri_get_real_edges(
e_feat_data->edges.data(), e_feat_data->loops.data(), &mlooptri[i / 3], real_edges);
if (real_edges[i % 3] >= 0) {
const MEdge *medge = &edges[real_edges[i % 3]];
const MEdge *medge = &e_feat_data->edges[real_edges[i % 3]];
if (ld->conf.use_crease && ld->conf.sharp_as_crease && (medge->flag & ME_SHARP)) {
edge_flag_result |= LRT_EDGE_FLAG_CREASE;
@ -1785,6 +1785,8 @@ static void lineart_triangle_adjacent_assign(LineartTriangle *tri,
struct TriData {
LineartObjectInfo *ob_info;
blender::Span<MVert> verts;
blender::Span<MLoop> loops;
const MLoopTri *mlooptri;
const int *material_indices;
LineartVert *vert_arr;
@ -1798,13 +1800,13 @@ static void lineart_load_tri_task(void *__restrict userdata,
const TaskParallelTLS *__restrict /*tls*/)
{
TriData *tri_task_data = (TriData *)userdata;
Mesh *me = tri_task_data->ob_info->original_me;
LineartObjectInfo *ob_info = tri_task_data->ob_info;
const blender::Span<MVert> verts = tri_task_data->verts;
const blender::Span<MLoop> loops = tri_task_data->loops;
const MLoopTri *mlooptri = &tri_task_data->mlooptri[i];
const int *material_indices = tri_task_data->material_indices;
LineartVert *vert_arr = tri_task_data->vert_arr;
LineartTriangle *tri = tri_task_data->tri_arr;
const MLoop *loops = BKE_mesh_loops(me);
tri = (LineartTriangle *)(((uchar *)tri) + tri_task_data->lineart_triangle_size * i);
@ -1837,7 +1839,6 @@ static void lineart_load_tri_task(void *__restrict userdata,
double gn[3];
float no[3];
const MVert *verts = BKE_mesh_verts(me);
normal_tri_v3(no, verts[v1].co, verts[v2].co, verts[v3].co);
copy_v3db_v3fl(gn, no);
mul_v3_mat3_m4v3_db(tri->gn, ob_info->normal, gn);
@ -2043,6 +2044,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
TriData tri_data;
tri_data.ob_info = ob_info;
tri_data.mlooptri = mlooptri;
tri_data.verts = me->verts();
tri_data.material_indices = material_indices;
tri_data.vert_arr = la_v_arr;
tri_data.tri_arr = la_tri_arr;
@ -2072,6 +2074,9 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info,
edge_feat_data.ob_eval = ob_info->original_ob_eval;
edge_feat_data.mlooptri = mlooptri;
edge_feat_data.material_indices = material_indices;
edge_feat_data.edges = me->edges();
edge_feat_data.polys = me->polys();
edge_feat_data.loops = me->loops();
edge_feat_data.edge_nabr = lineart_build_edge_neighbor(me, total_edges);
edge_feat_data.tri_array = la_tri_arr;
edge_feat_data.v_array = la_v_arr;

View File

@ -177,7 +177,8 @@ void BKE_mesh_calc_poly_normal(const struct MPoly * /*mpoly*/,
BLI_assert_unreachable();
}
void BKE_mesh_looptri_get_real_edges(const struct Mesh * /*mesh*/,
void BKE_mesh_looptri_get_real_edges(const struct MEdge * /*edges*/,
const struct MLoop * /*loops*/,
const struct MLoopTri * /*looptri*/,
int UNUSED(r_edges[3]))
{

View File

@ -173,7 +173,6 @@ static void get_cols(const CDStreamConfig &config,
{
const float cscale = 1.0f / 255.0f;
const MPoly *polys = config.mpoly;
const MLoop *mloops = config.mloop;
const MCol *cfaces = static_cast<const MCol *>(cd_data);
buffer.reserve(config.totvert);
@ -184,11 +183,9 @@ static void get_cols(const CDStreamConfig &config,
for (int i = 0; i < config.totpoly; i++) {
const MPoly *p = &polys[i];
const MCol *cface = &cfaces[p->loopstart + p->totloop];
const MLoop *mloop = &mloops[p->loopstart + p->totloop];
for (int j = 0; j < p->totloop; j++) {
cface--;
mloop--;
col[0] = cface->a * cscale;
col[1] = cface->r * cscale;

View File

@ -899,10 +899,18 @@ typedef struct BooleanModifierData {
float double_threshold;
char operation;
char solver;
/** #BooleanModifierMaterialMode. */
char material_mode;
char flag;
char bm_flag;
char _pad[7];
} BooleanModifierData;
typedef enum BooleanModifierMaterialMode {
eBooleanModifierMaterialMode_Index = 0,
eBooleanModifierMaterialMode_Transfer = 1,
} BooleanModifierMaterialMode;
/** #BooleanModifierData.operation */
typedef enum {
eBooleanModifierOp_Intersect = 0,

View File

@ -1199,6 +1199,8 @@ typedef enum eGP_Interpolate_SettingsFlag {
GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS = (1 << 0),
/* apply interpolation to only selected */
GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED = (1 << 1),
/* Exclude breakdown keyframe type as extreme */
GP_TOOLFLAG_INTERPOLATE_EXCLUDE_BREAKDOWNS = (1 << 2),
} eGP_Interpolate_SettingsFlag;
/** #GP_Interpolate_Settings.type */

View File

@ -2760,6 +2760,24 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem material_mode_items[] = {
{eBooleanModifierMaterialMode_Index,
"INDEX",
0,
"Index Based",
"Set the material on new faces based on the order of the material slot lists. If a "
"material doesn't exist on the modifier object, the face will use the same material slot "
"or the first if the object doesn't have enough slots"},
{eBooleanModifierMaterialMode_Transfer,
"TRANSFER",
0,
"Transfer",
"Transfer materials from non-empty slots to the result mesh, adding new materials as "
"necessary. For empty slots, fall back to using the same material index as the operand "
"mesh"},
{0, NULL, 0, NULL, NULL},
};
srna = RNA_def_struct(brna, "BooleanModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Boolean Modifier", "Boolean operations modifier");
RNA_def_struct_sdna(srna, "BooleanModifierData");
@ -2819,6 +2837,12 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hole Tolerant", "Better results when there are holes (slower)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "material_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, material_mode_items);
RNA_def_property_enum_default(prop, eBooleanModifierMaterialMode_Index);
RNA_def_property_ui_text(prop, "Material Mode", "Method for setting materials on the new faces");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
/* BMesh debugging options, only used when G_DEBUG is set */
/* BMesh intersection options */

View File

@ -323,6 +323,7 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
# include "BKE_deform.h"
# include "BKE_effect.h"
# include "BKE_global.h"
# include "BKE_gpencil_modifier.h"
# include "BKE_key.h"
# include "BKE_material.h"
# include "BKE_mesh.h"
@ -1949,6 +1950,8 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain,
GpencilModifierData *mod_dst = ED_object_gpencil_modifier_add(
NULL, bmain, NULL, ob_dst, mod_src->name, mod_src->type);
BKE_gpencil_modifier_copydata(mod_src, mod_dst);
BLI_remlink(&ob_dst->greasepencil_modifiers, mod_dst);
/* This handles NULL anchor as expected by adding at head of list. */
BLI_insertlinkafter(&ob_dst->greasepencil_modifiers, mod_anchor, mod_dst);

View File

@ -377,21 +377,31 @@ static void BMD_mesh_intersection(BMesh *bm,
#ifdef WITH_GMP
/* Get a mapping from material slot numbers in the src_ob to slot numbers in the dst_ob.
* If a material doesn't exist in the dst_ob, the mapping just goes to the same slot
* or to zero if there aren't enough slots in the destination. */
static Array<short> get_material_remap_index_based(Object *dest_ob, Object *src_ob)
{
int n = src_ob->totcol;
if (n <= 0) {
n = 1;
}
Array<short> remap(n);
BKE_object_material_remap_calc(dest_ob, src_ob, remap.data());
return remap;
}
/* Get a mapping from material slot numbers in the source geometry to slot numbers in the result
* geometry. The material is added to the result geometry if it doesn't already use it. */
static Array<short> get_material_remap(Object &object,
const Mesh &mesh,
VectorSet<Material *> &materials)
static Array<short> get_material_remap_transfer(Object &object,
const Mesh &mesh,
VectorSet<Material *> &materials)
{
const int material_num = mesh.totcol;
if (material_num == 0) {
/* Necessary for faces using the default material when there are no material slots. */
return Array<short>({materials.index_of_or_add(nullptr)});
}
Array<short> map(material_num);
for (const int i : IndexRange(material_num)) {
Material *material = BKE_object_material_get_eval(&object, i + 1);
map[i] = materials.index_of_or_add(material);
map[i] = material ? materials.index_of_or_add(material) : -1;
}
return map;
}
@ -403,7 +413,6 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
Vector<const Mesh *> meshes;
Vector<float4x4 *> obmats;
VectorSet<Material *> materials;
Vector<Array<short>> material_remaps;
# ifdef DEBUG_TIME
@ -417,12 +426,18 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
meshes.append(mesh);
obmats.append((float4x4 *)&ctx->object->object_to_world);
material_remaps.append({});
if (mesh->totcol == 0) {
/* Necessary for faces using the default material when there are no material slots. */
materials.add(nullptr);
}
else {
materials.add_multiple({mesh->mat, mesh->totcol});
const BooleanModifierMaterialMode material_mode = BooleanModifierMaterialMode(
bmd->material_mode);
VectorSet<Material *> materials;
if (material_mode == eBooleanModifierMaterialMode_Transfer) {
if (mesh->totcol == 0) {
/* Necessary for faces using the default material when there are no material slots. */
materials.add(nullptr);
}
else {
materials.add_multiple({mesh->mat, mesh->totcol});
}
}
if (bmd->flag & eBooleanModifierFlag_Object) {
@ -433,7 +448,12 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
BKE_mesh_wrapper_ensure_mdata(mesh_operand);
meshes.append(mesh_operand);
obmats.append((float4x4 *)&bmd->object->object_to_world);
material_remaps.append(get_material_remap(*bmd->object, *mesh_operand, materials));
if (material_mode == eBooleanModifierMaterialMode_Index) {
material_remaps.append(get_material_remap_index_based(ctx->object, bmd->object));
}
else {
material_remaps.append(get_material_remap_transfer(*bmd->object, *mesh_operand, materials));
}
}
else if (bmd->flag & eBooleanModifierFlag_Collection) {
Collection *collection = bmd->collection;
@ -448,7 +468,12 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
BKE_mesh_wrapper_ensure_mdata(collection_mesh);
meshes.append(collection_mesh);
obmats.append((float4x4 *)&ob->object_to_world);
material_remaps.append(get_material_remap(*ob, *collection_mesh, materials));
if (material_mode == eBooleanModifierMaterialMode_Index) {
material_remaps.append(get_material_remap_index_based(ctx->object, ob));
}
else {
material_remaps.append(get_material_remap_transfer(*ob, *collection_mesh, materials));
}
}
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
@ -466,10 +491,14 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
hole_tolerant,
bmd->operation,
nullptr);
MEM_SAFE_FREE(result->mat);
result->mat = (Material **)MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__);
result->totcol = materials.size();
MutableSpan(result->mat, result->totcol).copy_from(materials);
if (material_mode == eBooleanModifierMaterialMode_Transfer) {
MEM_SAFE_FREE(result->mat);
result->mat = (Material **)MEM_malloc_arrayN(materials.size(), sizeof(Material *), __func__);
result->totcol = materials.size();
MutableSpan(result->mat, result->totcol).copy_from(materials);
}
return result;
}
#endif
@ -610,6 +639,7 @@ static void solver_options_panel_draw(const bContext * /*C*/, Panel *panel)
uiLayout *col = uiLayoutColumn(layout, true);
if (use_exact) {
uiItemR(col, ptr, "material_mode", 0, IFACE_("Materials"), ICON_NONE);
/* When operand is collection, we always use_self. */
if (RNA_enum_get(ptr, "operand_type") == eBooleanModifierFlag_Object) {
uiItemR(col, ptr, "use_self", 0, nullptr, ICON_NONE);

View File

@ -120,7 +120,7 @@ static void uv_warp_compute(void *__restrict userdata,
}
}
else {
for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
for (l = 0; l < mp->totloop; l++, mluv++) {
uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat);
}
}

View File

@ -83,8 +83,12 @@ static void node_geo_exec(GeoNodeExecParams params)
if (mesh_in_a != nullptr) {
meshes.append(mesh_in_a);
transforms.append(nullptr);
for (Material *material : Span(mesh_in_a->mat, mesh_in_a->totcol)) {
materials.add(material);
if (mesh_in_a->totcol == 0) {
/* Necessary for faces using the default material when there are no material slots. */
materials.add(nullptr);
}
else {
materials.add_multiple({mesh_in_a->mat, mesh_in_a->totcol});
}
material_remaps.append({});
}
@ -98,20 +102,13 @@ static void node_geo_exec(GeoNodeExecParams params)
bke::geometry_set_gather_instances(geometry_set, set_groups);
}
for (const bke::GeometryInstanceGroup &set_group : set_groups) {
const Mesh *mesh = set_group.geometry_set.get_mesh_for_read();
if (mesh != nullptr) {
for (Material *material : Span(mesh->mat, mesh->totcol)) {
materials.add(material);
}
}
}
for (const bke::GeometryInstanceGroup &set_group : set_groups) {
const Mesh *mesh = set_group.geometry_set.get_mesh_for_read();
if (mesh != nullptr) {
Array<short> map(mesh->totcol);
for (const int i : IndexRange(mesh->totcol)) {
map[i] = materials.index_of(mesh->mat[i]);
Material *material = mesh->mat[i];
map[i] = material ? materials.index_of_or_add(material) : -1;
}
material_remaps.append(std::move(map));
}

View File

@ -8,6 +8,7 @@
#include "BKE_attribute_math.hh"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "node_geometry_util.hh"
@ -126,7 +127,6 @@ static void copy_data_based_on_pairs(Span<T> data,
* closest face.
*/
static void transfer_attributes(
const Map<AttributeIDRef, AttributeKind> &attributes,
const Span<VertexType> vertex_types,
const bool keep_boundaries,
const Span<int> new_to_old_edges_map,
@ -135,12 +135,14 @@ static void transfer_attributes(
const AttributeAccessor src_attributes,
MutableAttributeAccessor dst_attributes)
{
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
GAttributeReader src_attribute = src_attributes.lookup(attribute_id);
if (!src_attribute) {
continue;
}
/* Retrieve all attributes except for position which is handled manually.
* Remove anonymous attributes that don't need to be propagated.*/
Set<AttributeIDRef> attribute_ids = src_attributes.all_ids();
attribute_ids.remove("position");
attribute_ids.remove_if([](const AttributeIDRef &id) { return !id.should_be_kept(); });
for (const AttributeIDRef &id : attribute_ids) {
GAttributeReader src_attribute = src_attributes.lookup(id);
eAttrDomain out_domain;
if (src_attribute.domain == ATTR_DOMAIN_FACE) {
@ -156,7 +158,7 @@ static void transfer_attributes(
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
@ -249,23 +251,6 @@ static void calc_boundaries(const Mesh &mesh,
}
}
/**
* Stores the indices of the polygons connected to each vertex.
*/
static void create_vertex_poly_map(const Mesh &mesh,
MutableSpan<Vector<int>> r_vertex_poly_indices)
{
const Span<MPoly> polys = mesh.polys();
const Span<MLoop> loops = mesh.loops();
for (const int i : polys.index_range()) {
const MPoly &poly = polys[i];
const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
for (const MLoop &loop : poly_loops) {
r_vertex_poly_indices[loop.v].append(i);
}
}
}
/**
* Sorts the polygons connected to the given vertex based on polygon adjacency. The ordering is
* so such that the normals point in the same way as the original mesh. If the vertex is a
@ -538,14 +523,13 @@ static bool vertex_needs_dissolving(const int vertex,
const int first_poly_index,
const int second_poly_index,
const Span<VertexType> vertex_types,
const Span<Vector<int>> vertex_poly_indices)
const Span<Vector<int>> vert_to_poly_map)
{
/* Order is guaranteed to be the same because 2poly verts that are not on the boundary are
* ignored in `sort_vertex_polys`. */
return (vertex_types[vertex] != VertexType::Boundary &&
vertex_poly_indices[vertex].size() == 2 &&
vertex_poly_indices[vertex][0] == first_poly_index &&
vertex_poly_indices[vertex][1] == second_poly_index);
return (vertex_types[vertex] != VertexType::Boundary && vert_to_poly_map[vertex].size() == 2 &&
vert_to_poly_map[vertex][0] == first_poly_index &&
vert_to_poly_map[vertex][1] == second_poly_index);
}
/**
@ -558,7 +542,7 @@ static bool vertex_needs_dissolving(const int vertex,
static void dissolve_redundant_verts(const Span<MEdge> edges,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<Vector<int>> vertex_poly_indices,
const Span<Vector<int>> vert_to_poly_map,
MutableSpan<VertexType> vertex_types,
MutableSpan<int> old_to_new_edges_map,
Vector<MEdge> &new_edges,
@ -566,11 +550,11 @@ static void dissolve_redundant_verts(const Span<MEdge> edges,
{
const int vertex_num = vertex_types.size();
for (const int vert_i : IndexRange(vertex_num)) {
if (vertex_poly_indices[vert_i].size() != 2 || vertex_types[vert_i] != VertexType::Normal) {
if (vert_to_poly_map[vert_i].size() != 2 || vertex_types[vert_i] != VertexType::Normal) {
continue;
}
const int first_poly_index = vertex_poly_indices[vert_i][0];
const int second_poly_index = vertex_poly_indices[vert_i][1];
const int first_poly_index = vert_to_poly_map[vert_i][0];
const int second_poly_index = vert_to_poly_map[vert_i][1];
const int new_edge_index = new_edges.size();
bool edge_created = false;
const MPoly &poly = polys[first_poly_index];
@ -581,13 +565,13 @@ static void dissolve_redundant_verts(const Span<MEdge> edges,
const int v2 = edge.v2;
bool mark_edge = false;
if (vertex_needs_dissolving(
v1, first_poly_index, second_poly_index, vertex_types, vertex_poly_indices)) {
v1, first_poly_index, second_poly_index, vertex_types, vert_to_poly_map)) {
/* This vertex is now 'removed' and should be ignored elsewhere. */
vertex_types[v1] = VertexType::Loose;
mark_edge = true;
}
if (vertex_needs_dissolving(
v2, first_poly_index, second_poly_index, vertex_types, vertex_poly_indices)) {
v2, first_poly_index, second_poly_index, vertex_types, vert_to_poly_map)) {
/* This vertex is now 'removed' and should be ignored elsewhere. */
vertex_types[v2] = VertexType::Loose;
mark_edge = true;
@ -622,38 +606,31 @@ static void dissolve_redundant_verts(const Span<MEdge> edges,
*
* Some special cases are needed for boundaries and non-manifold geometry.
*/
static void calc_dual_mesh(GeometrySet &geometry_set,
const MeshComponent &in_component,
const bool keep_boundaries)
static Mesh *calc_dual_mesh(const Mesh &src_mesh, const bool keep_boundaries)
{
const Mesh &mesh_in = *in_component.get_for_read();
const Span<MVert> src_verts = mesh_in.verts();
const Span<MEdge> src_edges = mesh_in.edges();
const Span<MPoly> src_polys = mesh_in.polys();
const Span<MLoop> src_loops = mesh_in.loops();
const Span<MVert> src_verts = src_mesh.verts();
const Span<MEdge> src_edges = src_mesh.edges();
const Span<MPoly> src_polys = src_mesh.polys();
const Span<MLoop> src_loops = src_mesh.loops();
Map<AttributeIDRef, AttributeKind> attributes;
geometry_set.gather_attributes_for_propagation(
{GEO_COMPONENT_TYPE_MESH}, GEO_COMPONENT_TYPE_MESH, false, attributes);
Array<VertexType> vertex_types(mesh_in.totvert);
Array<EdgeType> edge_types(mesh_in.totedge);
calc_boundaries(mesh_in, vertex_types, edge_types);
Array<VertexType> vertex_types(src_mesh.totvert);
Array<EdgeType> edge_types(src_mesh.totedge);
calc_boundaries(src_mesh, vertex_types, edge_types);
/* Stores the indices of the polygons connected to the vertex. Because the polygons are looped
* over in order of their indices, the polygon's indices will be sorted in ascending order.
* (This can change once they are sorted using `sort_vertex_polys`). */
Array<Vector<int>> vertex_poly_indices(mesh_in.totvert);
Array<Array<int>> vertex_shared_edges(mesh_in.totvert);
Array<Array<int>> vertex_corners(mesh_in.totvert);
create_vertex_poly_map(mesh_in, vertex_poly_indices);
threading::parallel_for(vertex_poly_indices.index_range(), 512, [&](IndexRange range) {
Array<Vector<int>> vert_to_poly_map = bke::mesh_topology::build_vert_to_poly_map(
src_polys, src_loops, src_verts.size());
Array<Array<int>> vertex_shared_edges(src_mesh.totvert);
Array<Array<int>> vertex_corners(src_mesh.totvert);
threading::parallel_for(vert_to_poly_map.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
if (vertex_types[i] == VertexType::Loose || vertex_types[i] >= VertexType::NonManifold ||
(!keep_boundaries && vertex_types[i] == VertexType::Boundary)) {
/* Bad vertex that we can't work with. */
continue;
}
MutableSpan<int> loop_indices = vertex_poly_indices[i];
MutableSpan<int> loop_indices = vert_to_poly_map[i];
Array<int> sorted_corners(loop_indices.size());
bool vertex_ok = true;
if (vertex_types[i] == VertexType::Normal) {
@ -692,8 +669,8 @@ static void calc_dual_mesh(GeometrySet &geometry_set,
}
});
Vector<float3> vertex_positions(mesh_in.totpoly);
for (const int i : IndexRange(mesh_in.totpoly)) {
Vector<float3> vertex_positions(src_mesh.totpoly);
for (const int i : IndexRange(src_mesh.totpoly)) {
const MPoly &poly = src_polys[i];
BKE_mesh_calc_poly_center(
&poly, &src_loops[poly.loopstart], src_verts.data(), vertex_positions[i]);
@ -702,9 +679,9 @@ static void calc_dual_mesh(GeometrySet &geometry_set,
Array<int> boundary_edge_midpoint_index;
if (keep_boundaries) {
/* Only initialize when we actually need it. */
boundary_edge_midpoint_index.reinitialize(mesh_in.totedge);
boundary_edge_midpoint_index.reinitialize(src_mesh.totedge);
/* We need to add vertices at the centers of boundary edges. */
for (const int i : IndexRange(mesh_in.totedge)) {
for (const int i : IndexRange(src_mesh.totedge)) {
if (edge_types[i] == EdgeType::Boundary) {
float3 mid;
const MEdge &edge = src_edges[i];
@ -729,7 +706,7 @@ static void calc_dual_mesh(GeometrySet &geometry_set,
* needs to be created or not. If it's not -1 it gives the index in `new_edges` of the dual
* edge. The edges coming from preserving the boundaries only get added once anyway, so we
* don't need a hash-map for that. */
Array<int> old_to_new_edges_map(mesh_in.totedge);
Array<int> old_to_new_edges_map(src_mesh.totedge);
old_to_new_edges_map.fill(-1);
/* This is necessary to prevent duplicate edges from being created, but will likely not do
@ -737,20 +714,20 @@ static void calc_dual_mesh(GeometrySet &geometry_set,
dissolve_redundant_verts(src_edges,
src_polys,
src_loops,
vertex_poly_indices,
vert_to_poly_map,
vertex_types,
old_to_new_edges_map,
new_edges,
new_to_old_edges_map);
for (const int i : IndexRange(mesh_in.totvert)) {
for (const int i : IndexRange(src_mesh.totvert)) {
if (vertex_types[i] == VertexType::Loose || vertex_types[i] >= VertexType::NonManifold ||
(!keep_boundaries && vertex_types[i] == VertexType::Boundary)) {
/* Bad vertex that we can't work with. */
continue;
}
Vector<int> loop_indices = vertex_poly_indices[i];
Vector<int> loop_indices = vert_to_poly_map[i];
Span<int> shared_edges = vertex_shared_edges[i];
Span<int> sorted_corners = vertex_corners[i];
if (vertex_types[i] == VertexType::Normal) {
@ -904,13 +881,13 @@ static void calc_dual_mesh(GeometrySet &geometry_set,
}
Mesh *mesh_out = BKE_mesh_new_nomain(
vertex_positions.size(), new_edges.size(), 0, loops.size(), loop_lengths.size());
transfer_attributes(attributes,
vertex_types,
transfer_attributes(vertex_types,
keep_boundaries,
new_to_old_edges_map,
new_to_old_face_corners_map,
boundary_vertex_to_relevant_face_map,
mesh_in.attributes(),
src_mesh.attributes(),
mesh_out->attributes_for_write());
MutableSpan<MVert> dst_verts = mesh_out->verts_for_write();
@ -932,7 +909,7 @@ static void calc_dual_mesh(GeometrySet &geometry_set,
copy_v3_v3(dst_verts[i].co, vertex_positions[i]);
}
dst_edges.copy_from(new_edges);
geometry_set.replace_mesh(mesh_out);
return mesh_out;
}
static void node_geo_exec(GeoNodeExecParams params)
@ -940,9 +917,9 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
const bool keep_boundaries = params.extract_input<bool>("Keep Boundaries");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (geometry_set.has_mesh()) {
const MeshComponent &component = *geometry_set.get_component_for_read<MeshComponent>();
calc_dual_mesh(geometry_set, component, keep_boundaries);
if (const Mesh *mesh = geometry_set.get_mesh_for_read()) {
Mesh *new_mesh = calc_dual_mesh(*mesh, keep_boundaries);
geometry_set.replace_mesh(new_mesh);
}
});
params.set_output("Dual Mesh", std::move(geometry_set));

View File

@ -255,7 +255,7 @@ int ConeConfig::calculate_total_corners()
return corner_total;
}
static void calculate_cone_verts(const MutableSpan<MVert> &verts, const ConeConfig &config)
static void calculate_cone_verts(const ConeConfig &config, MutableSpan<MVert> verts)
{
Array<float2> circle(config.circle_segments);
const float angle_delta = 2.0f * (M_PI / float(config.circle_segments));
@ -319,7 +319,7 @@ static void calculate_cone_verts(const MutableSpan<MVert> &verts, const ConeConf
}
}
static void calculate_cone_edges(const MutableSpan<MEdge> &edges, const ConeConfig &config)
static void calculate_cone_edges(const ConeConfig &config, MutableSpan<MEdge> edges)
{
int edge_index = 0;
@ -368,9 +368,9 @@ static void calculate_cone_edges(const MutableSpan<MEdge> &edges, const ConeConf
}
}
static void calculate_cone_faces(const MutableSpan<MLoop> &loops,
const MutableSpan<MPoly> &polys,
const ConeConfig &config)
static void calculate_cone_faces(const ConeConfig &config,
MutableSpan<MLoop> loops,
MutableSpan<MPoly> polys)
{
int loop_index = 0;
int poly_index = 0;
@ -474,12 +474,10 @@ static void calculate_cone_faces(const MutableSpan<MLoop> &loops,
}
}
static void calculate_selection_outputs(Mesh *mesh,
const ConeConfig &config,
ConeAttributeOutputs &attribute_outputs)
static void calculate_selection_outputs(const ConeConfig &config,
const ConeAttributeOutputs &attribute_outputs,
MutableAttributeAccessor attributes)
{
MutableAttributeAccessor attributes = mesh->attributes_for_write();
/* Populate "Top" selection output. */
if (attribute_outputs.top_id) {
const bool face = !config.top_is_point && config.fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE;
@ -691,11 +689,11 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
MutableSpan<MPoly> polys = mesh->polys_for_write();
MutableSpan<MLoop> loops = mesh->loops_for_write();
calculate_cone_verts(verts, config);
calculate_cone_edges(edges, config);
calculate_cone_faces(loops, polys, config);
calculate_cone_verts(config, verts);
calculate_cone_edges(config, edges);
calculate_cone_faces(config, loops, polys);
calculate_cone_uvs(mesh, config);
calculate_selection_outputs(mesh, config, attribute_outputs);
calculate_selection_outputs(config, attribute_outputs, mesh->attributes_for_write());
mesh->loose_edges_tag_none();

View File

@ -170,6 +170,13 @@ static void node_geo_exec(GeoNodeExecParams params)
Mesh *mesh_out = BKE_subdiv_to_mesh(subdiv, &mesh_settings, &mesh);
if (use_creases) {
/* Remove the layer in case it was created by the node from the field input. The fact
* that this node uses #CD_CREASE to input creases to the subvision code is meant to be
* an implementation detail ideally. */
CustomData_free_layers(&mesh_out->edata, CD_CREASE, mesh_out->totedge);
}
geometry_set.replace_mesh(mesh_out);
BKE_subdiv_free(subdiv);

View File

@ -674,15 +674,8 @@ static void get_ccgdm_data(DerivedMesh *lodm,
mpoly = lodm->getPolyArray(lodm) + poly_index;
g_index = grid_offset[poly_index];
S = mdisp_rot_face_to_crn(lodm->getVertArray(lodm),
mpoly,
lodm->getLoopArray(lodm),
lt,
face_side,
u * (face_side - 1),
v * (face_side - 1),
&crn_x,
&crn_y);
S = mdisp_rot_face_to_crn(
mpoly, face_side, u * (face_side - 1), v * (face_side - 1), &crn_x, &crn_y);
}
else {
/* number of faces per grid side */

View File

@ -117,9 +117,10 @@ void SEQ_transform_translate_sequence(Scene *evil_scene, Sequence *seq, int delt
return;
}
/* Meta strips requires special handling: their content is to be translated, and then frame range
* of the meta is to be updated for the updated content. */
if (seq->type == SEQ_TYPE_META) {
/* Meta strips requires their content is to be translated, and then frame range of the meta is
* updated based on nested strips. Thiw won't work for empty metas, so they can be treated as
* normal strip. */
if (seq->type == SEQ_TYPE_META && !BLI_listbase_is_empty(&seq->seqbase)) {
Sequence *seq_child;
for (seq_child = seq->seqbase.first; seq_child; seq_child = seq_child->next) {
SEQ_transform_translate_sequence(evil_scene, seq_child, delta);