Geometry Nodes: new repeat zone #109164
|
@ -122,5 +122,6 @@ if(BUILD_MODE STREQUAL Release AND WIN32)
|
|||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/lld.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/lld-link.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${HARVEST_TARGET}/dpcpp/bin/wasm-ld.exe
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -46,7 +46,7 @@ ${temp_LIBDIR}/vpx/lib/pkgconfig:\
|
|||
${temp_LIBDIR}/theora/lib/pkgconfig:\
|
||||
${temp_LIBDIR}/openjpeg/lib/pkgconfig:\
|
||||
${temp_LIBDIR}/opus/lib/pkgconfig:\
|
||||
${temp_LIBDIR}/aom/lib/pkgconfig"
|
||||
${temp_LIBDIR}/aom/lib/pkgconfig:"
|
||||
)
|
||||
|
||||
unset(temp_LIBDIR)
|
||||
|
|
|
@ -2,35 +2,45 @@
|
|||
|
||||
set(FFTW_EXTRA_ARGS)
|
||||
|
||||
if(WIN32)
|
||||
set(FFTW3_PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/fftw3/src/external_fftw3 < ${PATCH_DIR}/fftw3.diff)
|
||||
set(FFTW_EXTRA_ARGS --disable-static --enable-shared)
|
||||
set(FFTW_INSTALL install-strip)
|
||||
else()
|
||||
set(FFTW_EXTRA_ARGS --enable-static)
|
||||
set(FFTW_INSTALL install)
|
||||
endif()
|
||||
macro(fftw_build FFTW_POSTFIX)
|
||||
if(WIN32)
|
||||
set(FFTW3_PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/fftw3/src/external_fftw3_${FFTW_POSTFIX} < ${PATCH_DIR}/fftw3.diff)
|
||||
set(FFTW_EXTRA_ARGS --disable-static --enable-shared)
|
||||
set(FFTW_INSTALL install-strip)
|
||||
else()
|
||||
set(FFTW_EXTRA_ARGS --enable-static)
|
||||
set(FFTW_INSTALL install)
|
||||
endif()
|
||||
ExternalProject_Add(external_fftw3_${FFTW_POSTFIX}
|
||||
URL file://${PACKAGE_DIR}/${FFTW_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${FFTW_HASH_TYPE}=${FFTW_HASH}
|
||||
PREFIX ${BUILD_DIR}/fftw3
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3_${FFTW_POSTFIX}/ && ${CONFIGURE_COMMAND} ${FFTW_EXTRA_ARGS} ${ARGN} --prefix=${mingw_LIBDIR}/fftw3
|
||||
PATCH_COMMAND ${FFTW3_PATCH_COMMAND}
|
||||
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3_${FFTW_POSTFIX}/ && make -j${MAKE_THREADS}
|
||||
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3_${FFTW_POSTFIX}/ && make ${FFTW_INSTALL}
|
||||
INSTALL_DIR ${LIBDIR}/fftw3
|
||||
)
|
||||
endmacro()
|
||||
|
||||
ExternalProject_Add(external_fftw3
|
||||
URL file://${PACKAGE_DIR}/${FFTW_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${FFTW_HASH_TYPE}=${FFTW_HASH}
|
||||
PREFIX ${BUILD_DIR}/fftw3
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && ${CONFIGURE_COMMAND} ${FFTW_EXTRA_ARGS} --prefix=${mingw_LIBDIR}/fftw3
|
||||
PATCH_COMMAND ${FFTW3_PATCH_COMMAND}
|
||||
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && make -j${MAKE_THREADS}
|
||||
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && make ${FFTW_INSTALL}
|
||||
INSTALL_DIR ${LIBDIR}/fftw3
|
||||
)
|
||||
fftw_build(double)
|
||||
fftw_build(float --enable-float)
|
||||
|
||||
if(MSVC)
|
||||
set_target_properties(external_fftw3 PROPERTIES FOLDER Mingw)
|
||||
set_target_properties(external_fftw3_double PROPERTIES FOLDER Mingw)
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_fftw3 after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/lib/libfftw3.dll.a ${HARVEST_TARGET}/fftw3/lib/libfftw.lib
|
||||
ExternalProject_Add_Step(external_fftw3_double after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/lib/libfftw3.dll.a ${HARVEST_TARGET}/fftw3/lib/libfftw3-3.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/bin/libfftw3-3.dll ${HARVEST_TARGET}/fftw3/lib/libfftw3-3.dll
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/include/fftw3.h ${HARVEST_TARGET}/fftw3/include/fftw3.h
|
||||
DEPENDEES install
|
||||
)
|
||||
ExternalProject_Add_Step(external_fftw3_float after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/lib/libfftw3f.dll.a ${HARVEST_TARGET}/fftw3/lib/libfftw3f.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/bin/libfftw3f-3.dll ${HARVEST_TARGET}/fftw3/lib/libfftw3f-3.dll
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
|
|
@ -218,7 +218,7 @@ else()
|
|||
harvest(openimagedenoise/lib openimagedenoise/lib "*.a")
|
||||
harvest(embree/include embree/include "*.h")
|
||||
harvest(embree/lib embree/lib "*.a")
|
||||
harvest(embree/lib embree/lib "*${SHAREDLIBEXT}*")
|
||||
harvest_rpath_lib(embree/lib embree/lib "*${SHAREDLIBEXT}*")
|
||||
harvest(openpgl/include openpgl/include "*.h")
|
||||
harvest(openpgl/lib openpgl/lib "*.a")
|
||||
harvest(openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION} openpgl/lib/cmake/openpgl "*.cmake")
|
||||
|
|
|
@ -11,7 +11,7 @@ if(WIN32)
|
|||
elseif(APPLE)
|
||||
# Use bison and flex installed via Homebrew.
|
||||
# The ones that come with Xcode toolset are too old.
|
||||
if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "arm64")
|
||||
if(BLENDER_PLATFORM_ARM)
|
||||
set(ISPC_EXTRA_ARGS_APPLE
|
||||
-DBISON_EXECUTABLE=/opt/homebrew/opt/bison/bin/bison
|
||||
-DFLEX_EXECUTABLE=/opt/homebrew/opt/flex/bin/flex
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
set(MATERIALX_EXTRA_ARGS
|
||||
-DMATERIALX_BUILD_PYTHON=ON
|
||||
-DMATERIALX_BUILD_RENDER=OFF
|
||||
-DMATERIALX_BUILD_RENDER=ON
|
||||
-DMATERIALX_INSTALL_PYTHON=OFF
|
||||
-DMATERIALX_PYTHON_EXECUTABLE=${PYTHON_BINARY}
|
||||
-DMATERIALX_PYTHON_VERSION=${PYTHON_SHORT_VERSION}
|
||||
-DMATERIALX_BUILD_SHARED_LIBS=ON
|
||||
-DMATERIALX_BUILD_TESTS=OFF
|
||||
-DCMAKE_DEBUG_POSTFIX=_d
|
||||
-Dpybind11_ROOT=${LIBDIR}/pybind11
|
||||
-DPython_EXECUTABLE=${PYTHON_BINARY}
|
||||
|
|
|
@ -27,6 +27,7 @@ ExternalProject_Add(external_openexr
|
|||
URL file://${PACKAGE_DIR}/${OPENEXR_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${OPENEXR_HASH_TYPE}=${OPENEXR_HASH}
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openexr/src/external_openexr < ${PATCH_DIR}/openexr_b18905772e.diff
|
||||
CMAKE_GENERATOR ${PLATFORM_ALT_GENERATOR}
|
||||
PREFIX ${BUILD_DIR}/openexr
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openexr ${DEFAULT_CMAKE_FLAGS} ${OPENEXR_EXTRA_ARGS}
|
||||
|
|
|
@ -54,7 +54,7 @@ set(OPENIMAGEIO_EXTRA_ARGS
|
|||
-DUSE_DCMTK=OFF
|
||||
-DUSE_LIBHEIF=OFF
|
||||
-DUSE_OPENGL=OFF
|
||||
-DUSE_TBB=OFF
|
||||
-DUSE_TBB=ON
|
||||
-DUSE_QT=OFF
|
||||
-DUSE_PYTHON=ON
|
||||
-DUSE_GIF=OFF
|
||||
|
@ -96,6 +96,7 @@ set(OPENIMAGEIO_EXTRA_ARGS
|
|||
-DImath_ROOT=${LIBDIR}/imath
|
||||
-Dpybind11_ROOT=${LIBDIR}/pybind11
|
||||
-DPython_EXECUTABLE=${PYTHON_BINARY}
|
||||
-DTBB_ROOT=${LIBDIR}/tbb
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_openimageio
|
||||
|
@ -104,7 +105,8 @@ ExternalProject_Add(external_openimageio
|
|||
URL_HASH ${OPENIMAGEIO_HASH_TYPE}=${OPENIMAGEIO_HASH}
|
||||
CMAKE_GENERATOR ${PLATFORM_ALT_GENERATOR}
|
||||
PREFIX ${BUILD_DIR}/openimageio
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio.diff
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio.diff &&
|
||||
${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/oiio_3832.diff
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openimageio ${DEFAULT_CMAKE_FLAGS} ${OPENIMAGEIO_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/openimageio
|
||||
)
|
||||
|
@ -125,6 +127,7 @@ add_dependencies(
|
|||
external_webp
|
||||
external_python
|
||||
external_pybind11
|
||||
external_tbb
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
|
|
@ -35,7 +35,7 @@ if(WIN32)
|
|||
# regardless of the version actually in there.
|
||||
PATCH_COMMAND mkdir ${PYTHON_EXTERNALS_FOLDER_DOS} &&
|
||||
mklink /J ${PYTHON_EXTERNALS_FOLDER_DOS}\\zlib-1.2.13 ${ZLIB_SOURCE_FOLDER_DOS} &&
|
||||
mklink /J ${PYTHON_EXTERNALS_FOLDER_DOS}\\openssl-1.1.1q ${SSL_SOURCE_FOLDER_DOS} &&
|
||||
mklink /J ${PYTHON_EXTERNALS_FOLDER_DOS}\\openssl-1.1.1t ${SSL_SOURCE_FOLDER_DOS} &&
|
||||
${CMAKE_COMMAND} -E copy ${ZLIB_SOURCE_FOLDER}/../external_zlib-build/zconf.h ${PYTHON_EXTERNALS_FOLDER}/zlib-1.2.13/zconf.h &&
|
||||
${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_windows.diff
|
||||
CONFIGURE_COMMAND echo "."
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(SSL_CONFIGURE_COMMAND ./Configure)
|
||||
set(SSL_PATCH_CMD echo .)
|
||||
|
||||
if(WIN32)
|
||||
# Python will build this with its preferred build options and patches. We only need to unpack openssl
|
||||
|
@ -18,7 +17,6 @@ if(WIN32)
|
|||
else()
|
||||
if(APPLE)
|
||||
set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}")
|
||||
set(SSL_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/ssl/src/external_ssl < ${PATCH_DIR}/ssl.diff)
|
||||
else()
|
||||
if(BLENDER_PLATFORM_ARM)
|
||||
set(SSL_OS_COMPILER "blender-linux-aarch64")
|
||||
|
@ -35,7 +33,6 @@ else()
|
|||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${SSL_HASH_TYPE}=${SSL_HASH}
|
||||
PREFIX ${BUILD_DIR}/ssl
|
||||
PATCH_COMMAND ${SSL_PATCH_CMD}
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/ssl/src/external_ssl/ && ${SSL_CONFIGURE_COMMAND} --prefix=${LIBDIR}/ssl
|
||||
--openssldir=${LIBDIR}/ssl
|
||||
no-shared
|
||||
|
|
|
@ -15,8 +15,7 @@ if(WIN32)
|
|||
-D_PXR_CXX_DEFINITIONS=/DBOOST_ALL_NO_LIB
|
||||
-DCMAKE_SHARED_LINKER_FLAGS_INIT=/LIBPATH:${LIBDIR}/tbb/lib
|
||||
-DPython_FIND_REGISTRY=NEVER
|
||||
-DPYTHON_INCLUDE_DIRS=${LIBDIR}/python/include
|
||||
-DPYTHON_LIBRARY=${LIBDIR}/python/libs/python${PYTHON_SHORT_VERSION_NO_DOTS}${PYTHON_POSTFIX}${LIBEXT}
|
||||
-DPython3_EXECUTABLE=${PYTHON_BINARY}
|
||||
)
|
||||
if(BUILD_MODE STREQUAL Debug)
|
||||
list(APPEND USD_PLATFORM_FLAGS -DPXR_USE_DEBUG_PYTHON=ON)
|
||||
|
@ -27,6 +26,12 @@ elseif(UNIX)
|
|||
# part of the interpret in the USD library. Allow undefined Python symbols and replace
|
||||
# Python library with TBB so it doesn't complain about missing library.
|
||||
set(USD_PLATFORM_FLAGS
|
||||
# NOTE(@ideasman42): Setting the root is needed, without this an older version of Python
|
||||
# is detected from the system. Referencing the root-directory may remove the need
|
||||
# to explicitly set the `PYTHON_INCLUDE_DIR` & `PYTHON_LIBRARY`.
|
||||
# Keep them as it's known these are the libraries to use and it avoids any ambiguity.
|
||||
-DPython3_ROOT_DIR=${LIBDIR}/python/
|
||||
|
||||
-DPYTHON_INCLUDE_DIR=${LIBDIR}/python/include/python${PYTHON_SHORT_VERSION}/
|
||||
-DPYTHON_LIBRARY=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${SHAREDLIBEXT}
|
||||
)
|
||||
|
@ -44,6 +49,7 @@ set(USD_EXTRA_ARGS
|
|||
${USD_PLATFORM_FLAGS}
|
||||
-DOPENSUBDIV_ROOT_DIR=${LIBDIR}/opensubdiv
|
||||
-DOpenImageIO_ROOT=${LIBDIR}/openimageio
|
||||
-DMaterialX_ROOT=${LIBDIR}/materialx
|
||||
-DOPENEXR_LIBRARIES=${LIBDIR}/imath/lib/${LIBPREFIX}Imath${OPENEXR_VERSION_POSTFIX}${SHAREDLIBEXT}
|
||||
-DOPENEXR_INCLUDE_DIR=${LIBDIR}/imath/include
|
||||
-DImath_DIR=${LIBDIR}/imath
|
||||
|
@ -56,9 +62,10 @@ set(USD_EXTRA_ARGS
|
|||
-DPXR_BUILD_TUTORIALS=OFF
|
||||
-DPXR_BUILD_USDVIEW=OFF
|
||||
-DPXR_ENABLE_HDF5_SUPPORT=OFF
|
||||
-DPXR_ENABLE_MATERIALX_SUPPORT=OFF
|
||||
-DPXR_ENABLE_MATERIALX_SUPPORT=ON
|
||||
-DPXR_ENABLE_OPENVDB_SUPPORT=ON
|
||||
-DPYTHON_EXECUTABLE=${PYTHON_BINARY}
|
||||
-DPython3_EXECUTABLE=${PYTHON_BINARY}
|
||||
-DPXR_BUILD_MONOLITHIC=ON
|
||||
# OSL is an optional dependency of the Imaging module. However, since that
|
||||
# module was included for its support for converting primitive shapes (sphere,
|
||||
|
@ -95,7 +102,12 @@ ExternalProject_Add(external_usd
|
|||
CMAKE_GENERATOR ${PLATFORM_ALT_GENERATOR}
|
||||
PREFIX ${BUILD_DIR}/usd
|
||||
LIST_SEPARATOR ^^
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/usd/src/external_usd < ${PATCH_DIR}/usd.diff
|
||||
# usd_pull_1965.diff https://github.com/PixarAnimationStudios/USD/pull/1965
|
||||
# usd_hydra.diff - https://github.com/bnagirniak/RPRHydraRenderBlenderAddon/blob/master/usd.diff
|
||||
# usd_hydra.diff also included the blender changes and usd_pull_1965 and has been edited to remove those sections.
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/usd/src/external_usd < ${PATCH_DIR}/usd.diff &&
|
||||
${PATCH_CMD} -p 1 -d ${BUILD_DIR}/usd/src/external_usd < ${PATCH_DIR}/usd_pull_1965.diff &&
|
||||
${PATCH_CMD} -p 1 -d ${BUILD_DIR}/usd/src/external_usd < ${PATCH_DIR}/usd_hydra.diff
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/usd -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${USD_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/usd
|
||||
)
|
||||
|
@ -107,6 +119,7 @@ add_dependencies(
|
|||
external_opensubdiv
|
||||
external_python
|
||||
external_openimageio
|
||||
external_materialx
|
||||
openvdb
|
||||
)
|
||||
|
||||
|
|
|
@ -58,16 +58,16 @@ set(PTHREADS_HASH f3bf81bb395840b3446197bcf4ecd653)
|
|||
set(PTHREADS_HASH_TYPE MD5)
|
||||
set(PTHREADS_FILE pthreads4w-code-${PTHREADS_VERSION}.zip)
|
||||
|
||||
set(OPENEXR_VERSION 3.1.5)
|
||||
set(OPENEXR_VERSION 3.1.7)
|
||||
set(OPENEXR_URI https://github.com/AcademySoftwareFoundation/openexr/archive/v${OPENEXR_VERSION}.tar.gz)
|
||||
set(OPENEXR_HASH a92f38eedd43e56c0af56d4852506886)
|
||||
set(OPENEXR_HASH ae68f0cb8b30a49c961fa87d31c60394)
|
||||
set(OPENEXR_HASH_TYPE MD5)
|
||||
set(OPENEXR_FILE openexr-${OPENEXR_VERSION}.tar.gz)
|
||||
set(OPENEXR_CPE "cpe:2.3:a:openexr:openexr:${OPENEXR_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(IMATH_VERSION 3.1.5)
|
||||
set(IMATH_VERSION 3.1.7)
|
||||
set(IMATH_URI https://github.com/AcademySoftwareFoundation/Imath/archive/v${OPENEXR_VERSION}.tar.gz)
|
||||
set(IMATH_HASH dd375574276c54872b7b3d54053baff0)
|
||||
set(IMATH_HASH 5cedab446ab296c080957c3037c6d097)
|
||||
set(IMATH_HASH_TYPE MD5)
|
||||
set(IMATH_FILE imath-${IMATH_VERSION}.tar.gz)
|
||||
|
||||
|
@ -88,9 +88,9 @@ else()
|
|||
set(OPENEXR_VERSION_POSTFIX)
|
||||
endif()
|
||||
|
||||
set(FREETYPE_VERSION 2.12.1)
|
||||
set(FREETYPE_VERSION 2.13.0)
|
||||
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
|
||||
set(FREETYPE_HASH 8bc5c9c9df7ac12c504f8918552a7cf2)
|
||||
set(FREETYPE_HASH 98bc3cf234fe88ef3cf24569251fe0a4)
|
||||
set(FREETYPE_HASH_TYPE MD5)
|
||||
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
|
||||
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
@ -112,7 +112,6 @@ set(ALEMBIC_URI https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.ta
|
|||
set(ALEMBIC_HASH 2cd8d6e5a3ac4a014e24a4b04f4fadf9)
|
||||
set(ALEMBIC_HASH_TYPE MD5)
|
||||
set(ALEMBIC_FILE alembic-${ALEMBIC_VERSION}.tar.gz)
|
||||
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPENSUBDIV_VERSION v3_5_0)
|
||||
set(OPENSUBDIV_URI https://github.com/PixarAnimationStudios/OpenSubdiv/archive/${OPENSUBDIV_VERSION}.tar.gz)
|
||||
|
@ -165,17 +164,17 @@ set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${
|
|||
set(OPENMP_HASH_TYPE MD5)
|
||||
set(OPENMP_FILE openmp-${OPENMP_VERSION}.src.tar.xz)
|
||||
|
||||
set(OPENIMAGEIO_VERSION v2.4.9.0)
|
||||
set(OPENIMAGEIO_VERSION v2.4.11.0)
|
||||
set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/refs/tags/${OPENIMAGEIO_VERSION}.tar.gz)
|
||||
set(OPENIMAGEIO_HASH 7da92a7d6029921a8599a977ff1efa2a)
|
||||
set(OPENIMAGEIO_HASH 7eb997479ecfe7d9fa59cc8ddd35d0ae)
|
||||
set(OPENIMAGEIO_HASH_TYPE MD5)
|
||||
set(OPENIMAGEIO_FILE OpenImageIO-${OPENIMAGEIO_VERSION}.tar.gz)
|
||||
|
||||
# 8.0.0 is currently oiio's preferred version although never versions may be available.
|
||||
# 9.1.0 is currently oiio's preferred version although never versions may be available.
|
||||
# the preferred version can be found in oiio's externalpackages.cmake
|
||||
set(FMT_VERSION 8.0.0)
|
||||
set(FMT_VERSION 9.1.0)
|
||||
set(FMT_URI https://github.com/fmtlib/fmt/archive/refs/tags/${FMT_VERSION}.tar.gz)
|
||||
set(FMT_HASH 7bce0e9e022e586b178b150002e7c2339994e3c2bbe44027e9abb0d60f9cce83)
|
||||
set(FMT_HASH 5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2)
|
||||
set(FMT_HASH_TYPE SHA256)
|
||||
set(FMT_FILE fmt-${FMT_VERSION}.tar.gz)
|
||||
set(FMT_CPE "cpe:2.3:a:fmt:fmt:${FMT_VERSION}:*:*:*:*:*:*:*")
|
||||
|
@ -209,11 +208,11 @@ set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
|
|||
# BZIP2, FFI, SQLITE and change the versions in this file as well. For compliance
|
||||
# reasons there can be no exceptions to this.
|
||||
|
||||
set(PYTHON_VERSION 3.10.9)
|
||||
set(PYTHON_VERSION 3.10.11)
|
||||
set(PYTHON_SHORT_VERSION 3.10)
|
||||
set(PYTHON_SHORT_VERSION_NO_DOTS 310)
|
||||
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
|
||||
set(PYTHON_HASH dc8c0f274b28ee9e95923d20cfc364c9)
|
||||
set(PYTHON_HASH 1bf8481a683e0881e14d52e0f23633a6)
|
||||
set(PYTHON_HASH_TYPE MD5)
|
||||
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
|
||||
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")
|
||||
|
@ -296,9 +295,9 @@ set(THEORA_HASH b6ae1ee2fa3d42ac489287d3ec34c5885730b1296f0801ae577a35193d3affbc
|
|||
set(THEORA_HASH_TYPE SHA256)
|
||||
set(THEORA_FILE libtheora-${THEORA_VERSION}.tar.bz2)
|
||||
|
||||
set(FLAC_VERSION 1.3.4)
|
||||
set(FLAC_VERSION 1.4.2)
|
||||
set(FLAC_URI http://downloads.xiph.org/releases/flac/flac-${FLAC_VERSION}.tar.xz)
|
||||
set(FLAC_HASH 8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737 )
|
||||
set(FLAC_HASH e322d58a1f48d23d9dd38f432672865f6f79e73a6f9cc5a5f57fcaa83eb5a8e4 )
|
||||
set(FLAC_HASH_TYPE SHA256)
|
||||
set(FLAC_FILE flac-${FLAC_VERSION}.tar.xz)
|
||||
set(FLAC_CPE "cpe:2.3:a:flac_project:flac:${FLAC_VERSION}:*:*:*:*:*:*:*")
|
||||
|
@ -336,9 +335,9 @@ set(OPENJPEG_HASH_TYPE SHA256)
|
|||
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
|
||||
set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(FFMPEG_VERSION 5.1.2)
|
||||
set(FFMPEG_VERSION 6.0)
|
||||
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||
set(FFMPEG_HASH 39a0bcc8d98549f16c570624678246a6ac736c066cebdb409f9502e915b22f2b)
|
||||
set(FFMPEG_HASH 47d062731c9f66a78380e35a19aac77cebceccd1c7cc309b9c82343ffc430c3d)
|
||||
set(FFMPEG_HASH_TYPE SHA256)
|
||||
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||
set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*")
|
||||
|
@ -460,9 +459,9 @@ set(LZMA_HASH_TYPE SHA256)
|
|||
set(LZMA_FILE xz-${LZMA_VERSION}.tar.bz2)
|
||||
|
||||
# NOTE: Python's build has been modified to use our ssl version.
|
||||
set(SSL_VERSION 1.1.1q)
|
||||
set(SSL_VERSION 1.1.1t)
|
||||
set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
|
||||
set(SSL_HASH d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca)
|
||||
set(SSL_HASH 8dee9b24bdb1dcbf0c3d1e9b02fb8f6bf22165e807f45adeb7c9677536859d3b)
|
||||
set(SSL_HASH_TYPE SHA256)
|
||||
set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
|
||||
set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
|
||||
|
@ -470,10 +469,10 @@ set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
|
|||
# Note: This will *HAVE* to match the version python ships on windows which
|
||||
# is hardcoded in pythons PCbuild/get_externals.bat for compliance reasons there
|
||||
# can be no exceptions to this.
|
||||
set(SQLITE_VERSION 3.39.4)
|
||||
set(SQLLITE_LONG_VERSION 3390400)
|
||||
set(SQLITE_VERSION 3.40.1)
|
||||
set(SQLLITE_LONG_VERSION 3400100)
|
||||
set(SQLITE_URI https://www.sqlite.org/2022/sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
|
||||
set(SQLITE_HASH c4c5c39269d1b9bb1487cff580c1f583608229b2)
|
||||
set(SQLITE_HASH b8c2d4bc0094f5c0ce985dc0e237dfcbaa1f6275)
|
||||
set(SQLITE_HASH_TYPE SHA1)
|
||||
set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
|
||||
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
@ -484,9 +483,9 @@ set(EMBREE_HASH dd26617719a587e126b341d1b32f7fd0)
|
|||
set(EMBREE_HASH_TYPE MD5)
|
||||
set(EMBREE_FILE embree-v${EMBREE_VERSION}.zip)
|
||||
|
||||
set(USD_VERSION 22.11)
|
||||
set(USD_VERSION 23.05)
|
||||
set(USD_URI https://github.com/PixarAnimationStudios/USD/archive/v${USD_VERSION}.tar.gz)
|
||||
set(USD_HASH 8c89459e48a2ef0e7ae9e7e490377507)
|
||||
set(USD_HASH 56684f4fdd1a9209dabf03856be5eca6)
|
||||
set(USD_HASH_TYPE MD5)
|
||||
set(USD_FILE usd-v${USD_VERSION}.tar.gz)
|
||||
|
||||
|
|
|
@ -9,77 +9,3 @@
|
|||
enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++"
|
||||
enabled libopus && {
|
||||
enabled libopus_decoder && {
|
||||
--- a/libavcodec/cfhddata.c
|
||||
+++ b/libavcodec/cfhddata.c
|
||||
@@ -276,10 +276,10 @@
|
||||
av_cold int ff_cfhd_init_vlcs(CFHDContext *s)
|
||||
{
|
||||
int i, j, ret = 0;
|
||||
- uint32_t new_cfhd_vlc_bits[NB_VLC_TABLE_18 * 2];
|
||||
- uint8_t new_cfhd_vlc_len[NB_VLC_TABLE_18 * 2];
|
||||
- uint16_t new_cfhd_vlc_run[NB_VLC_TABLE_18 * 2];
|
||||
- int16_t new_cfhd_vlc_level[NB_VLC_TABLE_18 * 2];
|
||||
+ uint32_t *new_cfhd_vlc_bits = av_calloc(sizeof(uint32_t), NB_VLC_TABLE_18 * 2);
|
||||
+ uint8_t *new_cfhd_vlc_len = av_calloc(sizeof(uint8_t), NB_VLC_TABLE_18 * 2);
|
||||
+ uint16_t *new_cfhd_vlc_run = av_calloc(sizeof(uint16_t), NB_VLC_TABLE_18 * 2);
|
||||
+ int16_t *new_cfhd_vlc_level = av_calloc(sizeof(int16_t), NB_VLC_TABLE_18 * 2);
|
||||
|
||||
/** Similar to dv.c, generate signed VLC tables **/
|
||||
|
||||
@@ -305,8 +305,13 @@
|
||||
|
||||
ret = init_vlc(&s->vlc_9, VLC_BITS, j, new_cfhd_vlc_len,
|
||||
1, 1, new_cfhd_vlc_bits, 4, 4, 0);
|
||||
- if (ret < 0)
|
||||
+ if (ret < 0) {
|
||||
+ av_free(new_cfhd_vlc_bits);
|
||||
+ av_free(new_cfhd_vlc_len);
|
||||
+ av_free(new_cfhd_vlc_run);
|
||||
+ av_free(new_cfhd_vlc_level);
|
||||
return ret;
|
||||
+ }
|
||||
for (i = 0; i < s->vlc_9.table_size; i++) {
|
||||
int code = s->vlc_9.table[i][0];
|
||||
int len = s->vlc_9.table[i][1];
|
||||
@@ -346,8 +351,14 @@
|
||||
|
||||
ret = init_vlc(&s->vlc_18, VLC_BITS, j, new_cfhd_vlc_len,
|
||||
1, 1, new_cfhd_vlc_bits, 4, 4, 0);
|
||||
- if (ret < 0)
|
||||
+ if (ret < 0) {
|
||||
+ av_free(new_cfhd_vlc_bits);
|
||||
+ av_free(new_cfhd_vlc_len);
|
||||
+ av_free(new_cfhd_vlc_run);
|
||||
+ av_free(new_cfhd_vlc_level);
|
||||
return ret;
|
||||
+ }
|
||||
+
|
||||
av_assert0(s->vlc_18.table_size == 4572);
|
||||
|
||||
for (i = 0; i < s->vlc_18.table_size; i++) {
|
||||
@@ -367,5 +378,10 @@
|
||||
s->table_18_rl_vlc[i].run = run;
|
||||
}
|
||||
|
||||
+ av_free(new_cfhd_vlc_bits);
|
||||
+ av_free(new_cfhd_vlc_len);
|
||||
+ av_free(new_cfhd_vlc_run);
|
||||
+ av_free(new_cfhd_vlc_level);
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
diff --git a/libavcodec/x86/simple_idct.asm b/libavcodec/x86/simple_idct.asm
|
||||
index dcf0da6df121..982b2f0bbba1 100644
|
||||
--- a/libavcodec/x86/simple_idct.asm
|
||||
+++ b/libavcodec/x86/simple_idct.asm
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
%include "libavutil/x86/x86util.asm"
|
||||
|
||||
-%if ARCH_X86_32
|
||||
SECTION_RODATA
|
||||
|
||||
+%if ARCH_X86_32
|
||||
cextern pb_80
|
||||
|
||||
wm1010: dw 0, 0xffff, 0, 0xffff
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
diff --git a/src/python/py_oiio.cpp b/src/python/py_oiio.cpp
|
||||
index 6031d2c23..e71105da5 100644
|
||||
--- a/src/python/py_oiio.cpp
|
||||
+++ b/src/python/py_oiio.cpp
|
||||
@@ -153,7 +153,7 @@ oiio_bufinfo::oiio_bufinfo(const py::buffer_info& pybuf, int nchans, int width,
|
||||
format = TypeUnknown; // No idea what's going on -- error
|
||||
error = Strutil::fmt::format(
|
||||
"Python array shape is [{:,}] but expecting h={}, w={}, ch={}",
|
||||
- cspan<ssize_t>(pybuf.shape), height, width, nchans);
|
||||
+ cspan<py::ssize_t>(pybuf.shape), height, width, nchans);
|
||||
}
|
||||
} else if (pixeldims == 1) {
|
||||
// Reading a 1D scanline span
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,37 @@
|
|||
diff --git a/pxr/usd/usdMtlx/reader.cpp b/pxr/usd/usdMtlx/reader.cpp
|
||||
index 29e901816..e6fc68b20 100644
|
||||
--- a/pxr/usd/usdMtlx/reader.cpp
|
||||
+++ b/pxr/usd/usdMtlx/reader.cpp
|
||||
@@ -797,6 +797,15 @@ _NodeGraphBuilder::_CreateInterfaceInputs(
|
||||
// We deliberately ignore tokens here.
|
||||
}
|
||||
|
||||
+mx::StringSet _GetStdlibIncludes() {
|
||||
+ mx::StringSet stdlibIncludes = UsdMtlxGetDocument("")->getReferencedSourceUris();
|
||||
+ mx::StringSet normStdlibIncludes;
|
||||
+ for (std::string const& entry : stdlibIncludes) {
|
||||
+ normStdlibIncludes.insert(TfNormPath(entry));
|
||||
+ }
|
||||
+ return normStdlibIncludes;
|
||||
+}
|
||||
+
|
||||
// Returns True if the mtlxNodeDef corresponds to a locally defined custom node
|
||||
// with an associated nodegraph.
|
||||
// XXX Locally defined custom nodes without nodegraphs are not supported
|
||||
@@ -818,13 +827,14 @@ _NodeGraphBuilder::_IsLocalCustomNode(const mx::ConstNodeDefPtr &mtlxNodeDef)
|
||||
}
|
||||
// Combine with the nodeDef relative path
|
||||
nodeDefUri = TfNormPath(fullMtlxPath + nodeDefUri);
|
||||
+ } else {
|
||||
+ nodeDefUri = TfNormPath(nodeDefUri);
|
||||
}
|
||||
|
||||
// This is a locally defined custom node if the absolute path to the
|
||||
// nodedef is not included in the stdlibDoc.
|
||||
static mx::StringSet customNodeDefNames;
|
||||
- static const mx::StringSet stdlibIncludes =
|
||||
- UsdMtlxGetDocument("")->getReferencedSourceUris();
|
||||
+ static const mx::StringSet stdlibIncludes = _GetStdlibIncludes();
|
||||
if (stdlibIncludes.find(nodeDefUri) == stdlibIncludes.end()) {
|
||||
// Check if we already used this custom node
|
||||
if (std::find(customNodeDefNames.begin(), customNodeDefNames.end(),
|
|
@ -0,0 +1,106 @@
|
|||
diff --git a/build_scripts/build_usd.py b/build_scripts/build_usd.py
|
||||
index cfe243effb..a4bb94eee1 100644
|
||||
--- a/build_scripts/build_usd.py
|
||||
+++ b/build_scripts/build_usd.py
|
||||
@@ -1415,7 +1415,7 @@ def InstallDraco(context, force, buildArgs):
|
||||
############################################################
|
||||
# MaterialX
|
||||
|
||||
-MATERIALX_URL = "https://github.com/materialx/MaterialX/archive/v1.38.4.zip"
|
||||
+MATERIALX_URL = "https://github.com/materialx/MaterialX/archive/v1.38.5.zip"
|
||||
|
||||
def InstallMaterialX(context, force, buildArgs):
|
||||
with CurrentWorkingDirectory(DownloadURL(MATERIALX_URL, context, force)):
|
||||
diff --git a/pxr/imaging/hdSt/materialXShaderGen.cpp b/pxr/imaging/hdSt/materialXShaderGen.cpp
|
||||
index df80ff119f..e4b5f04a73 100644
|
||||
--- a/pxr/imaging/hdSt/materialXShaderGen.cpp
|
||||
+++ b/pxr/imaging/hdSt/materialXShaderGen.cpp
|
||||
@@ -136,8 +136,7 @@ HdStMaterialXShaderGen::HdStMaterialXShaderGen(
|
||||
"st" : mxHdInfo.defaultTexcoordName;
|
||||
|
||||
// Register the customized version of the Surface node generator
|
||||
- registerImplementation("IM_surface_" + GlslShaderGenerator::TARGET,
|
||||
- HdStMaterialXSurfaceNodeGen::create);
|
||||
+ registerImplementation("IM_surface_genglsl", HdStMaterialXSurfaceNodeGen::create);
|
||||
}
|
||||
|
||||
// Based on GlslShaderGenerator::generate()
|
||||
@@ -273,8 +272,7 @@ HdStMaterialXShaderGen::_EmitMxFunctions(
|
||||
mx::ShaderStage& mxStage) const
|
||||
{
|
||||
// Add global constants and type definitions
|
||||
- emitLibraryInclude("stdlib/" + mx::GlslShaderGenerator::TARGET
|
||||
- + "/lib/mx_math.glsl", mxContext, mxStage);
|
||||
+ emitLibraryInclude("stdlib/genglsl/lib/mx_math.glsl", mxContext, mxStage);
|
||||
emitLine("#if NUM_LIGHTS > 0", mxStage, false);
|
||||
emitLine("#define MAX_LIGHT_SOURCES NUM_LIGHTS", mxStage, false);
|
||||
emitLine("#else", mxStage, false);
|
||||
@@ -394,16 +392,24 @@ HdStMaterialXShaderGen::_EmitMxFunctions(
|
||||
emitSpecularEnvironment(mxContext, mxStage);
|
||||
}
|
||||
if (shadowing) {
|
||||
- emitLibraryInclude("pbrlib/" + mx::GlslShaderGenerator::TARGET
|
||||
- + "/lib/mx_shadow.glsl", mxContext, mxStage);
|
||||
+ emitLibraryInclude("pbrlib/genglsl/lib/mx_shadow.glsl", mxContext, mxStage);
|
||||
}
|
||||
|
||||
+#if MATERIALX_MAJOR_VERSION > 1 || \
|
||||
+ (MATERIALX_MAJOR_VERSION == 1 && MATERIALX_MINOR_VERSION > 38) || \
|
||||
+ (MATERIALX_MAJOR_VERSION == 1 && MATERIALX_MINOR_VERSION == 38 && MATERIALX_BUILD_VERSION > 4)
|
||||
+ // MaterialX 1.38.5 changes the default transmission method to "refraction".
|
||||
+ mxContext.getOptions().hwTransmissionRenderMethod = mx::TRANSMISSION_OPACITY;
|
||||
+
|
||||
+ // Emit transmission code
|
||||
+ emitTransmissionRender(mxContext, mxStage);
|
||||
+#endif
|
||||
+
|
||||
// Emit directional albedo table code.
|
||||
if (mxContext.getOptions().hwDirectionalAlbedoMethod ==
|
||||
mx::HwDirectionalAlbedoMethod::DIRECTIONAL_ALBEDO_TABLE ||
|
||||
mxContext.getOptions().hwWriteAlbedoTable) {
|
||||
- emitLibraryInclude("pbrlib/" + mx::GlslShaderGenerator::TARGET
|
||||
- + "/lib/mx_table.glsl", mxContext, mxStage);
|
||||
+ emitLibraryInclude("pbrlib/genglsl/lib/mx_table.glsl", mxContext, mxStage);
|
||||
emitLineBreak(mxStage);
|
||||
}
|
||||
|
||||
@@ -421,7 +427,7 @@ HdStMaterialXShaderGen::_EmitMxFunctions(
|
||||
// Emit uv transform code globally if needed.
|
||||
if (mxContext.getOptions().hwAmbientOcclusion) {
|
||||
emitLibraryInclude(
|
||||
- "stdlib/" + mx::GlslShaderGenerator::TARGET + "/lib/" +
|
||||
+ "stdlib/genglsl/lib/" +
|
||||
_tokenSubstitutions[ShaderGenerator::T_FILE_TRANSFORM_UV],
|
||||
mxContext, mxStage);
|
||||
}
|
||||
@@ -490,10 +496,30 @@ HdStMaterialXShaderGen::_EmitMxSurfaceShader(
|
||||
// closure/shader nodes and need to be emitted first.
|
||||
emitFunctionCalls(mxGraph, mxContext, mxStage, mx::ShaderNode::Classification::TEXTURE);
|
||||
|
||||
+#if MATERIALX_MAJOR_VERSION == 1 && \
|
||||
+ MATERIALX_MINOR_VERSION == 38 && \
|
||||
+ MATERIALX_BUILD_VERSION <= 4
|
||||
// Emit function calls for all surface shader nodes.
|
||||
// These will internally emit their closure function calls.
|
||||
emitFunctionCalls(mxGraph, mxContext, mxStage, mx::ShaderNode::Classification::SHADER |
|
||||
mx::ShaderNode::Classification::SURFACE);
|
||||
+#else
|
||||
+ // Emit function calls for "root" closure/shader nodes.
|
||||
+ // These will internally emit function calls for any dependent closure nodes upstream.
|
||||
+ for (mx::ShaderGraphOutputSocket* socket : mxGraph.getOutputSockets())
|
||||
+ {
|
||||
+ if (socket->getConnection())
|
||||
+ {
|
||||
+ const mx::ShaderNode* upstream = socket->getConnection()->getNode();
|
||||
+ if (upstream->getParent() == &mxGraph &&
|
||||
+ (upstream->hasClassification(mx::ShaderNode::Classification::CLOSURE) ||
|
||||
+ upstream->hasClassification(mx::ShaderNode::Classification::SHADER)))
|
||||
+ {
|
||||
+ emitFunctionCall(*upstream, mxContext, mxStage);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
else
|
||||
{
|
|
@ -108,7 +108,8 @@ set oiio_paths=%Staging%\%BuildDir%%ARCH%R\Release\openimageio\bin;%Staging%\%Bu
|
|||
set boost_paths=%Staging%\%BuildDir%%ARCH%R\Release\boost\lib;%Staging%\%BuildDir%%ARCH%D\Debug\boost\lib
|
||||
set openexr_paths=%Staging%\%BuildDir%%ARCH%R\Release\openexr\bin;%Staging%\%BuildDir%%ARCH%D\Debug\openexr\bin
|
||||
set imath_paths=%Staging%\%BuildDir%%ARCH%R\Release\imath\bin;%Staging%\%BuildDir%%ARCH%D\Debug\imath\bin
|
||||
set path=%BUILD_DIR%\downloads\mingw\mingw64\msys\1.0\bin\;%BUILD_DIR%\downloads\nasm-2.12.01\;%path%;%boost_paths%;%oiio_paths%;%openexr_paths%;%imath_paths%
|
||||
set tbb_paths=%Staging%\%BuildDir%%ARCH%R\Release\tbb\bin;%Staging%\%BuildDir%%ARCH%D\Debug\tbb\bin
|
||||
set path=%BUILD_DIR%\downloads\mingw\mingw64\msys\1.0\bin\;%BUILD_DIR%\downloads\nasm-2.12.01\;%path%;%boost_paths%;%oiio_paths%;%openexr_paths%;%imath_paths%;%tbb_paths%
|
||||
mkdir %STAGING%\%BuildDir%%ARCH%R
|
||||
cd %Staging%\%BuildDir%%ARCH%R
|
||||
echo %DATE% %TIME% : Start > %StatusFile%
|
||||
|
|
|
@ -39,6 +39,11 @@ class PHYSICS_PT_geometry_nodes(Panel):
|
|||
row.operator("object.simulation_nodes_cache_bake", text=bake_text).selected = True
|
||||
row.operator("object.simulation_nodes_cache_delete", text="", icon='TRASH').selected = True
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
ob = context.object
|
||||
layout.prop(ob, "use_simulation_cache", text="Cache")
|
||||
|
||||
|
||||
classes = (
|
||||
PHYSICS_PT_geometry_nodes,
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
* version. Older Blender versions will test this and show a warning if the file
|
||||
* was written with too new a version. */
|
||||
#define BLENDER_FILE_MIN_VERSION 305
|
||||
#define BLENDER_FILE_MIN_SUBVERSION 8
|
||||
#define BLENDER_FILE_MIN_SUBVERSION 9
|
||||
|
||||
/** User readable version string. */
|
||||
const char *BKE_blender_version_string(void);
|
||||
|
|
|
@ -308,6 +308,15 @@ void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
|
|||
* Properly delete a single ID from given \a bmain database.
|
||||
*/
|
||||
void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
|
||||
/**
|
||||
* Like BKE_id_delete, but with extra corner-case options.
|
||||
*
|
||||
* \param extra_remapping_flags Additional `ID_REMAP_` flags to pass to remapping code when
|
||||
* ensuring that deleted IDs are not used by any other ID in given `bmain`. Typical example would
|
||||
* be e.g. `ID_REMAP_FORCE_UI_POINTERS`, required when default UI-handling callbacks of remapping
|
||||
* code won't be working (e.g. from readfile code). */
|
||||
void BKE_id_delete_ex(struct Main *bmain, void *idv, const int extra_remapping_flags)
|
||||
ATTR_NONNULL(1, 2);
|
||||
/**
|
||||
* Properly delete all IDs tagged with \a LIB_TAG_DOIT, in given \a bmain database.
|
||||
*
|
||||
|
|
|
@ -269,7 +269,7 @@ bool BKE_library_id_can_use_idtype(struct ID *id_owner, short id_type_used);
|
|||
/**
|
||||
* Given the id_owner return the type of id_types it can use as a filter_id.
|
||||
*/
|
||||
uint64_t BKE_library_id_can_use_filter_id(const struct ID *id_owner);
|
||||
uint64_t BKE_library_id_can_use_filter_id(const struct ID *id_owner, const bool include_ui);
|
||||
|
||||
/**
|
||||
* Check whether given ID is used locally (i.e. by another non-linked ID).
|
||||
|
|
|
@ -181,6 +181,7 @@ class ModifierSimulationCache {
|
|||
}
|
||||
|
||||
void reset();
|
||||
void clear_prev_states();
|
||||
};
|
||||
|
||||
} // namespace blender::bke::sim
|
||||
|
|
|
@ -199,7 +199,9 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */
|
|||
}
|
||||
}
|
||||
|
||||
static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
||||
static size_t id_delete(Main *bmain,
|
||||
const bool do_tagged_deletion,
|
||||
const int extra_remapping_flags)
|
||||
{
|
||||
const int tag = LIB_TAG_DOIT;
|
||||
ListBase *lbarray[INDEX_ID_MAX];
|
||||
|
@ -211,6 +213,8 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
|||
const int free_flag = LIB_ID_FREE_NO_UI_USER |
|
||||
(do_tagged_deletion ? LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_USER_REFCOUNT :
|
||||
0);
|
||||
const int remapping_flags = (ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | extra_remapping_flags);
|
||||
ListBase tagged_deleted_ids = {NULL};
|
||||
|
||||
base_count = set_listbasepointers(bmain, lbarray);
|
||||
|
@ -261,11 +265,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
|||
* links, this can lead to nasty crashing here in second, actual deleting loop.
|
||||
* Also, this will also flag users of deleted data that cannot be unlinked
|
||||
* (object using deleted obdata, etc.), so that they also get deleted. */
|
||||
BKE_libblock_remap_multiple_locked(bmain,
|
||||
id_remapper,
|
||||
ID_REMAP_FLAG_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS);
|
||||
BKE_libblock_remap_multiple_locked(bmain, id_remapper, remapping_flags);
|
||||
BKE_id_remapper_clear(id_remapper);
|
||||
}
|
||||
|
||||
|
@ -329,11 +329,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
|||
* links, this can lead to nasty crashing here in second, actual deleting loop.
|
||||
* Also, this will also flag users of deleted data that cannot be unlinked
|
||||
* (object using deleted obdata, etc.), so that they also get deleted. */
|
||||
BKE_libblock_remap_multiple_locked(bmain,
|
||||
remapper,
|
||||
(ID_REMAP_FLAG_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_NEVER_NULL_USAGE |
|
||||
ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS));
|
||||
BKE_libblock_remap_multiple_locked(bmain, remapper, remapping_flags);
|
||||
}
|
||||
BKE_id_remapper_free(remapper);
|
||||
}
|
||||
|
@ -371,7 +367,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
|
|||
return num_datablocks_deleted;
|
||||
}
|
||||
|
||||
void BKE_id_delete(Main *bmain, void *idv)
|
||||
void BKE_id_delete_ex(Main *bmain, void *idv, const int extra_remapping_flags)
|
||||
{
|
||||
BLI_assert_msg((((ID *)idv)->tag & LIB_TAG_NO_MAIN) == 0,
|
||||
"Cannot be used with IDs outside of Main");
|
||||
|
@ -379,12 +375,17 @@ void BKE_id_delete(Main *bmain, void *idv)
|
|||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
((ID *)idv)->tag |= LIB_TAG_DOIT;
|
||||
|
||||
id_delete(bmain, false);
|
||||
id_delete(bmain, false, extra_remapping_flags);
|
||||
}
|
||||
|
||||
void BKE_id_delete(Main *bmain, void *idv)
|
||||
{
|
||||
BKE_id_delete_ex(bmain, idv, 0);
|
||||
}
|
||||
|
||||
size_t BKE_id_multi_tagged_delete(Main *bmain)
|
||||
{
|
||||
return id_delete(bmain, true);
|
||||
return id_delete(bmain, true, 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -374,7 +374,7 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner)
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner, const bool include_ui)
|
||||
{
|
||||
/* any type of ID can be used in custom props. */
|
||||
if (id_owner->properties) {
|
||||
|
@ -387,6 +387,11 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *id_owner)
|
|||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
/* Screen UI IDs can also link to virtually any ID (through e.g. the Outliner). */
|
||||
if (include_ui && id_type_owner == ID_SCR) {
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
/* Casting to non const.
|
||||
* TODO(jbakker): We should introduce a ntree_id_has_tree function as we are actually not
|
||||
* interested in the result. */
|
||||
|
@ -510,7 +515,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
|
|||
}
|
||||
|
||||
const uint64_t filter_id_type_used = BKE_idtype_idcode_to_idfilter(id_type_used);
|
||||
const uint64_t can_be_used = BKE_library_id_can_use_filter_id(id_owner);
|
||||
const uint64_t can_be_used = BKE_library_id_can_use_filter_id(id_owner, false);
|
||||
return (can_be_used & filter_id_type_used) != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -482,13 +482,14 @@ static void libblock_remap_data(Main *bmain,
|
|||
const int remap_flags)
|
||||
{
|
||||
IDRemap id_remap_data = {0};
|
||||
const int foreach_id_flags =
|
||||
(((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ?
|
||||
IDWALK_DO_INTERNAL_RUNTIME_POINTERS :
|
||||
IDWALK_NOP) |
|
||||
((remap_flags & ID_REMAP_FORCE_UI_POINTERS) != 0 ? IDWALK_INCLUDE_UI : IDWALK_NOP) |
|
||||
((remap_flags & ID_REMAP_NO_ORIG_POINTERS_ACCESS) != 0 ? IDWALK_NO_ORIG_POINTERS_ACCESS :
|
||||
IDWALK_NOP));
|
||||
const bool include_ui = (remap_flags & ID_REMAP_FORCE_UI_POINTERS) != 0;
|
||||
const int foreach_id_flags = (((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ?
|
||||
IDWALK_DO_INTERNAL_RUNTIME_POINTERS :
|
||||
IDWALK_NOP) |
|
||||
(include_ui ? IDWALK_INCLUDE_UI : IDWALK_NOP) |
|
||||
((remap_flags & ID_REMAP_NO_ORIG_POINTERS_ACCESS) != 0 ?
|
||||
IDWALK_NO_ORIG_POINTERS_ACCESS :
|
||||
IDWALK_NOP));
|
||||
|
||||
id_remap_data.id_remapper = id_remapper;
|
||||
id_remap_data.type = remap_type;
|
||||
|
@ -514,7 +515,7 @@ static void libblock_remap_data(Main *bmain,
|
|||
ID *id_curr;
|
||||
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id_curr) {
|
||||
const uint64_t can_use_filter_id = BKE_library_id_can_use_filter_id(id_curr);
|
||||
const uint64_t can_use_filter_id = BKE_library_id_can_use_filter_id(id_curr, include_ui);
|
||||
const bool has_mapping = BKE_id_remapper_has_mapping_for(id_remapper, can_use_filter_id);
|
||||
|
||||
/* Continue when id_remapper doesn't have any mappings that can be used by id_curr. */
|
||||
|
|
|
@ -1020,22 +1020,14 @@ int *BKE_mesh_poly_offsets_for_write(Mesh *mesh)
|
|||
|
||||
static void mesh_ensure_cdlayers_primary(Mesh &mesh)
|
||||
{
|
||||
if (!CustomData_get_layer_named(&mesh.vdata, CD_PROP_FLOAT3, "position")) {
|
||||
CustomData_add_layer_named(
|
||||
&mesh.vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh.totvert, "position");
|
||||
}
|
||||
if (!CustomData_get_layer_named(&mesh.edata, CD_PROP_INT32_2D, ".edge_verts")) {
|
||||
CustomData_add_layer_named(
|
||||
&mesh.edata, CD_PROP_INT32_2D, CD_CONSTRUCT, mesh.totedge, ".edge_verts");
|
||||
}
|
||||
if (!CustomData_get_layer_named(&mesh.ldata, CD_PROP_INT32, ".corner_vert")) {
|
||||
CustomData_add_layer_named(
|
||||
&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh.totloop, ".corner_vert");
|
||||
}
|
||||
if (!CustomData_get_layer_named(&mesh.ldata, CD_PROP_INT32, ".corner_edge")) {
|
||||
CustomData_add_layer_named(
|
||||
&mesh.ldata, CD_PROP_INT32, CD_CONSTRUCT, mesh.totloop, ".corner_edge");
|
||||
}
|
||||
blender::bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
||||
blender::bke::AttributeInitConstruct attribute_init;
|
||||
|
||||
/* Try to create attributes if they do not exist. */
|
||||
attributes.add("position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3, attribute_init);
|
||||
attributes.add(".edge_verts", ATTR_DOMAIN_EDGE, CD_PROP_INT32_2D, attribute_init);
|
||||
attributes.add(".corner_vert", ATTR_DOMAIN_CORNER, CD_PROP_INT32, attribute_init);
|
||||
attributes.add(".corner_edge", ATTR_DOMAIN_CORNER, CD_PROP_INT32, attribute_init);
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_new_nomain(const int verts_num,
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_vector.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
|
|
|
@ -202,6 +202,15 @@ void ModifierSimulationState::ensure_bake_loaded() const
|
|||
bake_loaded_ = true;
|
||||
}
|
||||
|
||||
void ModifierSimulationCache::clear_prev_states()
|
||||
{
|
||||
std::lock_guard lock(states_at_frames_mutex_);
|
||||
std::unique_ptr<ModifierSimulationStateAtFrame> temp = std::move(states_at_frames_.last());
|
||||
states_at_frames_.clear_and_shrink();
|
||||
bdata_sharing_.reset();
|
||||
states_at_frames_.append(std::move(temp));
|
||||
}
|
||||
|
||||
void ModifierSimulationCache::reset()
|
||||
{
|
||||
std::lock_guard lock(states_at_frames_mutex_);
|
||||
|
|
|
@ -290,7 +290,11 @@ static BLI_freenode *mempool_chunk_add(BLI_mempool *pool,
|
|||
|
||||
static void mempool_chunk_free(BLI_mempool_chunk *mpchunk, BLI_mempool *pool)
|
||||
{
|
||||
#ifdef WITH_ASAN
|
||||
BLI_asan_unpoison(mpchunk, sizeof(BLI_mempool_chunk) + pool->esize * pool->csize);
|
||||
#else
|
||||
UNUSED_VARS(pool);
|
||||
#endif
|
||||
MEM_freeN(mpchunk);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,21 +26,118 @@
|
|||
# pragma GCC diagnostic error "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name UTF8 Character Decoding (Skip & Mask Lookup)
|
||||
*
|
||||
* Derived from GLIB `gutf8.c`.
|
||||
*
|
||||
* Ranges (zero based, inclusive):
|
||||
*
|
||||
* - 000..127: 1 byte.
|
||||
* - 128..191: invalid.
|
||||
* - 192..223: 2 bytes.
|
||||
* - 224..239: 3 bytes.
|
||||
* - 240..247: 4 bytes.
|
||||
* - 248..251: 4 bytes.
|
||||
* - 252..253: 4 bytes.
|
||||
* - 254..255: invalid.
|
||||
*
|
||||
* Invalid values fall back to 1 byte or -1 (for an error value).
|
||||
* \{ */
|
||||
|
||||
BLI_INLINE int utf8_char_compute_skip(const char c)
|
||||
{
|
||||
if (UNLIKELY(c >= 192)) {
|
||||
if ((c & 0xe0) == 0xc0) {
|
||||
return 2;
|
||||
}
|
||||
if ((c & 0xf0) == 0xe0) {
|
||||
return 3;
|
||||
}
|
||||
if ((c & 0xf8) == 0xf0) {
|
||||
return 4;
|
||||
}
|
||||
if ((c & 0xfc) == 0xf8) {
|
||||
return 5;
|
||||
}
|
||||
if ((c & 0xfe) == 0xfc) {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
BLI_INLINE int utf8_char_compute_skip_or_error(const char c)
|
||||
{
|
||||
if (c < 128) {
|
||||
return 1;
|
||||
}
|
||||
if ((c & 0xe0) == 0xc0) {
|
||||
return 2;
|
||||
}
|
||||
if ((c & 0xf0) == 0xe0) {
|
||||
return 3;
|
||||
}
|
||||
if ((c & 0xf8) == 0xf0) {
|
||||
return 4;
|
||||
}
|
||||
if ((c & 0xfc) == 0xf8) {
|
||||
return 5;
|
||||
}
|
||||
if ((c & 0xfe) == 0xfc) {
|
||||
return 6;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
BLI_INLINE int utf8_char_compute_skip_or_error_with_mask(const char c, char *r_mask)
|
||||
{
|
||||
/* Originally from GLIB `UTF8_COMPUTE` macro. */
|
||||
if (c < 128) {
|
||||
*r_mask = 0x7f;
|
||||
return 1;
|
||||
}
|
||||
if ((c & 0xe0) == 0xc0) {
|
||||
*r_mask = 0x1f;
|
||||
return 2;
|
||||
}
|
||||
if ((c & 0xf0) == 0xe0) {
|
||||
*r_mask = 0x0f;
|
||||
return 3;
|
||||
}
|
||||
if ((c & 0xf8) == 0xf0) {
|
||||
*r_mask = 0x07;
|
||||
return 4;
|
||||
}
|
||||
if ((c & 0xfc) == 0xf8) {
|
||||
*r_mask = 0x03;
|
||||
return 5;
|
||||
}
|
||||
if ((c & 0xfe) == 0xfc) {
|
||||
*r_mask = 0x01;
|
||||
return 6;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array copied from GLIB's `gutf8.c`.
|
||||
* \note last two values (0xfe and 0xff) are forbidden in UTF-8,
|
||||
* so they are considered 1 byte length too.
|
||||
* Decode a UTF8 code-point, use in combination with #utf8_char_compute_skip_or_error_with_mask.
|
||||
*/
|
||||
static const size_t utf8_skip_data[256] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1,
|
||||
};
|
||||
BLI_INLINE uint utf8_char_decode(const char *p, const char mask, const int len, const uint err)
|
||||
{
|
||||
/* Originally from GLIB `UTF8_GET` macro, added an 'err' argument. */
|
||||
uint result = p[0] & mask;
|
||||
for (int count = 1; count < len; count++) {
|
||||
if ((p[count] & 0xc0) != 0x80) {
|
||||
return err;
|
||||
}
|
||||
result <<= 6;
|
||||
result |= p[count] & 0x3f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length)
|
||||
{
|
||||
|
@ -75,7 +172,7 @@ ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length)
|
|||
/* Note that since we always increase p (and decrease length) by one byte in main loop,
|
||||
* we only add/subtract extra utf8 bytes in code below
|
||||
* (ab number, aka number of bytes remaining in the utf8 sequence after the initial one). */
|
||||
ab = (int)utf8_skip_data[c] - 1;
|
||||
ab = utf8_char_compute_skip(c) - 1;
|
||||
if (length <= ab) {
|
||||
goto utf8_error;
|
||||
}
|
||||
|
@ -212,21 +309,24 @@ int BLI_str_utf8_invalid_strip(char *str, size_t length)
|
|||
*/
|
||||
BLI_INLINE char *str_utf8_copy_max_bytes_impl(char *dst, const char *src, size_t dst_maxncpy)
|
||||
{
|
||||
/* Cast to `uint8_t` is a no-op, quiets array subscript of type `char` warning. */
|
||||
/* Cast to `uint8_t` is a no-op, quiets array subscript of type `char` warning.
|
||||
* No need to check `src` points to a nil byte, this will break out of the switch statement. */
|
||||
size_t utf8_size;
|
||||
while (*src != '\0' && (utf8_size = utf8_skip_data[(uint8_t)*src]) < dst_maxncpy) {
|
||||
while ((utf8_size = (size_t)utf8_char_compute_skip(*src)) < dst_maxncpy) {
|
||||
dst_maxncpy -= utf8_size;
|
||||
/* Prefer more compact block. */
|
||||
/* NOLINTBEGIN: bugprone-assignment-in-if-condition */
|
||||
/* clang-format off */
|
||||
switch (utf8_size) {
|
||||
case 6: *dst++ = *src++; ATTR_FALLTHROUGH;
|
||||
case 5: *dst++ = *src++; ATTR_FALLTHROUGH;
|
||||
case 4: *dst++ = *src++; ATTR_FALLTHROUGH;
|
||||
case 3: *dst++ = *src++; ATTR_FALLTHROUGH;
|
||||
case 2: *dst++ = *src++; ATTR_FALLTHROUGH;
|
||||
case 1: *dst++ = *src++;
|
||||
case 6: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 5: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 4: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 3: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 2: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++; ATTR_FALLTHROUGH;
|
||||
case 1: if (UNLIKELY(!(*dst = *src++))) { return dst; } dst++;
|
||||
}
|
||||
/* clang-format on */
|
||||
/* NOLINTEND: bugprone-assignment-in-if-condition */
|
||||
}
|
||||
*dst = '\0';
|
||||
return dst;
|
||||
|
@ -237,10 +337,8 @@ char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t
|
|||
BLI_assert(dst_maxncpy != 0);
|
||||
BLI_string_debug_size(dst, dst_maxncpy);
|
||||
|
||||
char *r_dst = dst;
|
||||
str_utf8_copy_max_bytes_impl(dst, src, dst_maxncpy);
|
||||
|
||||
return r_dst;
|
||||
return dst;
|
||||
}
|
||||
|
||||
size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy)
|
||||
|
@ -615,115 +713,46 @@ char32_t BLI_str_utf32_char_to_lower(const char32_t wc)
|
|||
|
||||
/** \} */ /* -------------------------------------------------------------------- */
|
||||
|
||||
/* copied from glib's gutf8.c, added 'Err' arg */
|
||||
|
||||
/* NOTE(@ideasman42): glib uses uint for unicode, best we do the same,
|
||||
* though we don't typedef it. */
|
||||
|
||||
#define UTF8_COMPUTE(Char, Mask, Len, Err) \
|
||||
if (Char < 128) { \
|
||||
Len = 1; \
|
||||
Mask = 0x7f; \
|
||||
} \
|
||||
else if ((Char & 0xe0) == 0xc0) { \
|
||||
Len = 2; \
|
||||
Mask = 0x1f; \
|
||||
} \
|
||||
else if ((Char & 0xf0) == 0xe0) { \
|
||||
Len = 3; \
|
||||
Mask = 0x0f; \
|
||||
} \
|
||||
else if ((Char & 0xf8) == 0xf0) { \
|
||||
Len = 4; \
|
||||
Mask = 0x07; \
|
||||
} \
|
||||
else if ((Char & 0xfc) == 0xf8) { \
|
||||
Len = 5; \
|
||||
Mask = 0x03; \
|
||||
} \
|
||||
else if ((Char & 0xfe) == 0xfc) { \
|
||||
Len = 6; \
|
||||
Mask = 0x01; \
|
||||
} \
|
||||
else { \
|
||||
Len = Err; /* -1 is the typical error value or 1 to skip */ \
|
||||
} \
|
||||
(void)0
|
||||
|
||||
/* same as glib define but added an 'Err' arg */
|
||||
#define UTF8_GET(Result, Chars, Count, Mask, Len, Err) \
|
||||
(Result) = (Chars)[0] & (Mask); \
|
||||
for ((Count) = 1; (Count) < (Len); ++(Count)) { \
|
||||
if (((Chars)[(Count)] & 0xc0) != 0x80) { \
|
||||
(Result) = Err; \
|
||||
break; \
|
||||
} \
|
||||
(Result) <<= 6; \
|
||||
(Result) |= ((Chars)[(Count)] & 0x3f); \
|
||||
} \
|
||||
(void)0
|
||||
|
||||
int BLI_str_utf8_size(const char *p)
|
||||
{
|
||||
/* NOTE: uses glib functions but not from GLIB. */
|
||||
|
||||
int mask = 0, len;
|
||||
const uchar c = (uchar)*p;
|
||||
|
||||
UTF8_COMPUTE(c, mask, len, -1);
|
||||
|
||||
(void)mask; /* quiet warning */
|
||||
|
||||
return len;
|
||||
return utf8_char_compute_skip_or_error(*p);
|
||||
}
|
||||
|
||||
int BLI_str_utf8_size_safe(const char *p)
|
||||
{
|
||||
int mask = 0, len;
|
||||
const uchar c = (uchar)*p;
|
||||
|
||||
UTF8_COMPUTE(c, mask, len, 1);
|
||||
|
||||
(void)mask; /* quiet warning */
|
||||
|
||||
return len;
|
||||
return utf8_char_compute_skip(*p);
|
||||
}
|
||||
|
||||
uint BLI_str_utf8_as_unicode(const char *p)
|
||||
{
|
||||
/* Originally `g_utf8_get_char` in GLIB. */
|
||||
|
||||
int i, len;
|
||||
uint mask = 0;
|
||||
uint result;
|
||||
const uchar c = (uchar)*p;
|
||||
|
||||
UTF8_COMPUTE(c, mask, len, -1);
|
||||
char mask = 0;
|
||||
const int len = utf8_char_compute_skip_or_error_with_mask(c, &mask);
|
||||
if (UNLIKELY(len == -1)) {
|
||||
return BLI_UTF8_ERR;
|
||||
}
|
||||
UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR);
|
||||
|
||||
return result;
|
||||
return utf8_char_decode(p, mask, len, BLI_UTF8_ERR);
|
||||
}
|
||||
|
||||
uint BLI_str_utf8_as_unicode_step_or_error(const char *__restrict p,
|
||||
const size_t p_len,
|
||||
size_t *__restrict index)
|
||||
{
|
||||
int i, len;
|
||||
uint mask = 0;
|
||||
uint result;
|
||||
const uchar c = (uchar) * (p += *index);
|
||||
|
||||
BLI_assert(*index < p_len);
|
||||
BLI_assert(c != '\0');
|
||||
|
||||
UTF8_COMPUTE(c, mask, len, -1);
|
||||
char mask = 0;
|
||||
const int len = utf8_char_compute_skip_or_error_with_mask(c, &mask);
|
||||
if (UNLIKELY(len == -1) || (*index + (size_t)len > p_len)) {
|
||||
return BLI_UTF8_ERR;
|
||||
}
|
||||
UTF8_GET(result, p, i, mask, len, BLI_UTF8_ERR);
|
||||
|
||||
const uint result = utf8_char_decode(p, mask, len, BLI_UTF8_ERR);
|
||||
if (UNLIKELY(result == BLI_UTF8_ERR)) {
|
||||
return BLI_UTF8_ERR;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,109 @@ using std::pair;
|
|||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name String Copy (UTF8)
|
||||
* \{ */
|
||||
|
||||
TEST(string, StrCopyUTF8_ASCII)
|
||||
{
|
||||
#define STRNCPY_UTF8_ASCII(...) \
|
||||
{ \
|
||||
const char src[] = {__VA_ARGS__, 0}; \
|
||||
char dst[sizeof(src)]; \
|
||||
memset(dst, 0xff, sizeof(dst)); \
|
||||
BLI_strncpy_utf8(dst, src, sizeof(dst)); \
|
||||
EXPECT_EQ(strlen(dst), sizeof(dst) - 1); \
|
||||
EXPECT_STREQ(dst, src); \
|
||||
}
|
||||
|
||||
STRNCPY_UTF8_ASCII('a');
|
||||
STRNCPY_UTF8_ASCII('a', 'b', 'c');
|
||||
|
||||
#undef STRNCPY_UTF8_ASCII
|
||||
}
|
||||
|
||||
TEST(string, StrCopyUTF8_ASCII_Truncate)
|
||||
{
|
||||
#define STRNCPY_UTF8_ASCII_TRUNCATE(maxncpy, ...) \
|
||||
{ \
|
||||
char src[] = {__VA_ARGS__}; \
|
||||
char dst[sizeof(src)]; \
|
||||
memset(dst, 0xff, sizeof(dst)); \
|
||||
BLI_strncpy_utf8(dst, src, maxncpy); \
|
||||
int len_expect = MIN2(sizeof(src), maxncpy) - 1; \
|
||||
src[len_expect] = '\0'; /* To be able to use `EXPECT_STREQ`. */ \
|
||||
EXPECT_EQ(strlen(dst), len_expect); \
|
||||
EXPECT_STREQ(dst, src); \
|
||||
}
|
||||
|
||||
STRNCPY_UTF8_ASCII_TRUNCATE(1, '\0');
|
||||
STRNCPY_UTF8_ASCII_TRUNCATE(3, 'A', 'A', 'A', 'A');
|
||||
|
||||
#undef STRNCPY_UTF8_ASCII_TRUNCATE
|
||||
}
|
||||
|
||||
TEST(string, StrCopyUTF8_TruncateEncoding)
|
||||
{
|
||||
/* Ensure copying one byte less than the code-point results in it being ignored entirely. */
|
||||
#define STRNCPY_UTF8_TRUNCATE(byte_size, ...) \
|
||||
{ \
|
||||
const char src[] = {__VA_ARGS__, 0}; \
|
||||
EXPECT_EQ(BLI_str_utf8_size(src), byte_size); \
|
||||
char dst[sizeof(src)]; \
|
||||
memset(dst, 0xff, sizeof(dst)); \
|
||||
BLI_strncpy_utf8(dst, src, sizeof(dst)); \
|
||||
EXPECT_EQ(strlen(dst), sizeof(dst) - 1); \
|
||||
EXPECT_STREQ(dst, src); \
|
||||
BLI_strncpy_utf8(dst, src, sizeof(dst) - 1); \
|
||||
EXPECT_STREQ(dst, ""); \
|
||||
}
|
||||
|
||||
STRNCPY_UTF8_TRUNCATE(6, 252, 1, 1, 1, 1, 1);
|
||||
STRNCPY_UTF8_TRUNCATE(5, 248, 1, 1, 1, 1);
|
||||
STRNCPY_UTF8_TRUNCATE(4, 240, 1, 1, 1);
|
||||
STRNCPY_UTF8_TRUNCATE(3, 224, 1, 1);
|
||||
STRNCPY_UTF8_TRUNCATE(2, 192, 1);
|
||||
STRNCPY_UTF8_TRUNCATE(1, 96);
|
||||
|
||||
#undef STRNCPY_UTF8_TRUNCATE
|
||||
}
|
||||
|
||||
TEST(string, StrCopyUTF8_TerminateEncodingEarly)
|
||||
{
|
||||
/* A UTF8 sequence that has a null byte before the sequence ends.
|
||||
* Ensure the the UTF8 sequence does not step over the null byte. */
|
||||
#define STRNCPY_UTF8_TERMINATE_EARLY(byte_size, ...) \
|
||||
{ \
|
||||
char src[] = {__VA_ARGS__, 0}; \
|
||||
EXPECT_EQ(BLI_str_utf8_size(src), byte_size); \
|
||||
char dst[sizeof(src)]; \
|
||||
memset(dst, 0xff, sizeof(dst)); \
|
||||
BLI_strncpy_utf8(dst, src, sizeof(dst)); \
|
||||
EXPECT_EQ(strlen(dst), sizeof(dst) - 1); \
|
||||
EXPECT_STREQ(dst, src); \
|
||||
for (int i = sizeof(dst) - 1; i > 1; i--) { \
|
||||
src[i] = '\0'; \
|
||||
memset(dst, 0xff, sizeof(dst)); \
|
||||
const int dst_copied = BLI_strncpy_utf8_rlen(dst, src, sizeof(dst)); \
|
||||
EXPECT_STREQ(dst, src); \
|
||||
EXPECT_EQ(strlen(dst), i); \
|
||||
EXPECT_EQ(dst_copied, i); \
|
||||
} \
|
||||
}
|
||||
|
||||
STRNCPY_UTF8_TERMINATE_EARLY(6, 252, 1, 1, 1, 1, 1);
|
||||
STRNCPY_UTF8_TERMINATE_EARLY(5, 248, 1, 1, 1, 1);
|
||||
STRNCPY_UTF8_TERMINATE_EARLY(4, 240, 1, 1, 1);
|
||||
STRNCPY_UTF8_TERMINATE_EARLY(3, 224, 1, 1);
|
||||
STRNCPY_UTF8_TERMINATE_EARLY(2, 192, 1);
|
||||
STRNCPY_UTF8_TERMINATE_EARLY(1, 96);
|
||||
|
||||
#undef STRNCPY_UTF8_TERMINATE_EARLY
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name String Partition
|
||||
* \{ */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
|
@ -196,7 +197,10 @@ bool BLO_main_validate_shapekeys(Main *bmain, ReportList *reports)
|
|||
"Shapekey %s has an invalid 'from' pointer (%p), it will be deleted",
|
||||
shapekey->id.name,
|
||||
shapekey->from);
|
||||
BKE_id_delete(bmain, shapekey);
|
||||
/* NOTE: also need to remap UI data ID pointers here, since `bmain` is not the current
|
||||
* `G_MAIN`, default UI-handling remapping callback (defined by call to
|
||||
* `BKE_library_callback_remap_editor_id_reference_set`) won't work on exoected data here. */
|
||||
BKE_id_delete_ex(bmain, shapekey, ID_REMAP_FORCE_UI_POINTERS);
|
||||
}
|
||||
|
||||
return is_valid;
|
||||
|
|
|
@ -3472,7 +3472,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
|
||||
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
|
||||
ob->flag &= ~(OB_FLAG_UNUSED_11 | OB_FLAG_UNUSED_12);
|
||||
ob->flag &= ~(OB_FLAG_USE_SIMULATION_CACHE | OB_FLAG_UNUSED_12);
|
||||
ob->transflag &= ~(OB_TRANSFORM_ADJUST_ROOT_PARENT_FOR_VIEW_LOCK | OB_TRANSFLAG_UNUSED_1);
|
||||
ob->shapeflag &= ~OB_SHAPE_FLAG_UNUSED_1;
|
||||
}
|
||||
|
|
|
@ -1174,8 +1174,7 @@ void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain)
|
|||
SOCK_OBJECT,
|
||||
SOCK_COLLECTION,
|
||||
SOCK_TEXTURE,
|
||||
SOCK_MATERIAL))
|
||||
{
|
||||
SOCK_MATERIAL)) {
|
||||
link->tosock = link->tosock->next;
|
||||
}
|
||||
}
|
||||
|
@ -2646,8 +2645,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 17)) {
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size"))
|
||||
{
|
||||
fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size")) {
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
|
@ -2675,8 +2673,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 18)) {
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library_ref"))
|
||||
{
|
||||
fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library_ref")) {
|
||||
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
|
||||
BKE_asset_library_reference_init_default(&workspace->asset_library_ref);
|
||||
}
|
||||
|
@ -4351,6 +4348,13 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 306, 8)) {
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
ob->flag |= OB_FLAG_USE_SIMULATION_CACHE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
|
|
@ -132,6 +132,7 @@ set(GLSL_SRC
|
|||
shaders/compositor_normalize.glsl
|
||||
shaders/compositor_parallel_reduction.glsl
|
||||
shaders/compositor_plane_deform.glsl
|
||||
shaders/compositor_plane_deform_motion_blur.glsl
|
||||
shaders/compositor_projector_lens_distortion.glsl
|
||||
shaders/compositor_read_pass.glsl
|
||||
shaders/compositor_realize_on_domain.glsl
|
||||
|
@ -231,6 +232,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_normalize_info.hh
|
||||
shaders/infos/compositor_parallel_reduction_info.hh
|
||||
shaders/infos/compositor_plane_deform_info.hh
|
||||
shaders/infos/compositor_plane_deform_motion_blur_info.hh
|
||||
shaders/infos/compositor_projector_lens_distortion_info.hh
|
||||
shaders/infos/compositor_read_pass_info.hh
|
||||
shaders/infos/compositor_realize_on_domain_info.hh
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
/* Add 0.5 to evaluate the sampler at the center of the pixel and divide by the size to get the
|
||||
* coordinates into the sampler's expected [0, 1] range. We choose the maximum between both
|
||||
* output sizes because one of the outputs might be a dummy 1x1 image. */
|
||||
ivec2 output_size = max(imageSize(output_img), imageSize(mask_img));
|
||||
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(output_size);
|
||||
|
||||
vec4 accumulated_color = vec4(0.0);
|
||||
for (int i = 0; i < number_of_motion_blur_samples; i++) {
|
||||
mat3 homography_matrix = mat3(homography_matrices[i]);
|
||||
|
||||
vec3 transformed_coordinates = homography_matrix * vec3(coordinates, 1.0);
|
||||
vec2 projected_coordinates = transformed_coordinates.xy / transformed_coordinates.z;
|
||||
|
||||
/* The derivatives of the projected coordinates with respect to x and y are the first and
|
||||
* second columns respectively, divided by the z projection factor as can be shown by
|
||||
* differentiating the above matrix multiplication with respect to x and y. */
|
||||
vec2 x_gradient = homography_matrix[0].xy / transformed_coordinates.z;
|
||||
vec2 y_gradient = homography_matrix[1].xy / transformed_coordinates.z;
|
||||
|
||||
accumulated_color += textureGrad(input_tx, projected_coordinates, x_gradient, y_gradient);
|
||||
}
|
||||
|
||||
accumulated_color /= number_of_motion_blur_samples;
|
||||
|
||||
imageStore(output_img, texel, accumulated_color);
|
||||
imageStore(mask_img, texel, accumulated_color.aaaa);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_plane_deform_motion_blur)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::INT, "number_of_motion_blur_samples")
|
||||
.uniform_buf(0, "mat4", "homography_matrices[64]")
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.image(1, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "mask_img")
|
||||
.compute_source("compositor_plane_deform_motion_blur.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -137,6 +137,27 @@ static bNode *node_group_get_active(bContext *C, const char *node_idname)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/* Maps old to new identifiers for simulation input node pairing. */
|
||||
static void remap_pairing(bNodeTree &dst_tree,
|
||||
Span<bNode *> nodes,
|
||||
const Map<int32_t, int32_t> &identifier_map)
|
||||
{
|
||||
for (bNode *dst_node : nodes) {
|
||||
if (dst_node->type == GEO_NODE_SIMULATION_INPUT) {
|
||||
NodeGeometrySimulationInput *data = static_cast<NodeGeometrySimulationInput *>(
|
||||
dst_node->storage);
|
||||
if (data->output_node_id == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data->output_node_id = identifier_map.lookup_default(data->output_node_id, 0);
|
||||
if (data->output_node_id == 0) {
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -232,7 +253,10 @@ static bool node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
|
|||
bNodeTree *wgroup = ntreeCopyTree(bmain, ngroup);
|
||||
|
||||
/* Add the nodes into the `ntree`. */
|
||||
Vector<bNode *> new_nodes;
|
||||
Map<int32_t, int32_t> node_identifier_map;
|
||||
LISTBASE_FOREACH_MUTABLE (bNode *, node, &wgroup->nodes) {
|
||||
new_nodes.append(node);
|
||||
/* Remove interface nodes.
|
||||
* This also removes remaining links to and from interface nodes.
|
||||
*/
|
||||
|
@ -253,8 +277,10 @@ static bool node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
|
|||
/* migrate node */
|
||||
BLI_remlink(&wgroup->nodes, node);
|
||||
BLI_addtail(&ntree->nodes, node);
|
||||
const int32_t old_identifier = node->identifier;
|
||||
nodeUniqueID(ntree, node);
|
||||
nodeUniqueName(ntree, node);
|
||||
node_identifier_map.add(old_identifier, node->identifier);
|
||||
|
||||
BKE_ntree_update_tag_node_new(ntree, node);
|
||||
|
||||
|
@ -310,6 +336,8 @@ static bool node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
|
|||
}
|
||||
}
|
||||
|
||||
remap_pairing(*ntree, new_nodes, node_identifier_map);
|
||||
|
||||
/* free the group tree (takes care of user count) */
|
||||
BKE_id_free(bmain, wgroup);
|
||||
|
||||
|
@ -440,28 +468,6 @@ void NODE_OT_group_ungroup(wmOperatorType *ot)
|
|||
/** \name Separate Operator
|
||||
* \{ */
|
||||
|
||||
static void remap_pairing(bNodeTree &dst_tree, const Set<bNode *> &nodes)
|
||||
{
|
||||
for (bNode *dst_node : nodes) {
|
||||
if (dst_node->type == GEO_NODE_SIMULATION_INPUT) {
|
||||
NodeGeometrySimulationInput &data = *static_cast<NodeGeometrySimulationInput *>(
|
||||
dst_node->storage);
|
||||
/* XXX Technically this is not correct because the output_node_id is only valid
|
||||
* in the original node group tree and we'd have map old IDs to new nodes first.
|
||||
* The ungroup operator does not build a node map, it just expects node IDs to
|
||||
* remain unchanged, which is probably true most of the time because they are
|
||||
* mostly random numbers out of the uint32_t range. */
|
||||
if (const bNode *output_node = dst_tree.node_by_id(data.output_node_id)) {
|
||||
data.output_node_id = output_node->identifier;
|
||||
}
|
||||
else {
|
||||
data.output_node_id = 0;
|
||||
blender::nodes::update_node_declaration_and_sockets(dst_tree, *dst_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \return True if successful.
|
||||
*/
|
||||
|
@ -472,28 +478,31 @@ static bool node_group_separate_selected(
|
|||
|
||||
ListBase anim_basepaths = {nullptr, nullptr};
|
||||
|
||||
Map<bNode *, bNode *> node_map;
|
||||
Map<const bNodeSocket *, bNodeSocket *> socket_map;
|
||||
Map<int32_t, int32_t> node_identifier_map;
|
||||
|
||||
/* Add selected nodes into the ntree, ignoring interface nodes. */
|
||||
VectorSet<bNode *> nodes_to_move = get_selected_nodes(ngroup);
|
||||
nodes_to_move.remove_if(
|
||||
[](const bNode *node) { return node->is_group_input() || node->is_group_output(); });
|
||||
|
||||
Set<bNode *> new_nodes;
|
||||
|
||||
for (bNode *node : nodes_to_move) {
|
||||
bNode *newnode;
|
||||
if (make_copy) {
|
||||
newnode = bke::node_copy_with_mapping(&ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map);
|
||||
new_nodes.add_new(newnode);
|
||||
node_identifier_map.add(node->identifier, newnode->identifier);
|
||||
}
|
||||
else {
|
||||
newnode = node;
|
||||
BLI_remlink(&ngroup.nodes, newnode);
|
||||
BLI_addtail(&ntree.nodes, newnode);
|
||||
const int32_t old_identifier = node->identifier;
|
||||
nodeUniqueID(&ntree, newnode);
|
||||
nodeUniqueName(&ntree, newnode);
|
||||
node_identifier_map.add(old_identifier, newnode->identifier);
|
||||
}
|
||||
node_map.add_new(node, newnode);
|
||||
|
||||
/* Keep track of this node's RNA "base" path (the part of the path identifying the node)
|
||||
* if the old node-tree has animation data which potentially covers this node. */
|
||||
|
@ -525,16 +534,16 @@ static bool node_group_separate_selected(
|
|||
|
||||
/* add internal links to the ntree */
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ngroup.links) {
|
||||
const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
|
||||
const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
|
||||
const bool fromselect = (link->fromnode && nodes_to_move.contains(link->fromnode));
|
||||
const bool toselect = (link->tonode && nodes_to_move.contains(link->tonode));
|
||||
|
||||
if (make_copy) {
|
||||
/* make a copy of internal links */
|
||||
if (fromselect && toselect) {
|
||||
nodeAddLink(&ntree,
|
||||
ntree.node_by_id(link->fromnode->identifier),
|
||||
node_map.lookup(link->fromnode),
|
||||
socket_map.lookup(link->fromsock),
|
||||
ntree.node_by_id(link->tonode->identifier),
|
||||
node_map.lookup(link->tonode),
|
||||
socket_map.lookup(link->tosock));
|
||||
}
|
||||
}
|
||||
|
@ -550,7 +559,9 @@ static bool node_group_separate_selected(
|
|||
}
|
||||
}
|
||||
|
||||
for (bNode *node : new_nodes) {
|
||||
remap_pairing(ntree, nodes_to_move, node_identifier_map);
|
||||
|
||||
for (bNode *node : node_map.values()) {
|
||||
nodeDeclarationEnsure(&ntree, node);
|
||||
}
|
||||
|
||||
|
@ -566,8 +577,6 @@ static bool node_group_separate_selected(
|
|||
}
|
||||
}
|
||||
|
||||
remap_pairing(ntree, new_nodes);
|
||||
|
||||
BKE_ntree_update_tag_all(&ntree);
|
||||
if (!make_copy) {
|
||||
BKE_ntree_update_tag_all(&ngroup);
|
||||
|
@ -734,6 +743,36 @@ static bool node_group_make_test_selected(bNodeTree &ntree,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
/* Check if simulation zone pairs are fully selected.
|
||||
* Simulation input or output nodes can only be grouped together with the paired node.
|
||||
*/
|
||||
for (bNode *input_node : ntree.nodes_by_type("GeometryNodeSimulationInput")) {
|
||||
const NodeGeometrySimulationInput &input_data =
|
||||
*static_cast<const NodeGeometrySimulationInput *>(input_node->storage);
|
||||
|
||||
if (bNode *output_node = ntree.node_by_id(input_data.output_node_id)) {
|
||||
const bool input_selected = nodes_to_group.contains(input_node);
|
||||
const bool output_selected = nodes_to_group.contains(output_node);
|
||||
if (input_selected && !output_selected) {
|
||||
BKE_reportf(
|
||||
&reports,
|
||||
RPT_WARNING,
|
||||
"Can not add simulation input node '%s' to a group without its paired output '%s'",
|
||||
input_node->name,
|
||||
output_node->name);
|
||||
return false;
|
||||
}
|
||||
if (output_selected && !input_selected) {
|
||||
BKE_reportf(
|
||||
&reports,
|
||||
RPT_WARNING,
|
||||
"Can not add simulation output node '%s' to a group without its paired input '%s'",
|
||||
output_node->name,
|
||||
input_node->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -863,6 +902,8 @@ static void node_group_make_insert_selected(const bContext &C,
|
|||
Vector<OutputLinkInfo> output_links;
|
||||
Set<bNodeLink *> internal_links_to_move;
|
||||
Set<bNodeLink *> links_to_remove;
|
||||
/* Map old to new node identifiers. */
|
||||
Map<int32_t, int32_t> node_identifier_map;
|
||||
|
||||
ntree.ensure_topology_cache();
|
||||
for (bNode *node : nodes_to_move) {
|
||||
|
@ -959,11 +1000,15 @@ static void node_group_make_insert_selected(const bContext &C,
|
|||
|
||||
/* Move nodes into the group. */
|
||||
for (bNode *node : nodes_to_move) {
|
||||
const int32_t old_identifier = node->identifier;
|
||||
|
||||
BLI_remlink(&ntree.nodes, node);
|
||||
BLI_addtail(&group.nodes, node);
|
||||
nodeUniqueID(&group, node);
|
||||
nodeUniqueName(&group, node);
|
||||
|
||||
node_identifier_map.add(old_identifier, node->identifier);
|
||||
|
||||
BKE_ntree_update_tag_node_removed(&ntree);
|
||||
BKE_ntree_update_tag_node_new(&group, node);
|
||||
}
|
||||
|
@ -1029,6 +1074,8 @@ static void node_group_make_insert_selected(const bContext &C,
|
|||
}
|
||||
}
|
||||
|
||||
remap_pairing(group, nodes_to_move, node_identifier_map);
|
||||
|
||||
if (group.type == NTREE_GEOMETRY) {
|
||||
bke::node_field_inferencing::update_field_inferencing(group);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
namespace blender::geometry {
|
||||
|
||||
bke::CurvesGeometry create_curve_from_vert_indices(
|
||||
BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
|
||||
const bke::AttributeAccessor &mesh_attributes,
|
||||
const Span<int> vert_indices,
|
||||
const Span<int> curve_offsets,
|
||||
|
@ -80,27 +80,20 @@ struct CurveFromEdgesOutput {
|
|||
IndexRange cyclic_curves;
|
||||
};
|
||||
|
||||
static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
||||
const Span<int2> edges)
|
||||
BLI_NOINLINE static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
||||
const Span<int2> edges)
|
||||
{
|
||||
Vector<int> vert_indices;
|
||||
vert_indices.reserve(edges.size());
|
||||
Vector<int> curve_offsets;
|
||||
|
||||
/* Compute the number of edges connecting to each vertex. */
|
||||
Array<int> neighbor_count(verts_num, 0);
|
||||
for (const int2 &edge : edges) {
|
||||
neighbor_count[edge[0]]++;
|
||||
neighbor_count[edge[1]]++;
|
||||
}
|
||||
|
||||
/* Compute an offset into the array of neighbor edges based on the counts. */
|
||||
Array<int> neighbor_offsets(verts_num);
|
||||
int start = 0;
|
||||
for (const int i : IndexRange(verts_num)) {
|
||||
neighbor_offsets[i] = start;
|
||||
start += neighbor_count[i];
|
||||
Array<int> neighbor_offsets_data(verts_num + 1, 0);
|
||||
for (const int vert : edges.cast<int>()) {
|
||||
neighbor_offsets_data[vert]++;
|
||||
}
|
||||
offset_indices::accumulate_counts_to_offsets(neighbor_offsets_data);
|
||||
const OffsetIndices<int> neighbor_offsets(neighbor_offsets_data);
|
||||
|
||||
/* Use as an index into the "neighbor group" for each vertex. */
|
||||
Array<int> used_slots(verts_num, 0);
|
||||
|
@ -109,8 +102,8 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
|||
for (const int i : edges.index_range()) {
|
||||
const int v1 = edges[i][0];
|
||||
const int v2 = edges[i][1];
|
||||
neighbors[neighbor_offsets[v1] + used_slots[v1]] = v2;
|
||||
neighbors[neighbor_offsets[v2] + used_slots[v2]] = v1;
|
||||
neighbors[neighbor_offsets[v1].start() + used_slots[v1]] = v2;
|
||||
neighbors[neighbor_offsets[v2].start() + used_slots[v2]] = v1;
|
||||
used_slots[v1]++;
|
||||
used_slots[v2]++;
|
||||
}
|
||||
|
@ -120,7 +113,7 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
|||
|
||||
for (const int start_vert : IndexRange(verts_num)) {
|
||||
/* The vertex will be part of a cyclic curve. */
|
||||
if (neighbor_count[start_vert] == 2) {
|
||||
if (neighbor_offsets[start_vert].size() == 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -129,9 +122,9 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
|||
continue;
|
||||
}
|
||||
|
||||
for (const int i : IndexRange(neighbor_count[start_vert])) {
|
||||
for (const int neighbor : neighbors.as_span().slice(neighbor_offsets[start_vert])) {
|
||||
int current_vert = start_vert;
|
||||
int next_vert = neighbors[neighbor_offsets[current_vert] + i];
|
||||
int next_vert = neighbor;
|
||||
|
||||
if (unused_edges[next_vert] == 0) {
|
||||
continue;
|
||||
|
@ -150,11 +143,11 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
|||
unused_edges[current_vert]--;
|
||||
unused_edges[last_vert]--;
|
||||
|
||||
if (neighbor_count[current_vert] != 2) {
|
||||
if (neighbor_offsets[current_vert].size() != 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
const int offset = neighbor_offsets[current_vert];
|
||||
const int offset = neighbor_offsets[current_vert].start();
|
||||
const int next_a = neighbors[offset];
|
||||
const int next_b = neighbors[offset + 1];
|
||||
next_vert = (last_vert == next_a) ? next_b : next_a;
|
||||
|
@ -172,7 +165,7 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
|||
}
|
||||
|
||||
int current_vert = start_vert;
|
||||
int next_vert = neighbors[neighbor_offsets[current_vert]];
|
||||
int next_vert = neighbors[neighbor_offsets[current_vert].start()];
|
||||
|
||||
curve_offsets.append(vert_indices.size());
|
||||
vert_indices.append(current_vert);
|
||||
|
@ -186,7 +179,7 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
|||
unused_edges[current_vert]--;
|
||||
unused_edges[last_vert]--;
|
||||
|
||||
const int offset = neighbor_offsets[current_vert];
|
||||
const int offset = neighbor_offsets[current_vert].start();
|
||||
const int next_a = neighbors[offset];
|
||||
const int next_b = neighbors[offset + 1];
|
||||
next_vert = (last_vert == next_a) ? next_b : next_a;
|
||||
|
@ -198,7 +191,7 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(const int verts_num,
|
|||
return {std::move(vert_indices), std::move(curve_offsets), cyclic_curves};
|
||||
}
|
||||
|
||||
static bke::CurvesGeometry edges_to_curves_convert(
|
||||
BLI_NOINLINE static bke::CurvesGeometry edges_to_curves_convert(
|
||||
const Mesh &mesh,
|
||||
const Span<int2> edges,
|
||||
const bke::AnonymousAttributePropagationInfo &propagation_info)
|
||||
|
|
|
@ -89,6 +89,24 @@ static float dist_signed_squared_to_edge(float2 probe, float2 uva, float2 uvb)
|
|||
return numerator_ssq / edge_length_squared;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return the larger dimension of `extent`, factoring in the target aspect ratio.
|
||||
*/
|
||||
static float get_aspect_scaled_extent(const rctf &extent, const UVPackIsland_Params ¶ms)
|
||||
{
|
||||
const float width = BLI_rctf_size_x(&extent);
|
||||
const float height = BLI_rctf_size_y(&extent);
|
||||
return std::max(width / params.target_aspect_y, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* \return true iff `b` is a preferred layout over `a`, given the packing parameters supplied.
|
||||
*/
|
||||
static bool is_larger(const rctf &a, const rctf &b, const UVPackIsland_Params ¶ms)
|
||||
{
|
||||
return get_aspect_scaled_extent(b, params) < get_aspect_scaled_extent(a, params);
|
||||
}
|
||||
|
||||
PackIsland::PackIsland()
|
||||
{
|
||||
/* Initialize to the identity transform. */
|
||||
|
@ -345,12 +363,11 @@ static void pack_islands_alpaca_turbo(const int64_t start_index,
|
|||
const Span<UVAABBIsland *> islands,
|
||||
const float target_aspect_y,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
float *r_max_u,
|
||||
float *r_max_v)
|
||||
rctf *r_extent)
|
||||
{
|
||||
/* Exclude an initial AABB near the origin. */
|
||||
float next_u1 = *r_max_u;
|
||||
float next_v1 = *r_max_v;
|
||||
float next_u1 = r_extent->xmax;
|
||||
float next_v1 = r_extent->ymax;
|
||||
bool zigzag = next_u1 < next_v1 * target_aspect_y; /* Horizontal or Vertical strip? */
|
||||
|
||||
float u0 = zigzag ? next_u1 : 0.0f;
|
||||
|
@ -395,9 +412,8 @@ static void pack_islands_alpaca_turbo(const int64_t start_index,
|
|||
}
|
||||
}
|
||||
|
||||
/* Write back total pack AABB. */
|
||||
*r_max_u = next_u1;
|
||||
*r_max_v = next_v1;
|
||||
/* Write back extent. */
|
||||
*r_extent = {0.0f, next_u1, 0.0f, next_v1};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,12 +473,11 @@ static void pack_islands_alpaca_rotate(const int64_t start_index,
|
|||
const Span<UVAABBIsland *> islands,
|
||||
const float target_aspect_y,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
float *r_max_u,
|
||||
float *r_max_v)
|
||||
rctf *r_extent)
|
||||
{
|
||||
/* Exclude an initial AABB near the origin. */
|
||||
float next_u1 = *r_max_u;
|
||||
float next_v1 = *r_max_v;
|
||||
float next_u1 = r_extent->xmax;
|
||||
float next_v1 = r_extent->ymax;
|
||||
bool zigzag = next_u1 / target_aspect_y < next_v1; /* Horizontal or Vertical strip? */
|
||||
|
||||
/* Track an AABB "hole" which may be filled at any time. */
|
||||
|
@ -553,8 +568,25 @@ static void pack_islands_alpaca_rotate(const int64_t start_index,
|
|||
}
|
||||
|
||||
/* Write back total pack AABB. */
|
||||
*r_max_u = next_u1;
|
||||
*r_max_v = next_v1;
|
||||
*r_extent = {0.0f, next_u1, 0.0f, next_v1};
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a fast algorithm to pack the supplied `aabbs`.
|
||||
*/
|
||||
static void pack_islands_fast(const int64_t start_index,
|
||||
const Span<UVAABBIsland *> aabbs,
|
||||
const bool rotate,
|
||||
const float target_aspect_y,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
rctf *r_extent)
|
||||
{
|
||||
if (rotate) {
|
||||
pack_islands_alpaca_rotate(start_index, aabbs, target_aspect_y, r_phis, r_extent);
|
||||
}
|
||||
else {
|
||||
pack_islands_alpaca_turbo(start_index, aabbs, target_aspect_y, r_phis, r_extent);
|
||||
}
|
||||
}
|
||||
|
||||
/** Frits Göbel, 1979. */
|
||||
|
@ -594,24 +626,11 @@ static void pack_gobel(const Span<UVAABBIsland *> aabbs,
|
|||
}
|
||||
}
|
||||
/* Attempt to find an "Optimal" packing of the islands, e.g. assuming squares or circles. */
|
||||
static void pack_island_optimal_pack(const Span<UVAABBIsland *> aabbs,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
const bool all_can_rotate,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
float *r_max_u,
|
||||
float *r_max_v)
|
||||
static void pack_islands_optimal_pack(const Span<UVAABBIsland *> aabbs,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
rctf *r_extent)
|
||||
{
|
||||
*r_max_u = 0.0f;
|
||||
*r_max_v = 0.0f;
|
||||
if (!all_can_rotate) {
|
||||
/* Alpaca will produce an optimal layout when the inputs are uniform squares. */
|
||||
pack_islands_alpaca_turbo(0, aabbs, params.target_aspect_y, r_phis, r_max_u, r_max_v);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For many rectangle-only inputs, alpaca_rotate can produce an optimal layout. */
|
||||
pack_islands_alpaca_rotate(0, aabbs, params.target_aspect_y, r_phis, r_max_u, r_max_v);
|
||||
|
||||
if (params.shape_method == ED_UVPACK_SHAPE_AABB) {
|
||||
return;
|
||||
}
|
||||
|
@ -647,10 +666,10 @@ static void pack_island_optimal_pack(const Span<UVAABBIsland *> aabbs,
|
|||
int n = a * a + a + 3 + floorf((a - 1) * sqrtf(2.0f));
|
||||
if (island_count_patch == n) {
|
||||
float max_uv_gobel = large_uv * (a + 1 + sqrtf(0.5f));
|
||||
if (max_uv_gobel < std::max(*r_max_u, *r_max_v)) {
|
||||
rctf extent = {0.0f, max_uv_gobel, 0.0f, max_uv_gobel};
|
||||
if (is_larger(*r_extent, extent, params)) {
|
||||
*r_extent = extent;
|
||||
pack_gobel(aabbs, large_uv, a, r_phis);
|
||||
*r_max_u = max_uv_gobel;
|
||||
*r_max_v = max_uv_gobel;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -659,10 +678,9 @@ static void pack_island_optimal_pack(const Span<UVAABBIsland *> aabbs,
|
|||
|
||||
/* Wrapper around #BLI_box_pack_2d. */
|
||||
static void pack_island_box_pack_2d(const Span<UVAABBIsland *> aabbs,
|
||||
const float target_aspect_y,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
float *r_max_u,
|
||||
float *r_max_v)
|
||||
rctf *r_extent)
|
||||
{
|
||||
/* Allocate storage. */
|
||||
BoxPack *box_array = static_cast<BoxPack *>(
|
||||
|
@ -671,7 +689,7 @@ static void pack_island_box_pack_2d(const Span<UVAABBIsland *> aabbs,
|
|||
/* Prepare for box_pack_2d. */
|
||||
for (const int64_t i : aabbs.index_range()) {
|
||||
BoxPack *box = box_array + i;
|
||||
box->w = aabbs[i]->uv_diagonal.x / target_aspect_y;
|
||||
box->w = aabbs[i]->uv_diagonal.x / params.target_aspect_y;
|
||||
box->h = aabbs[i]->uv_diagonal.y;
|
||||
}
|
||||
|
||||
|
@ -680,19 +698,17 @@ static void pack_island_box_pack_2d(const Span<UVAABBIsland *> aabbs,
|
|||
float box_max_u = 0.0f;
|
||||
float box_max_v = 0.0f;
|
||||
BLI_box_pack_2d(box_array, int(aabbs.size()), sort_boxes, &box_max_u, &box_max_v);
|
||||
box_max_u *= target_aspect_y;
|
||||
box_max_u *= params.target_aspect_y;
|
||||
rctf extent = {0.0f, box_max_u, 0.0f, box_max_v};
|
||||
|
||||
if (std::max(box_max_u / target_aspect_y, box_max_v) <
|
||||
std::max(*r_max_u / target_aspect_y, *r_max_v))
|
||||
{
|
||||
*r_max_u = box_max_u;
|
||||
*r_max_v = box_max_v;
|
||||
if (is_larger(*r_extent, extent, params)) {
|
||||
*r_extent = extent;
|
||||
/* Write back box_pack UVs. */
|
||||
for (const int64_t i : aabbs.index_range()) {
|
||||
BoxPack *box = box_array + i;
|
||||
uv_phi &phi = *(uv_phi *)&r_phis[aabbs[i]->index];
|
||||
phi.rotation = 0.0f; /* #BLI_box_pack_2d never rotates. */
|
||||
phi.translation.x = (box->x + box->w * 0.5f) * target_aspect_y;
|
||||
phi.translation.x = (box->x + box->w * 0.5f) * params.target_aspect_y;
|
||||
phi.translation.y = (box->y + box->h * 0.5f);
|
||||
}
|
||||
}
|
||||
|
@ -1020,8 +1036,7 @@ class UVMinimumEnclosingSquareFinder {
|
|||
bounds.ymin -= margin_;
|
||||
bounds.xmax += margin_;
|
||||
bounds.ymax += margin_;
|
||||
const float current_quad = std::max(BLI_rctf_size_x(&bounds) / params_->target_aspect_y,
|
||||
BLI_rctf_size_y(&bounds));
|
||||
const float current_quad = get_aspect_scaled_extent(bounds, *params_);
|
||||
if (best_quad > current_quad) {
|
||||
best_quad = current_quad;
|
||||
best_angle = angle;
|
||||
|
@ -1067,8 +1082,7 @@ static bool rotate_inside_square(const Span<UVAABBIsland *> island_indices,
|
|||
const float scale,
|
||||
const float margin,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
float *r_max_u,
|
||||
float *r_max_v)
|
||||
rctf *r_extent)
|
||||
{
|
||||
if (island_indices.size() == 0) {
|
||||
return false; /* Nothing to do. */
|
||||
|
@ -1088,7 +1102,7 @@ static bool rotate_inside_square(const Span<UVAABBIsland *> island_indices,
|
|||
}
|
||||
|
||||
UVMinimumEnclosingSquareFinder square_finder(scale, margin, ¶ms);
|
||||
square_finder.best_quad = std::max(*r_max_u / params.target_aspect_y, *r_max_v) * 0.999f;
|
||||
square_finder.best_quad = get_aspect_scaled_extent(*r_extent, params) * 0.999f;
|
||||
|
||||
float matrix[2][2];
|
||||
|
||||
|
@ -1137,9 +1151,9 @@ static bool rotate_inside_square(const Span<UVAABBIsland *> island_indices,
|
|||
r_phis[i].translation.x -= square_finder.best_bounds.xmin;
|
||||
r_phis[i].translation.y -= square_finder.best_bounds.ymin;
|
||||
}
|
||||
*r_max_u = BLI_rctf_size_x(&square_finder.best_bounds);
|
||||
*r_max_v = BLI_rctf_size_y(&square_finder.best_bounds);
|
||||
return true; /* `r_phis` were modified. */
|
||||
r_extent->xmax = BLI_rctf_size_x(&square_finder.best_bounds);
|
||||
r_extent->ymax = BLI_rctf_size_y(&square_finder.best_bounds);
|
||||
return true; /* `r_phis` and `r_extent` were modified. */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1157,18 +1171,17 @@ static bool rotate_inside_square(const Span<UVAABBIsland *> island_indices,
|
|||
* Performance would normally be `O(n^4)`, however the occupancy
|
||||
* bitmap_radix is fixed, which gives a reduced time complexity of `O(n^3)`.
|
||||
*/
|
||||
static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
||||
const Span<PackIsland *> islands,
|
||||
const float scale,
|
||||
const float margin,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
float *r_max_u,
|
||||
float *r_max_v)
|
||||
static int64_t pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
||||
const Span<PackIsland *> islands,
|
||||
const float scale,
|
||||
const float margin,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
rctf *r_extent)
|
||||
{
|
||||
blender::Array<uv_phi> phis(r_phis.size());
|
||||
Occupancy occupancy(guess_initial_scale(islands, scale, margin));
|
||||
float max_u = 0.0f;
|
||||
float max_v = 0.0f;
|
||||
rctf extent = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* A heuristic to improve final layout efficiency by making an
|
||||
* intermediate call to #rotate_inside_square. */
|
||||
|
@ -1192,7 +1205,7 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
|||
const int64_t island_index = island_indices[traced_islands]->index;
|
||||
PackIsland *island = islands[island_index];
|
||||
const float island_scale = island->can_scale_(params) ? scale : 1.0f;
|
||||
occupancy.trace_island(island, r_phis[island_index], island_scale, margin, true);
|
||||
occupancy.trace_island(island, phis[island_index], island_scale, margin, true);
|
||||
traced_islands++;
|
||||
}
|
||||
|
||||
|
@ -1201,7 +1214,7 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
|||
uv_phi phi;
|
||||
phi.translation = island->pivot_;
|
||||
phi.rotation = 0.0f;
|
||||
r_phis[island_indices[i]->index] = phi;
|
||||
phis[island_indices[i]->index] = phi;
|
||||
i++;
|
||||
placed_can_rotate = false;
|
||||
continue;
|
||||
|
@ -1262,30 +1275,31 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
|||
}
|
||||
|
||||
/* Place island. */
|
||||
r_phis[island_indices[i]->index] = phi;
|
||||
phis[island_indices[i]->index] = phi;
|
||||
i++; /* Next island. */
|
||||
|
||||
if (i == square_milestone && placed_can_rotate) {
|
||||
if (rotate_inside_square(island_indices.take_front(i),
|
||||
islands,
|
||||
params,
|
||||
scale,
|
||||
margin,
|
||||
r_phis,
|
||||
&max_u,
|
||||
&max_v))
|
||||
if (rotate_inside_square(
|
||||
island_indices.take_front(i), islands, params, scale, margin, phis, &extent))
|
||||
{
|
||||
scan_line = 0;
|
||||
traced_islands = 0;
|
||||
occupancy.clear();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update top-right corner. */
|
||||
float2 top_right = island->get_diagonal_support(island_scale, phi.rotation, margin) +
|
||||
phi.translation;
|
||||
max_u = std::max(top_right.x, max_u);
|
||||
max_v = std::max(top_right.y, max_v);
|
||||
extent.xmax = std::max(top_right.x, extent.xmax);
|
||||
extent.ymax = std::max(top_right.y, extent.ymax);
|
||||
|
||||
if (!is_larger(*r_extent, extent, params)) {
|
||||
if (i >= square_milestone) {
|
||||
return 0; /* Early exit, we already have a better layout. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Heuristics to reduce size of brute-force search. */
|
||||
if (i < 128 || (i & 31) == 16) {
|
||||
|
@ -1296,8 +1310,15 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
|||
}
|
||||
}
|
||||
|
||||
*r_max_u = max_u;
|
||||
*r_max_v = max_v;
|
||||
if (!is_larger(*r_extent, extent, params)) {
|
||||
return 0;
|
||||
}
|
||||
*r_extent = extent;
|
||||
for (const int64_t i : phis.index_range()) {
|
||||
const int64_t island_index = island_indices[i]->index;
|
||||
r_phis[island_index] = phis[island_index];
|
||||
}
|
||||
return phis.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1415,20 +1436,27 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
|||
}
|
||||
const int64_t max_box_pack = std::min(alpaca_cutoff, islands.size());
|
||||
|
||||
float optimal_pack_u = 0.0f;
|
||||
float optimal_pack_v = 0.0f;
|
||||
rctf extent = {0.0f, 1e30f, 0.0f, 1e30f};
|
||||
|
||||
if (all_can_translate) {
|
||||
pack_island_optimal_pack(aabbs.as_span().take_front(max_box_pack),
|
||||
params,
|
||||
all_can_rotate,
|
||||
r_phis,
|
||||
&optimal_pack_u,
|
||||
&optimal_pack_v);
|
||||
pack_islands_fast(0,
|
||||
aabbs.as_span().take_front(max_box_pack),
|
||||
all_can_rotate,
|
||||
params.target_aspect_y,
|
||||
r_phis,
|
||||
&extent);
|
||||
}
|
||||
|
||||
if (all_can_translate) {
|
||||
pack_islands_optimal_pack(aabbs.as_span().take_front(max_box_pack), params, r_phis, &extent);
|
||||
}
|
||||
|
||||
/* Call box_pack_2d (slow for large N.) */
|
||||
if (all_can_translate) {
|
||||
pack_island_box_pack_2d(aabbs.as_span().take_front(max_box_pack), params, r_phis, &extent);
|
||||
}
|
||||
|
||||
/* Call xatlas (slow for large N.) */
|
||||
float max_u = 1e30f;
|
||||
float max_v = 1e30f;
|
||||
switch (params.shape_method) {
|
||||
case ED_UVPACK_SHAPE_CONVEX:
|
||||
case ED_UVPACK_SHAPE_CONCAVE:
|
||||
|
@ -1438,53 +1466,23 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
|||
margin,
|
||||
params,
|
||||
r_phis,
|
||||
&max_u,
|
||||
&max_v);
|
||||
&extent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call box_pack_2d (slow for large N.) */
|
||||
if (all_can_translate) {
|
||||
pack_island_box_pack_2d(
|
||||
aabbs.as_span().take_front(max_box_pack), params.target_aspect_y, r_phis, &max_u, &max_v);
|
||||
|
||||
if (std::max(optimal_pack_u / params.target_aspect_y, optimal_pack_v) <
|
||||
std::max(max_u / params.target_aspect_y, max_v))
|
||||
{
|
||||
pack_island_optimal_pack(aabbs.as_span().take_front(max_box_pack),
|
||||
params,
|
||||
all_can_rotate,
|
||||
r_phis,
|
||||
&max_u,
|
||||
&max_v);
|
||||
}
|
||||
}
|
||||
|
||||
/* At this stage, `max_u` and `max_v` contain the box_pack/xatlas UVs. */
|
||||
|
||||
if (all_can_rotate) {
|
||||
rotate_inside_square(aabbs.as_span().take_front(max_box_pack),
|
||||
islands,
|
||||
params,
|
||||
scale,
|
||||
margin,
|
||||
r_phis,
|
||||
&max_u,
|
||||
&max_v);
|
||||
rotate_inside_square(
|
||||
aabbs.as_span().take_front(max_box_pack), islands, params, scale, margin, r_phis, &extent);
|
||||
}
|
||||
|
||||
/* Call Alpaca. */
|
||||
if (all_can_rotate) {
|
||||
pack_islands_alpaca_rotate(
|
||||
max_box_pack, aabbs, params.target_aspect_y, r_phis, &max_u, &max_v);
|
||||
}
|
||||
else {
|
||||
pack_islands_alpaca_turbo(max_box_pack, aabbs, params.target_aspect_y, r_phis, &max_u, &max_v);
|
||||
}
|
||||
/* Call fast packer for remaining islands. */
|
||||
pack_islands_fast(max_box_pack, aabbs, all_can_rotate, params.target_aspect_y, r_phis, &extent);
|
||||
|
||||
return std::max(max_u / params.target_aspect_y, max_v);
|
||||
return get_aspect_scaled_extent(extent, params);
|
||||
}
|
||||
|
||||
/** Find the optimal scale to pack islands into the unit square.
|
||||
|
|
|
@ -841,9 +841,11 @@ if(WITH_GTESTS)
|
|||
tests/gpu_testing.cc
|
||||
|
||||
tests/framebuffer_test.cc
|
||||
tests/immediate_test.cc
|
||||
tests/index_buffer_test.cc
|
||||
tests/push_constants_test.cc
|
||||
tests/shader_test.cc
|
||||
tests/state_blend_test.cc
|
||||
tests/storage_buffer_test.cc
|
||||
tests/texture_test.cc
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
#include "GPU_framebuffer.h"
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_shader_builtin.h"
|
||||
#include "gpu_testing.hh"
|
||||
|
||||
#include "BLI_math_vector.hh"
|
||||
|
||||
namespace blender::gpu::tests {
|
||||
|
||||
static constexpr int Size = 256;
|
||||
|
||||
static void test_immediate_one_plane()
|
||||
{
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(Size,
|
||||
Size,
|
||||
false,
|
||||
GPU_RGBA16F,
|
||||
GPU_TEXTURE_USAGE_ATTACHMENT |
|
||||
GPU_TEXTURE_USAGE_HOST_READ,
|
||||
nullptr);
|
||||
BLI_assert(offscreen != nullptr);
|
||||
GPU_offscreen_bind(offscreen, false);
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
float4 color(1.0, 0.5, 0.25, 1.0);
|
||||
immUniformColor4fv(color);
|
||||
immBegin(GPU_PRIM_TRI_STRIP, 4);
|
||||
immVertex3f(pos, -1.0f, 1.0f, 0.0f);
|
||||
immVertex3f(pos, 1.0f, 1.0f, 0.0f);
|
||||
immVertex3f(pos, -1.0f, -1.0f, 0.0f);
|
||||
immVertex3f(pos, 1.0f, -1.0f, 0.0f);
|
||||
immEnd();
|
||||
|
||||
GPU_offscreen_unbind(offscreen, false);
|
||||
GPU_flush();
|
||||
|
||||
/* Read back data and perform some basic tests. */
|
||||
float read_data[4 * Size * Size];
|
||||
GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, &read_data);
|
||||
for (int pixel_index = 0; pixel_index < Size * Size; pixel_index++) {
|
||||
float4 read_color = float4(&read_data[pixel_index * 4]);
|
||||
EXPECT_EQ(read_color, color);
|
||||
}
|
||||
|
||||
GPU_offscreen_free(offscreen);
|
||||
}
|
||||
GPU_TEST(immediate_one_plane)
|
||||
|
||||
/**
|
||||
* Draws two planes with two different colors.
|
||||
* - Tests that both planes are stored in the same buffer (depends on backend).
|
||||
* - Test that data of the first plane isn't overwritten by the second plane.
|
||||
* (push constants, buffer, bind points etc.)
|
||||
*/
|
||||
static void test_immediate_two_planes()
|
||||
{
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(Size,
|
||||
Size,
|
||||
false,
|
||||
GPU_RGBA16F,
|
||||
GPU_TEXTURE_USAGE_ATTACHMENT |
|
||||
GPU_TEXTURE_USAGE_HOST_READ,
|
||||
nullptr);
|
||||
BLI_assert(offscreen != nullptr);
|
||||
GPU_offscreen_bind(offscreen, false);
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
float4 color(1.0, 0.5, 0.25, 1.0);
|
||||
immUniformColor4fv(color);
|
||||
immBegin(GPU_PRIM_TRI_STRIP, 4);
|
||||
immVertex3f(pos, -1.0f, 1.0f, 0.0f);
|
||||
immVertex3f(pos, 0.0f, 1.0f, 0.0f);
|
||||
immVertex3f(pos, -1.0f, -1.0f, 0.0f);
|
||||
immVertex3f(pos, 0.0f, -1.0f, 0.0f);
|
||||
immEnd();
|
||||
|
||||
float4 color2(0.25, 0.5, 1.0, 1.0);
|
||||
immUniformColor4fv(color2);
|
||||
immBegin(GPU_PRIM_TRI_STRIP, 4);
|
||||
immVertex3f(pos, 0.0f, 1.0f, 0.0f);
|
||||
immVertex3f(pos, 1.0f, 1.0f, 0.0f);
|
||||
immVertex3f(pos, 0.0f, -1.0f, 0.0f);
|
||||
immVertex3f(pos, 1.0f, -1.0f, 0.0f);
|
||||
immEnd();
|
||||
|
||||
GPU_offscreen_unbind(offscreen, false);
|
||||
GPU_flush();
|
||||
|
||||
/* Read back data and perform some basic tests.
|
||||
* Not performing detailed tests as there might be driver specific limitations. */
|
||||
float read_data[4 * Size * Size];
|
||||
GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, &read_data);
|
||||
int64_t color_num = 0;
|
||||
int64_t color2_num = 0;
|
||||
for (int pixel_index = 0; pixel_index < Size * Size; pixel_index++) {
|
||||
float4 read_color = float4(&read_data[pixel_index * 4]);
|
||||
if (read_color == color) {
|
||||
color_num++;
|
||||
}
|
||||
else if (read_color == color2) {
|
||||
color2_num++;
|
||||
}
|
||||
else {
|
||||
EXPECT_TRUE(read_color == color || read_color == color2);
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(color_num > 0);
|
||||
EXPECT_TRUE(color2_num > 0);
|
||||
|
||||
GPU_offscreen_free(offscreen);
|
||||
}
|
||||
GPU_TEST(immediate_two_planes)
|
||||
|
||||
} // namespace blender::gpu::tests
|
|
@ -0,0 +1,132 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
#include "gpu_testing.hh"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
#include "GPU_batch_presets.h"
|
||||
#include "GPU_framebuffer.h"
|
||||
#include "GPU_matrix.h"
|
||||
|
||||
#include "BLI_math_vector.hh"
|
||||
|
||||
#include "intern/draw_cache.h"
|
||||
|
||||
namespace blender::gpu::tests {
|
||||
|
||||
template<eGPUBlend blend_type>
|
||||
void blend_test(float4 source_a, float4 source_b, float4 expected_result)
|
||||
{
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(1,
|
||||
1,
|
||||
false,
|
||||
GPU_RGBA16F,
|
||||
GPU_TEXTURE_USAGE_ATTACHMENT |
|
||||
GPU_TEXTURE_USAGE_HOST_READ,
|
||||
nullptr);
|
||||
BLI_assert(offscreen != nullptr);
|
||||
GPU_offscreen_bind(offscreen, false);
|
||||
GPUTexture *color_texture = GPU_offscreen_color_texture(offscreen);
|
||||
GPU_texture_clear(color_texture, GPU_DATA_FLOAT, source_a);
|
||||
|
||||
GPUBatch *batch = DRW_cache_quad_get();
|
||||
|
||||
GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
GPU_batch_uniform_4fv(batch, "color", source_b);
|
||||
GPU_blend(blend_type);
|
||||
|
||||
GPU_batch_draw(batch);
|
||||
GPU_offscreen_unbind(offscreen, false);
|
||||
GPU_flush();
|
||||
|
||||
float4 read_back;
|
||||
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, &read_back);
|
||||
EXPECT_EQ(read_back, expected_result);
|
||||
|
||||
GPU_offscreen_free(offscreen);
|
||||
DRW_shape_cache_free();
|
||||
}
|
||||
|
||||
static void test_blend_none()
|
||||
{
|
||||
blend_test<GPU_BLEND_NONE>(float4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f));
|
||||
}
|
||||
GPU_TEST(blend_none)
|
||||
|
||||
static void test_blend_alpha()
|
||||
{
|
||||
blend_test<GPU_BLEND_ALPHA>(float4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(0.5f, 0.5f, 0.5f, 1.0f));
|
||||
}
|
||||
GPU_TEST(blend_alpha)
|
||||
|
||||
static void test_blend_alpha_premult()
|
||||
{
|
||||
blend_test<GPU_BLEND_ALPHA_PREMULT>(float4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(0.5f, 1.0f, 0.5f, 1.0f));
|
||||
}
|
||||
GPU_TEST(blend_alpha_premult)
|
||||
|
||||
static void test_blend_additive()
|
||||
{
|
||||
blend_test<GPU_BLEND_ADDITIVE>(float4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(1.0f, 0.5f, 1.0f, 1.0f));
|
||||
}
|
||||
GPU_TEST(blend_additive)
|
||||
|
||||
static void test_blend_additive_premult()
|
||||
{
|
||||
blend_test<GPU_BLEND_ADDITIVE_PREMULT>(float4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(1.0f, 1.0f, 1.0f, 1.5f));
|
||||
}
|
||||
GPU_TEST(blend_additive_premult)
|
||||
|
||||
static void test_blend_multiply()
|
||||
{
|
||||
blend_test<GPU_BLEND_MULTIPLY>(float4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||
}
|
||||
GPU_TEST(blend_multiply)
|
||||
|
||||
static void test_blend_subtract()
|
||||
{
|
||||
blend_test<GPU_BLEND_SUBTRACT>(float4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(1.0f, 0.0f, 1.0f, 0.5f));
|
||||
}
|
||||
GPU_TEST(blend_subtract)
|
||||
|
||||
static void test_blend_invert()
|
||||
{
|
||||
blend_test<GPU_BLEND_INVERT>(float4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
GPU_TEST(blend_invert)
|
||||
|
||||
static void test_blend_oit()
|
||||
{
|
||||
blend_test<GPU_BLEND_OIT>(float4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(1.0f, 2.0f, 1.0f, 0.5f));
|
||||
}
|
||||
GPU_TEST(blend_oit)
|
||||
|
||||
static void test_blend_background()
|
||||
{
|
||||
blend_test<GPU_BLEND_BACKGROUND>(float4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
float4(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
float4(0.5f, 0.5f, 0.5f, 0.5f));
|
||||
}
|
||||
GPU_TEST(blend_background)
|
||||
|
||||
} // namespace blender::gpu::tests
|
|
@ -45,9 +45,11 @@ void VKIndexBuffer::bind_as_ssbo(uint binding)
|
|||
VKContext &context = *VKContext::get();
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
|
||||
const std::optional<VKDescriptorSet::Location> location =
|
||||
shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
BLI_assert_msg(location, "Locations to SSBOs should always exist.");
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, *location);
|
||||
}
|
||||
|
||||
void VKIndexBuffer::read(uint32_t *data) const
|
||||
|
|
|
@ -196,11 +196,13 @@ const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
|||
return descriptor_set_location(shader_input);
|
||||
}
|
||||
|
||||
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
||||
const std::optional<VKDescriptorSet::Location> VKShaderInterface::descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const
|
||||
{
|
||||
const ShaderInput *shader_input = shader_input_get(bind_type, binding);
|
||||
BLI_assert(shader_input);
|
||||
if (shader_input == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return descriptor_set_location(shader_input);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class VKShaderInterface : public ShaderInterface {
|
|||
|
||||
const VKDescriptorSet::Location descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource &resource) const;
|
||||
const VKDescriptorSet::Location descriptor_set_location(
|
||||
const std::optional<VKDescriptorSet::Location> descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
|
||||
|
||||
/** Get the Layout of the shader. */
|
||||
|
|
|
@ -37,9 +37,11 @@ void VKStorageBuffer::bind(int slot)
|
|||
}
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot);
|
||||
shader->pipeline_get().descriptor_set_get().bind(*this, location);
|
||||
const std::optional<VKDescriptorSet::Location> location =
|
||||
shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot);
|
||||
BLI_assert_msg(location, "Locations to SSBOs should always exist.");
|
||||
shader->pipeline_get().descriptor_set_get().bind(*this, *location);
|
||||
}
|
||||
|
||||
void VKStorageBuffer::unbind() {}
|
||||
|
|
|
@ -319,9 +319,13 @@ void VKTexture::image_bind(int binding)
|
|||
VKContext &context = *VKContext::get();
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::IMAGE, binding);
|
||||
shader->pipeline_get().descriptor_set_get().image_bind(*this, location);
|
||||
const std::optional<VKDescriptorSet::Location> location =
|
||||
shader_interface.descriptor_set_location(shader::ShaderCreateInfo::Resource::BindType::IMAGE,
|
||||
binding);
|
||||
if (location) {
|
||||
VKDescriptorSetTracker &descriptor_set = shader->pipeline_get().descriptor_set_get();
|
||||
descriptor_set.image_bind(*this, *location);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -44,10 +44,12 @@ void VKUniformBuffer::bind(int slot, shader::ShaderCreateInfo::Resource::BindTyp
|
|||
VKContext &context = *VKContext::get();
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(bind_type,
|
||||
slot);
|
||||
VKDescriptorSetTracker &descriptor_set = shader->pipeline_get().descriptor_set_get();
|
||||
descriptor_set.bind(*this, location);
|
||||
const std::optional<VKDescriptorSet::Location> location =
|
||||
shader_interface.descriptor_set_location(bind_type, slot);
|
||||
if (location) {
|
||||
VKDescriptorSetTracker &descriptor_set = shader->pipeline_get().descriptor_set_get();
|
||||
descriptor_set.bind(*this, *location);
|
||||
}
|
||||
}
|
||||
|
||||
void VKUniformBuffer::bind(int slot)
|
||||
|
|
|
@ -27,9 +27,11 @@ void VKVertexBuffer::bind_as_ssbo(uint binding)
|
|||
VKContext &context = *VKContext::get();
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
|
||||
const std::optional<VKDescriptorSet::Location> location =
|
||||
shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
BLI_assert_msg(location, "Locations to SSBOs should always exist.");
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, *location);
|
||||
}
|
||||
|
||||
void VKVertexBuffer::bind_as_texture(uint /*binding*/) {}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
.drotAngle = 0, \
|
||||
.quat = _DNA_DEFAULT_UNIT_QT, \
|
||||
.dquat = _DNA_DEFAULT_UNIT_QT, \
|
||||
.flag = OB_FLAG_USE_SIMULATION_CACHE, \
|
||||
.protectflag = OB_LOCK_ROT4D, \
|
||||
\
|
||||
.dt = OB_TEXTURE, \
|
||||
|
|
|
@ -720,8 +720,8 @@ enum {
|
|||
|
||||
#define OB_FROMDUPLI (1 << 9)
|
||||
#define OB_DONE (1 << 10) /* unknown state, clear before use */
|
||||
#define OB_FLAG_USE_SIMULATION_CACHE (1 << 11)
|
||||
#ifdef DNA_DEPRECATED_ALLOW
|
||||
# define OB_FLAG_UNUSED_11 (1 << 11) /* cleared */
|
||||
# define OB_FLAG_UNUSED_12 (1 << 12) /* cleared */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3679,6 +3679,12 @@ static void rna_def_object(BlenderRNA *brna)
|
|||
RNA_def_property_struct_type(prop, "RigidBodyConstraint");
|
||||
RNA_def_property_ui_text(prop, "Rigid Body Constraint", "Constraint constraining rigid bodies");
|
||||
|
||||
prop = RNA_def_property(srna, "use_simulation_cache", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", OB_FLAG_USE_SIMULATION_CACHE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Use Simulation Cache", "Cache all frames during simulation nodes playback");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
rna_def_object_visibility(srna);
|
||||
|
||||
/* instancing */
|
||||
|
|
|
@ -1351,6 +1351,14 @@ static GeometrySet compute_geometry(const bNodeTree &btree,
|
|||
nmd_orig->runtime_eval_log = eval_log.release();
|
||||
}
|
||||
|
||||
if (DEG_is_active(ctx->depsgraph)) {
|
||||
/* When caching is turned off, remove all states except the last which was just created in this
|
||||
* evaluation. Check if active status to avoid changing original data in other depsgraphs. */
|
||||
if (!(ctx->object->flag & OB_FLAG_USE_SIMULATION_CACHE)) {
|
||||
nmd_orig->simulation_cache->clear_prev_states();
|
||||
}
|
||||
}
|
||||
|
||||
return output_geometry_set;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,19 @@
|
|||
* \ingroup cmpnodes
|
||||
*/
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_movieclip_types.h"
|
||||
#include "DNA_tracking_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_movieclip.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
@ -20,15 +26,22 @@
|
|||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
#include "GPU_uniform_buffer.h"
|
||||
|
||||
#include "COM_node_operation.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "node_composite_util.hh"
|
||||
|
||||
namespace blender::nodes::node_composite_planetrackdeform_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodePlaneTrackDeformData)
|
||||
|
||||
static void cmp_node_planetrackdeform_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>(N_("Image"));
|
||||
b.add_input<decl::Color>(N_("Image")).compositor_skip_realization();
|
||||
b.add_output<decl::Color>(N_("Image"));
|
||||
b.add_output<decl::Float>(N_("Plane"));
|
||||
}
|
||||
|
@ -116,9 +129,144 @@ class PlaneTrackDeformOperation : public NodeOperation {
|
|||
|
||||
void execute() override
|
||||
{
|
||||
get_input("Image").pass_through(get_result("Image"));
|
||||
get_result("Plane").allocate_invalid();
|
||||
context().set_info_message("Viewport compositor setup not fully supported");
|
||||
MovieTrackingPlaneTrack *plane_track = get_plane_track();
|
||||
|
||||
Result &input_image = get_input("Image");
|
||||
Result &output_image = get_result("Image");
|
||||
Result &output_mask = get_result("Plane");
|
||||
if (input_image.is_single_value() || !plane_track) {
|
||||
if (output_image.should_compute()) {
|
||||
input_image.pass_through(output_image);
|
||||
}
|
||||
if (output_mask.should_compute()) {
|
||||
output_mask.allocate_single_value();
|
||||
output_mask.set_float_value(1.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const Array<float4x4> homography_matrices = compute_homography_matrices(plane_track);
|
||||
|
||||
GPUShader *shader = shader_manager().get("compositor_plane_deform_motion_blur");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_shader_uniform_1i(shader, "number_of_motion_blur_samples", homography_matrices.size());
|
||||
|
||||
GPUUniformBuf *matrices_buffer = GPU_uniformbuf_create_ex(
|
||||
homography_matrices.size() * sizeof(float4x4),
|
||||
homography_matrices.data(),
|
||||
"Plane Track Deform Homography Matrices");
|
||||
const int ubo_location = GPU_shader_get_ubo_binding(shader, "homography_matrices");
|
||||
GPU_uniformbuf_bind(matrices_buffer, ubo_location);
|
||||
|
||||
GPU_texture_mipmap_mode(input_image.texture(), true, true);
|
||||
GPU_texture_anisotropic_filter(input_image.texture(), true);
|
||||
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
|
||||
input_image.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const Domain domain = compute_domain();
|
||||
output_image.allocate_texture(domain);
|
||||
output_image.bind_as_image(shader, "output_img");
|
||||
|
||||
output_mask.allocate_texture(domain);
|
||||
output_mask.bind_as_image(shader, "mask_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, domain.size);
|
||||
|
||||
input_image.unbind_as_texture();
|
||||
output_image.unbind_as_image();
|
||||
output_mask.unbind_as_image();
|
||||
GPU_shader_unbind();
|
||||
|
||||
GPU_uniformbuf_unbind(matrices_buffer);
|
||||
GPU_uniformbuf_free(matrices_buffer);
|
||||
}
|
||||
|
||||
Domain compute_domain() override
|
||||
{
|
||||
MovieTrackingPlaneTrack *plane_track = get_plane_track();
|
||||
|
||||
Result &input_image = get_input("Image");
|
||||
if (input_image.is_single_value() || !plane_track) {
|
||||
return input_image.domain();
|
||||
}
|
||||
|
||||
return Domain(get_movie_clip_size());
|
||||
}
|
||||
|
||||
Array<float4x4> compute_homography_matrices(MovieTrackingPlaneTrack *plane_track)
|
||||
{
|
||||
/* We evaluate at the frames in the range [frame - shutter, frame + shutter], if no motion blur
|
||||
* is enabled or the motion blur samples is set to 1, we just evaluate at the current frame. */
|
||||
const int samples = use_motion_blur() ? node_storage(bnode()).motion_blur_samples : 1;
|
||||
const float shutter = samples != 1 ? node_storage(bnode()).motion_blur_shutter : 0.0f;
|
||||
const float start_frame = context().get_frame_number() - shutter;
|
||||
const float frame_step = (shutter * 2.0f) / samples;
|
||||
|
||||
Array<float4x4> matrices(samples);
|
||||
for (int i = 0; i < samples; i++) {
|
||||
const float frame = start_frame + frame_step * i;
|
||||
const float clip_frame = BKE_movieclip_remap_scene_to_clip_frame(get_movie_clip(), frame);
|
||||
|
||||
float corners[4][2];
|
||||
BKE_tracking_plane_marker_get_subframe_corners(plane_track, clip_frame, corners);
|
||||
|
||||
/* Compute a 2D projection matrix that projects from the corners of the image in normalized
|
||||
* coordinates into the corners of the tracking plane. */
|
||||
float3x3 homography_matrix;
|
||||
float identity_corners[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
|
||||
BKE_tracking_homography_between_two_quads(
|
||||
corners, identity_corners, homography_matrix.ptr());
|
||||
|
||||
/* Store in a 4x4 matrix due to the alignment requirements of GPU uniform buffers. */
|
||||
matrices[i] = float4x4(homography_matrix);
|
||||
}
|
||||
|
||||
return matrices;
|
||||
}
|
||||
|
||||
MovieTrackingPlaneTrack *get_plane_track()
|
||||
{
|
||||
MovieClip *movie_clip = get_movie_clip();
|
||||
|
||||
if (!movie_clip) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MovieTrackingObject *tracking_object = BKE_tracking_object_get_named(
|
||||
&movie_clip->tracking, node_storage(bnode()).tracking_object);
|
||||
|
||||
if (!tracking_object) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return BKE_tracking_object_find_plane_track_with_name(tracking_object,
|
||||
node_storage(bnode()).plane_track_name);
|
||||
}
|
||||
|
||||
int2 get_movie_clip_size()
|
||||
{
|
||||
MovieClipUser user = *DNA_struct_default_get(MovieClipUser);
|
||||
BKE_movieclip_user_set_frame(&user, context().get_frame_number());
|
||||
|
||||
int2 size;
|
||||
BKE_movieclip_get_size(get_movie_clip(), &user, &size.x, &size.y);
|
||||
return size;
|
||||
}
|
||||
|
||||
bool use_motion_blur()
|
||||
{
|
||||
return get_flags() & CMP_NODE_PLANE_TRACK_DEFORM_FLAG_MOTION_BLUR;
|
||||
}
|
||||
|
||||
CMPNodePlaneTrackDeformFlags get_flags()
|
||||
{
|
||||
return static_cast<CMPNodePlaneTrackDeformFlags>(node_storage(bnode()).flag);
|
||||
}
|
||||
|
||||
MovieClip *get_movie_clip()
|
||||
{
|
||||
return reinterpret_cast<MovieClip *>(bnode().id);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -142,8 +290,6 @@ void register_node_type_cmp_planetrackdeform()
|
|||
node_type_storage(
|
||||
&ntype, "NodePlaneTrackDeformData", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
ntype.realtime_compositor_unsupported_message = N_(
|
||||
"Node not supported in the Viewport compositor");
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
|
|
@ -115,10 +115,8 @@ static void expand_mesh(Mesh &mesh,
|
|||
const int vert_expand,
|
||||
const int edge_expand,
|
||||
const int poly_expand,
|
||||
const int loop_expand,
|
||||
const AnonymousAttributePropagationInfo &propagation_info)
|
||||
const int loop_expand)
|
||||
{
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
/* Remove types that aren't supported for interpolation in this node. */
|
||||
if (vert_expand != 0) {
|
||||
CustomData_free_layers(&mesh.vdata, CD_ORCO, mesh.totvert);
|
||||
|
@ -202,7 +200,9 @@ static MutableSpan<int> get_orig_index_layer(Mesh &mesh, const eAttrDomain domai
|
|||
* result point.
|
||||
*/
|
||||
template<typename T, typename GetMixIndicesFn>
|
||||
void copy_with_mixing(MutableSpan<T> dst, Span<T> src, GetMixIndicesFn get_mix_indices_fn)
|
||||
void copy_with_mixing(const Span<T> src,
|
||||
const GetMixIndicesFn &get_mix_indices_fn,
|
||||
MutableSpan<T> dst)
|
||||
{
|
||||
threading::parallel_for(dst.index_range(), 512, [&](const IndexRange range) {
|
||||
bke::attribute_math::DefaultPropagationMixer<T> mixer{dst.slice(range)};
|
||||
|
@ -215,6 +215,15 @@ void copy_with_mixing(MutableSpan<T> dst, Span<T> src, GetMixIndicesFn get_mix_i
|
|||
});
|
||||
}
|
||||
|
||||
template<typename GetMixIndicesFn>
|
||||
void copy_with_mixing(const GSpan src, const GetMixIndicesFn &get_mix_indices_fn, GMutableSpan dst)
|
||||
{
|
||||
bke::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
copy_with_mixing(src.typed<T>(), get_mix_indices_fn, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
static Array<Vector<int>> create_vert_to_edge_map(const int vert_size,
|
||||
const Span<int2> edges,
|
||||
const int vert_offset = 0)
|
||||
|
@ -246,61 +255,67 @@ static void extrude_mesh_vertices(Mesh &mesh,
|
|||
evaluator.evaluate();
|
||||
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||
|
||||
/* This allows parallelizing attribute mixing for new edges. */
|
||||
Array<Vector<int>> vert_to_edge_map = create_vert_to_edge_map(orig_vert_size, mesh.edges());
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
|
||||
expand_mesh(mesh, selection.size(), selection.size(), 0, 0, propagation_info);
|
||||
Set<AttributeIDRef> point_ids;
|
||||
Set<AttributeIDRef> edge_ids;
|
||||
mesh.attributes().for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
|
||||
if (meta_data.data_type == CD_PROP_STRING) {
|
||||
return true;
|
||||
}
|
||||
if (meta_data.domain == ATTR_DOMAIN_POINT) {
|
||||
if (id.name() != "position") {
|
||||
point_ids.add(id);
|
||||
}
|
||||
}
|
||||
else if (meta_data.domain == ATTR_DOMAIN_EDGE) {
|
||||
if (id.name() != ".edge_verts") {
|
||||
edge_ids.add(id);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
/* This allows parallelizing attribute mixing for new edges. */
|
||||
Array<Vector<int>> vert_to_edge_map;
|
||||
if (!edge_ids.is_empty()) {
|
||||
vert_to_edge_map = create_vert_to_edge_map(orig_vert_size, mesh.edges());
|
||||
}
|
||||
|
||||
expand_mesh(mesh, selection.size(), selection.size(), 0, 0);
|
||||
|
||||
const IndexRange new_vert_range{orig_vert_size, selection.size()};
|
||||
const IndexRange new_edge_range{orig_edge_size, selection.size()};
|
||||
|
||||
MutableSpan<float3> new_positions = mesh.vert_positions_for_write().slice(new_vert_range);
|
||||
MutableSpan<int2> new_edges = mesh.edges_for_write().slice(new_edge_range);
|
||||
|
||||
for (const int i_selection : selection.index_range()) {
|
||||
new_edges[i_selection] = int2(selection[i_selection], new_vert_range[i_selection]);
|
||||
}
|
||||
|
||||
MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
||||
|
||||
attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
|
||||
if (!ELEM(meta_data.domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE)) {
|
||||
return true;
|
||||
}
|
||||
if (ELEM(id.name(), ".corner_vert", ".corner_edge", ".edge_verts")) {
|
||||
return true;
|
||||
}
|
||||
if (meta_data.data_type == CD_PROP_STRING) {
|
||||
return true;
|
||||
}
|
||||
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
|
||||
id, meta_data.domain, meta_data.data_type);
|
||||
switch (attribute.domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
/* New vertices copy the attribute values from their source vertex. */
|
||||
array_utils::gather(attribute.span, selection, attribute.span.slice(new_vert_range));
|
||||
break;
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
MutableSpan<T> data = attribute.span.typed<T>();
|
||||
/* New edge values are mixed from of all the edges connected to the source vertex. */
|
||||
copy_with_mixing(data.slice(new_edge_range), data.as_span(), [&](const int i) {
|
||||
return vert_to_edge_map[selection[i]].as_span();
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
/* New vertices copy the attribute values from their source vertex. */
|
||||
for (const AttributeIDRef &id : point_ids) {
|
||||
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
||||
array_utils::gather(attribute.span, selection, attribute.span.slice(new_vert_range));
|
||||
attribute.finish();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/* New edge values are mixed from of all the edges connected to the source vertex. */
|
||||
for (const AttributeIDRef &id : edge_ids) {
|
||||
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
||||
copy_with_mixing(
|
||||
attribute.span,
|
||||
[&](const int i) { return vert_to_edge_map[selection[i]].as_span(); },
|
||||
attribute.span.slice(new_edge_range));
|
||||
attribute.finish();
|
||||
}
|
||||
|
||||
MutableSpan<float3> positions = mesh.vert_positions_for_write();
|
||||
MutableSpan<float3> new_positions = positions.slice(new_vert_range);
|
||||
threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
new_positions[i] += offsets[selection[i]];
|
||||
new_positions[i] = positions[selection[i]] + offsets[selection[i]];
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -436,12 +451,12 @@ static void extrude_mesh_edges(Mesh &mesh,
|
|||
/* Every new polygon is a quad with four corners. */
|
||||
const IndexRange new_loop_range{orig_loop_size, new_poly_range.size() * 4};
|
||||
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
expand_mesh(mesh,
|
||||
new_vert_range.size(),
|
||||
connect_edge_range.size() + duplicate_edge_range.size(),
|
||||
new_poly_range.size(),
|
||||
new_loop_range.size(),
|
||||
propagation_info);
|
||||
new_loop_range.size());
|
||||
|
||||
MutableSpan<int2> edges = mesh.edges_for_write();
|
||||
MutableSpan<int2> connect_edges = edges.slice(connect_edge_range);
|
||||
|
@ -518,8 +533,7 @@ static void extrude_mesh_edges(Mesh &mesh,
|
|||
if (ELEM(id.name(), ".corner_vert", ".corner_edge", ".edge_verts")) {
|
||||
return true;
|
||||
}
|
||||
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
|
||||
id, meta_data.domain, meta_data.data_type);
|
||||
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
||||
|
||||
bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
@ -537,18 +551,19 @@ static void extrude_mesh_edges(Mesh &mesh,
|
|||
array_utils::gather(data.as_span(), edge_selection, duplicate_data);
|
||||
|
||||
/* Edges connected to original vertices mix values of selected connected edges. */
|
||||
MutableSpan<T> connect_data = data.slice(connect_edge_range);
|
||||
copy_with_mixing(connect_data, duplicate_data.as_span(), [&](const int i_new_vert) {
|
||||
return new_vert_to_duplicate_edge_map[i_new_vert].as_span();
|
||||
});
|
||||
copy_with_mixing(
|
||||
duplicate_data.as_span(),
|
||||
[&](const int i) { return new_vert_to_duplicate_edge_map[i].as_span(); },
|
||||
data.slice(connect_edge_range));
|
||||
break;
|
||||
}
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
/* Attribute values for new faces are a mix of the values of faces connected to the its
|
||||
* original edge. */
|
||||
copy_with_mixing(data.slice(new_poly_range), data.as_span(), [&](const int i) {
|
||||
return edge_to_poly_map[edge_selection[i]].as_span();
|
||||
});
|
||||
copy_with_mixing(
|
||||
data.as_span(),
|
||||
[&](const int i) { return edge_to_poly_map[edge_selection[i]].as_span(); },
|
||||
data.slice(new_poly_range));
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -800,12 +815,12 @@ static void extrude_mesh_face_regions(Mesh &mesh,
|
|||
/* The loops that form the new side faces. */
|
||||
const IndexRange side_loop_range{orig_corner_verts.size(), side_poly_range.size() * 4};
|
||||
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
expand_mesh(mesh,
|
||||
new_vert_range.size(),
|
||||
connect_edge_range.size() + boundary_edge_range.size() + new_inner_edge_range.size(),
|
||||
side_poly_range.size(),
|
||||
side_loop_range.size(),
|
||||
propagation_info);
|
||||
side_loop_range.size());
|
||||
|
||||
MutableSpan<int2> edges = mesh.edges_for_write();
|
||||
MutableSpan<int2> connect_edges = edges.slice(connect_edge_range);
|
||||
|
@ -918,8 +933,7 @@ static void extrude_mesh_face_regions(Mesh &mesh,
|
|||
if (ELEM(id.name(), ".corner_vert", ".corner_edge", ".edge_verts")) {
|
||||
return true;
|
||||
}
|
||||
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
|
||||
id, meta_data.domain, meta_data.data_type);
|
||||
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
||||
|
||||
bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
@ -941,10 +955,10 @@ static void extrude_mesh_face_regions(Mesh &mesh,
|
|||
array_utils::gather(data.as_span(), new_inner_edge_indices.as_span(), new_inner_data);
|
||||
|
||||
/* Edges connected to original vertices mix values of selected connected edges. */
|
||||
MutableSpan<T> connect_data = data.slice(connect_edge_range);
|
||||
copy_with_mixing(connect_data, boundary_data.as_span(), [&](const int i) {
|
||||
return new_vert_to_duplicate_edge_map[i].as_span();
|
||||
});
|
||||
copy_with_mixing(
|
||||
boundary_data.as_span(),
|
||||
[&](const int i) { return new_vert_to_duplicate_edge_map[i].as_span(); },
|
||||
data.slice(connect_edge_range));
|
||||
break;
|
||||
}
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
|
@ -1132,12 +1146,12 @@ static void extrude_individual_mesh_faces(
|
|||
const IndexRange side_poly_range{orig_polys.size(), duplicate_edge_range.size()};
|
||||
const IndexRange side_loop_range{orig_loop_size, side_poly_range.size() * 4};
|
||||
|
||||
remove_non_propagated_attributes(mesh.attributes_for_write(), propagation_info);
|
||||
expand_mesh(mesh,
|
||||
new_vert_range.size(),
|
||||
connect_edge_range.size() + duplicate_edge_range.size(),
|
||||
side_poly_range.size(),
|
||||
side_loop_range.size(),
|
||||
propagation_info);
|
||||
side_loop_range.size());
|
||||
|
||||
MutableSpan<float3> new_positions = mesh.vert_positions_for_write().slice(new_vert_range);
|
||||
MutableSpan<int2> edges = mesh.edges_for_write();
|
||||
|
@ -1218,8 +1232,7 @@ static void extrude_individual_mesh_faces(
|
|||
if (ELEM(id.name(), ".corner_vert", ".corner_edge", ".edge_verts")) {
|
||||
return true;
|
||||
}
|
||||
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
|
||||
id, meta_data.domain, meta_data.data_type);
|
||||
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
|
||||
|
||||
bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
|
|
@ -1205,9 +1205,20 @@ elseif(WIN32)
|
|||
|
||||
endif()
|
||||
|
||||
# Filenames change slightly between FFMPEG versions check both 5.0 and fallback to 4.4
|
||||
# Filenames change slightly between FFMPEG versions check both 6.0 and fallback to 5.0
|
||||
# to ease the transition between versions.
|
||||
if(EXISTS "${LIBDIR}/ffmpeg/lib/avcodec-59.dll")
|
||||
if(EXISTS "${LIBDIR}/ffmpeg/lib/avcodec-60.dll")
|
||||
windows_install_shared_manifest(
|
||||
FILES
|
||||
${LIBDIR}/ffmpeg/lib/avcodec-60.dll
|
||||
${LIBDIR}/ffmpeg/lib/avformat-60.dll
|
||||
${LIBDIR}/ffmpeg/lib/avdevice-60.dll
|
||||
${LIBDIR}/ffmpeg/lib/avutil-58.dll
|
||||
${LIBDIR}/ffmpeg/lib/swscale-7.dll
|
||||
${LIBDIR}/ffmpeg/lib/swresample-4.dll
|
||||
ALL
|
||||
)
|
||||
else()
|
||||
windows_install_shared_manifest(
|
||||
FILES
|
||||
${LIBDIR}/ffmpeg/lib/avcodec-59.dll
|
||||
|
@ -1218,17 +1229,6 @@ elseif(WIN32)
|
|||
${LIBDIR}/ffmpeg/lib/swresample-4.dll
|
||||
ALL
|
||||
)
|
||||
else()
|
||||
windows_install_shared_manifest(
|
||||
FILES
|
||||
${LIBDIR}/ffmpeg/lib/avcodec-58.dll
|
||||
${LIBDIR}/ffmpeg/lib/avformat-58.dll
|
||||
${LIBDIR}/ffmpeg/lib/avdevice-58.dll
|
||||
${LIBDIR}/ffmpeg/lib/avutil-56.dll
|
||||
${LIBDIR}/ffmpeg/lib/swscale-5.dll
|
||||
${LIBDIR}/ffmpeg/lib/swresample-3.dll
|
||||
ALL
|
||||
)
|
||||
endif()
|
||||
windows_install_shared_manifest(
|
||||
FILES
|
||||
|
|
Loading…
Reference in New Issue