Merge branch 'master' into geometry-nodes-simulation

This commit is contained in:
Hans Goudey 2022-12-14 14:02:15 -06:00
commit ab8d77359b
140 changed files with 2680 additions and 1969 deletions

View File

@ -26,13 +26,13 @@ set(SBOMCONTENTS)
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if(_variableName MATCHES "CPE$")
string(REPLACE ":" ";" CPE_LIST ${${_variableName}})
string(REPLACE "_CPE" "_ID" CPE_DEPNAME ${_variableName})
list(GET CPE_LIST 3 CPE_VENDOR)
list(GET CPE_LIST 4 CPE_NAME)
list(GET CPE_LIST 5 CPE_VERSION)
set(${CPE_DEPNAME} "${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}")
set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION},,,\n")
string(REPLACE ":" ";" CPE_LIST ${${_variableName}})
string(REPLACE "_CPE" "_ID" CPE_DEPNAME ${_variableName})
list(GET CPE_LIST 3 CPE_VENDOR)
list(GET CPE_LIST 4 CPE_NAME)
list(GET CPE_LIST 5 CPE_VERSION)
set(${CPE_DEPNAME} "${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}")
set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION},,,\n")
endif()
endforeach()
configure_file(${CMAKE_SOURCE_DIR}/cmake/cve_check.csv.in ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv @ONLY)

View File

@ -32,12 +32,13 @@ function(download_source dep)
message("Checking source : ${dep} (${TARGET_FILE})")
if(NOT EXISTS ${TARGET_FILE})
message("Checking source : ${dep} - source not found downloading from ${TARGET_URI}")
file(DOWNLOAD ${TARGET_URI} ${TARGET_FILE}
TIMEOUT 1800 # seconds
EXPECTED_HASH ${TARGET_HASH_TYPE}=${TARGET_HASH}
TLS_VERIFY ON
SHOW_PROGRESS
)
file(
DOWNLOAD ${TARGET_URI} ${TARGET_FILE}
TIMEOUT 1800 # seconds
EXPECTED_HASH ${TARGET_HASH_TYPE}=${TARGET_HASH}
TLS_VERIFY ON
SHOW_PROGRESS
)
endif()
if(EXISTS ${TARGET_FILE})
# Sometimes the download fails, but that is not a

View File

@ -1,9 +1,55 @@
# SPDX-License-Identifier: GPL-2.0-or-later
set(FFMPEG_CFLAGS "-I${mingw_LIBDIR}/lame/include -I${mingw_LIBDIR}/openjpeg/include/ -I${mingw_LIBDIR}/ogg/include -I${mingw_LIBDIR}/vorbis/include -I${mingw_LIBDIR}/theora/include -I${mingw_LIBDIR}/opus/include -I${mingw_LIBDIR}/vpx/include -I${mingw_LIBDIR}/x264/include -I${mingw_LIBDIR}/xvidcore/include -I${mingw_LIBDIR}/zlib/include -I${mingw_LIBDIR}/aom/include")
set(FFMPEG_LDFLAGS "-L${mingw_LIBDIR}/lame/lib -L${mingw_LIBDIR}/openjpeg/lib -L${mingw_LIBDIR}/ogg/lib -L${mingw_LIBDIR}/vorbis/lib -L${mingw_LIBDIR}/theora/lib -L${mingw_LIBDIR}/opus/lib -L${mingw_LIBDIR}/vpx/lib -L${mingw_LIBDIR}/x264/lib -L${mingw_LIBDIR}/xvidcore/lib -L${mingw_LIBDIR}/zlib/lib -L${mingw_LIBDIR}/aom/lib")
set(FFMPEG_EXTRA_FLAGS --pkg-config-flags=--static --extra-cflags=${FFMPEG_CFLAGS} --extra-ldflags=${FFMPEG_LDFLAGS})
set(FFMPEG_ENV PKG_CONFIG_PATH=${mingw_LIBDIR}/openjpeg/lib/pkgconfig:${mingw_LIBDIR}/x264/lib/pkgconfig:${mingw_LIBDIR}/vorbis/lib/pkgconfig:${mingw_LIBDIR}/ogg/lib/pkgconfig:${mingw_LIBDIR}:${mingw_LIBDIR}/vpx/lib/pkgconfig:${mingw_LIBDIR}/theora/lib/pkgconfig:${mingw_LIBDIR}/openjpeg/lib/pkgconfig:${mingw_LIBDIR}/opus/lib/pkgconfig:${mingw_LIBDIR}/aom/lib/pkgconfig:)
if(WIN32)
set(temp_LIBDIR ${mingw_LIBDIR})
else()
set(temp_LIBDIR ${LIBDIR})
endif()
set(FFMPEG_CFLAGS "\
-I${temp_LIBDIR}/lame/include \
-I${temp_LIBDIR}/openjpeg/include/ \
-I${temp_LIBDIR}/ogg/include \
-I${temp_LIBDIR}/vorbis/include \
-I${temp_LIBDIR}/theora/include \
-I${temp_LIBDIR}/opus/include \
-I${temp_LIBDIR}/vpx/include \
-I${temp_LIBDIR}/x264/include \
-I${temp_LIBDIR}/xvidcore/include \
-I${temp_LIBDIR}/zlib/include \
-I${temp_LIBDIR}/aom/include"
)
set(FFMPEG_LDFLAGS "\
-L${temp_LIBDIR}/lame/lib \
-L${temp_LIBDIR}/openjpeg/lib \
-L${temp_LIBDIR}/ogg/lib \
-L${temp_LIBDIR}/vorbis/lib \
-L${temp_LIBDIR}/theora/lib \
-L${temp_LIBDIR}/opus/lib \
-L${temp_LIBDIR}/vpx/lib \
-L${temp_LIBDIR}/x264/lib \
-L${temp_LIBDIR}/xvidcore/lib \
-L${temp_LIBDIR}/zlib/lib \
-L${temp_LIBDIR}/aom/lib"
)
set(FFMPEG_EXTRA_FLAGS
--pkg-config-flags=--static
--extra-cflags=${FFMPEG_CFLAGS}
--extra-ldflags=${FFMPEG_LDFLAGS}
)
set(FFMPEG_ENV "PKG_CONFIG_PATH=\
${temp_LIBDIR}/openjpeg/lib/pkgconfig:\
${temp_LIBDIR}/x264/lib/pkgconfig:\
${temp_LIBDIR}/vorbis/lib/pkgconfig:\
${temp_LIBDIR}/ogg/lib/pkgconfig:\
${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"
)
unset(temp_LIBDIR)
if(WIN32)
set(FFMPEG_ENV set ${FFMPEG_ENV} &&)

View File

@ -32,9 +32,10 @@ add_dependencies(
if(BUILD_MODE STREQUAL Release AND WIN32)
ExternalProject_Add_Step(external_freetype after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freetype ${HARVEST_TARGET}/freetype
# harfbuzz *NEEDS* to find freetype.lib and will not be conviced to take alternative names so just give it
# what it wants.
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/freetype/lib/freetype2st.lib ${LIBDIR}/freetype/lib/freetype.lib
# harfbuzz *NEEDS* to find freetype.lib and will not be conviced to take alternative names so just give it
# what it wants.
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/freetype/lib/freetype2st.lib ${LIBDIR}/freetype/lib/freetype.lib
DEPENDEES install
)
endif()

View File

@ -40,19 +40,21 @@ endif()
if(BUILD_MODE STREQUAL Release AND WIN32)
ExternalProject_Add_Step(external_gmp after_install
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-3.dll.def ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def
COMMAND lib /def:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def /machine:x64 /out:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/gmp/bin/libgmp-10.dll ${HARVEST_TARGET}/gmp/lib/libgmp-10.dll
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.lib ${HARVEST_TARGET}/gmp/lib/libgmp-10.lib
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/gmp/include ${HARVEST_TARGET}/gmp/include
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-3.dll.def ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def
COMMAND lib /def:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def /machine:x64 /out:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/gmp/bin/libgmp-10.dll ${HARVEST_TARGET}/gmp/lib/libgmp-10.dll
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.lib ${HARVEST_TARGET}/gmp/lib/libgmp-10.lib
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/gmp/include ${HARVEST_TARGET}/gmp/include
DEPENDEES install
)
endif()
if(BUILD_MODE STREQUAL Debug AND WIN32)
ExternalProject_Add_Step(external_gmp after_install
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-3.dll.def ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def
COMMAND lib /def:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def /machine:x64 /out:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.lib
ExternalProject_Add_Step(external_gmp after_install
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-3.dll.def ${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def
COMMAND lib /def:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.def /machine:x64 /out:${BUILD_DIR}/gmp/src/external_gmp/.libs/libgmp-10.lib
DEPENDEES install
)
endif()

View File

@ -33,6 +33,7 @@ ExternalProject_Add(external_harfbuzz
add_dependencies(
external_harfbuzz
external_python
external_freetype
# Needed for `MESON`.
external_python_site_packages
)

View File

@ -14,14 +14,14 @@ if(WIN32)
if(BUILD_MODE STREQUAL Release)
add_custom_target(Harvest_Release_Results
COMMAND # jpeg rename libfile + copy include
${CMAKE_COMMAND} -E copy ${LIBDIR}/jpeg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpeg/include/ ${HARVEST_TARGET}/jpeg/include/ &&
# png
${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static.lib ${HARVEST_TARGET}/png/lib/libpng.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ &&
# freeglut-> opengl
${CMAKE_COMMAND} -E copy ${LIBDIR}/freeglut/lib/freeglut_static.lib ${HARVEST_TARGET}/opengl/lib/freeglut_static.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freeglut/include/ ${HARVEST_TARGET}/opengl/include/ &&
${CMAKE_COMMAND} -E copy ${LIBDIR}/jpeg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpeg/include/ ${HARVEST_TARGET}/jpeg/include/ &&
# png
${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static.lib ${HARVEST_TARGET}/png/lib/libpng.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ &&
# freeglut-> opengl
${CMAKE_COMMAND} -E copy ${LIBDIR}/freeglut/lib/freeglut_static.lib ${HARVEST_TARGET}/opengl/lib/freeglut_static.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freeglut/include/ ${HARVEST_TARGET}/opengl/include/ &&
DEPENDS
)
endif()

View File

@ -34,21 +34,21 @@ elseif(UNIX)
endif()
set(ISPC_EXTRA_ARGS
-DISPC_NO_DUMPS=On
-DISPC_INCLUDE_EXAMPLES=Off
-DISPC_INCLUDE_TESTS=Off
-DLLVM_ROOT=${LIBDIR}/llvm/lib/cmake/llvm
-DLLVM_LIBRARY_DIR=${LIBDIR}/llvm/lib
-DCLANG_EXECUTABLE=${LIBDIR}/llvm/bin/clang
-DCLANGPP_EXECUTABLE=${LIBDIR}/llvm/bin/clang++
-DISPC_INCLUDE_TESTS=Off
-DCLANG_LIBRARY_DIR=${LIBDIR}/llvm/lib
-DCLANG_INCLUDE_DIRS=${LIBDIR}/llvm/include
-DPython3_ROOT_DIR=${LIBDIR}/python/
-DPython3_EXECUTABLE=${PYTHON_BINARY}
${ISPC_EXTRA_ARGS_WIN}
${ISPC_EXTRA_ARGS_APPLE}
${ISPC_EXTRA_ARGS_UNIX}
-DISPC_NO_DUMPS=On
-DISPC_INCLUDE_EXAMPLES=Off
-DISPC_INCLUDE_TESTS=Off
-DLLVM_ROOT=${LIBDIR}/llvm/lib/cmake/llvm
-DLLVM_LIBRARY_DIR=${LIBDIR}/llvm/lib
-DCLANG_EXECUTABLE=${LIBDIR}/llvm/bin/clang
-DCLANGPP_EXECUTABLE=${LIBDIR}/llvm/bin/clang++
-DISPC_INCLUDE_TESTS=Off
-DCLANG_LIBRARY_DIR=${LIBDIR}/llvm/lib
-DCLANG_INCLUDE_DIRS=${LIBDIR}/llvm/include
-DPython3_ROOT_DIR=${LIBDIR}/python/
-DPython3_EXECUTABLE=${PYTHON_BINARY}
${ISPC_EXTRA_ARGS_WIN}
${ISPC_EXTRA_ARGS_APPLE}
${ISPC_EXTRA_ARGS_UNIX}
)
ExternalProject_Add(external_ispc

View File

@ -105,10 +105,10 @@ if(WIN32)
)
endif()
else()
ExternalProject_Add_Step(external_opencolorio after_install
COMMAND cp ${LIBDIR}/yamlcpp/lib/libyaml-cpp.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${LIBDIR}/expat/lib/libexpat.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${LIBDIR}/pystring/lib/libpystring.a ${LIBDIR}/opencolorio/lib/
DEPENDEES install
)
ExternalProject_Add_Step(external_opencolorio after_install
COMMAND cp ${LIBDIR}/yamlcpp/lib/libyaml-cpp.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${LIBDIR}/expat/lib/libexpat.a ${LIBDIR}/opencolorio/lib/
COMMAND cp ${LIBDIR}/pystring/lib/libpystring.a ${LIBDIR}/opencolorio/lib/
DEPENDEES install
)
endif()

View File

@ -39,8 +39,10 @@ if(MSVC)
)
if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_openjpeg_msvc after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openjpeg_msvc/lib ${HARVEST_TARGET}/openjpeg/lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openjpeg_msvc/include ${HARVEST_TARGET}/openjpeg/include
COMMAND
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openjpeg_msvc/lib ${HARVEST_TARGET}/openjpeg/lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openjpeg_msvc/include ${HARVEST_TARGET}/openjpeg/include
DEPENDEES install
)
endif()

View File

@ -4,10 +4,10 @@
# library itself does not depend on them, so should give no problems.
set(OPENPGL_EXTRA_ARGS
-DOPENPGL_BUILD_STATIC=ON
-DOPENPGL_TBB_ROOT=${LIBDIR}/tbb
-DTBB_ROOT=${LIBDIR}/tbb
-DCMAKE_DEBUG_POSTFIX=_d
-DOPENPGL_BUILD_STATIC=ON
-DOPENPGL_TBB_ROOT=${LIBDIR}/tbb
-DTBB_ROOT=${LIBDIR}/tbb
-DCMAKE_DEBUG_POSTFIX=_d
)
if(TBB_STATIC_LIBRARY)
@ -18,17 +18,17 @@ if(TBB_STATIC_LIBRARY)
endif()
ExternalProject_Add(external_openpgl
URL file://${PACKAGE_DIR}/${OPENPGL_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${OPENPGL_HASH_TYPE}=${OPENPGL_HASH}
PREFIX ${BUILD_DIR}/openpgl
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openpgl ${DEFAULT_CMAKE_FLAGS} ${OPENPGL_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/openpgl
URL file://${PACKAGE_DIR}/${OPENPGL_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${OPENPGL_HASH_TYPE}=${OPENPGL_HASH}
PREFIX ${BUILD_DIR}/openpgl
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openpgl ${DEFAULT_CMAKE_FLAGS} ${OPENPGL_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/openpgl
)
add_dependencies(
external_openpgl
external_tbb
external_openpgl
external_tbb
)
if(WIN32)

View File

@ -15,8 +15,8 @@ if((WIN32 AND BUILD_MODE STREQUAL Release) OR UNIX)
)
if(WIN32)
ExternalProject_Add_Step(external_potrace after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/potrace ${HARVEST_TARGET}/potrace
DEPENDEES install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/potrace ${HARVEST_TARGET}/potrace
DEPENDEES install
)
endif()
endif()

View File

@ -2,37 +2,36 @@
if(WIN32)
if(MSVC14) # vs2015 has timespec
set(PTHREAD_CPPFLAGS "/I. /DHAVE_CONFIG_H /D_TIMESPEC_DEFINED ")
else() # everything before doesn't
set(PTHREAD_CPPFLAGS "/I. /DHAVE_CONFIG_H ")
endif()
if(MSVC14) # vs2015 has timespec
set(PTHREAD_CPPFLAGS "/I. /DHAVE_CONFIG_H /D_TIMESPEC_DEFINED ")
else() # everything before doesn't
set(PTHREAD_CPPFLAGS "/I. /DHAVE_CONFIG_H ")
endif()
set(PTHREADS_BUILD cd ${BUILD_DIR}/pthreads/src/external_pthreads/ && cd && nmake VC-static /e CPPFLAGS=${PTHREAD_CPPFLAGS})
set(PTHREADS_BUILD cd ${BUILD_DIR}/pthreads/src/external_pthreads/ && cd && nmake VC-static /e CPPFLAGS=${PTHREAD_CPPFLAGS})
ExternalProject_Add(external_pthreads
URL file://${PACKAGE_DIR}/${PTHREADS_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${PTHREADS_HASH_TYPE}=${PTHREADS_HASH}
PREFIX ${BUILD_DIR}/pthreads
CONFIGURE_COMMAND echo .
PATCH_COMMAND COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/pthreads/src/external_pthreads < ${PATCH_DIR}/pthreads.diff
BUILD_COMMAND ${PTHREADS_BUILD}
INSTALL_COMMAND COMMAND
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/libpthreadVC3${LIBEXT} ${LIBDIR}/pthreads/lib/pthreadVC3${LIBEXT} &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/pthread.h ${LIBDIR}/pthreads/inc/pthread.h &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/sched.h ${LIBDIR}/pthreads/inc/sched.h &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/semaphore.h ${LIBDIR}/pthreads/inc/semaphore.h &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/_ptw32.h ${LIBDIR}/pthreads/inc/_ptw32.h
INSTALL_DIR ${LIBDIR}/pthreads
ExternalProject_Add(external_pthreads
URL file://${PACKAGE_DIR}/${PTHREADS_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${PTHREADS_HASH_TYPE}=${PTHREADS_HASH}
PREFIX ${BUILD_DIR}/pthreads
CONFIGURE_COMMAND echo .
PATCH_COMMAND COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/pthreads/src/external_pthreads < ${PATCH_DIR}/pthreads.diff
BUILD_COMMAND ${PTHREADS_BUILD}
INSTALL_COMMAND COMMAND
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/libpthreadVC3${LIBEXT} ${LIBDIR}/pthreads/lib/pthreadVC3${LIBEXT} &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/pthread.h ${LIBDIR}/pthreads/inc/pthread.h &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/sched.h ${LIBDIR}/pthreads/inc/sched.h &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/semaphore.h ${LIBDIR}/pthreads/inc/semaphore.h &&
${CMAKE_COMMAND} -E copy ${BUILD_DIR}/pthreads/src/external_pthreads/_ptw32.h ${LIBDIR}/pthreads/inc/_ptw32.h
INSTALL_DIR ${LIBDIR}/pthreads
)
if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_pthreads after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/inc/ ${HARVEST_TARGET}/pthreads/include/
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/lib/ ${HARVEST_TARGET}/pthreads/lib
DEPENDEES install
)
if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_pthreads after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/inc/ ${HARVEST_TARGET}/pthreads/include/
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/pthreads/lib/ ${HARVEST_TARGET}/pthreads/lib
DEPENDEES install
)
endif()
endif()
endif()

View File

@ -52,10 +52,10 @@ endif()
if(BUILD_MODE STREQUAL Release AND WIN32)
ExternalProject_Add_Step(external_sndfile after_install
COMMAND lib /def:${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.def /machine:x64 /out:${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/bin/libsndfile-1.dll ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.dll
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.lib ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/include/sndfile.h ${HARVEST_TARGET}/sndfile/include/sndfile.h
COMMAND lib /def:${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.def /machine:x64 /out:${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/bin/libsndfile-1.dll ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.dll
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.lib ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/include/sndfile.h ${HARVEST_TARGET}/sndfile/include/sndfile.h
DEPENDEES install
)

View File

@ -5,7 +5,20 @@ ExternalProject_Add(external_spnav
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${SPNAV_HASH_TYPE}=${SPNAV_HASH}
PREFIX ${BUILD_DIR}/spnav
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/spnav/src/external_spnav/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/spnav --disable-shared --enable-static --with-pic
CONFIGURE_COMMAND
${CONFIGURE_ENV} &&
cd ${BUILD_DIR}/spnav/src/external_spnav/ &&
${CONFIGURE_COMMAND}
--prefix=${LIBDIR}/spnav
# X11 is not needed as Blender polls the device as part of the GHOST event loop.
# This is used to support `3dxserv`, however this is no longer supported by 3DCONNEXION.
# Disable so building without X11 is supported (WAYLAND only).
--disable-x11
--disable-shared
--enable-static
--with-pic
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/spnav/src/external_spnav/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/spnav/src/external_spnav/ && make install
INSTALL_DIR ${LIBDIR}/spnav

View File

@ -195,9 +195,12 @@ set(TIFF_HASH_TYPE MD5)
set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz)
set(TIFF_CPE "cpe:2.3:a:libtiff:libtiff:${TIFF_VERSION}:*:*:*:*:*:*:*")
set(OSL_VERSION 1.12.7.1)
set(OSL_URI https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/archive/v${OSL_VERSION}.tar.gz)
set(OSL_HASH 53211da86c34ba6e0344998c1a6d219c)
# Recent commit from 1.13.0.2 under development, which includes string table
# changes that make the Cycles OptiX implementation work. Official 1.12 OSL
# releases should also build but without OptiX support.
set(OSL_VERSION 1a7670600c8b08c2443a78d03c8c27e9a1149140)
set(OSL_URI https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/archive/${OSL_VERSION}.tar.gz)
set(OSL_HASH 7b6d6716b05d1addb92a8f47280bf77f)
set(OSL_HASH_TYPE MD5)
set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
@ -232,11 +235,11 @@ set(OPENVDB_FILE openvdb-${OPENVDB_VERSION}.tar.gz)
# ------------------------------------------------------------------------------
# Python Modules
# Needed by: TODO.
# Needed by: `requests` module (so the version doesn't change on rebuild).
set(IDNA_VERSION 3.3)
# Needed by: TODO.
# Needed by: `requests` module (so the version doesn't change on rebuild).
set(CHARSET_NORMALIZER_VERSION 2.0.10)
# Needed by: TODO.
# Needed by: `requests` module (so the version doesn't change on rebuild).
set(URLLIB3_VERSION 1.26.8)
set(URLLIB3_CPE "cpe:2.3:a:urllib3:urllib3:${URLLIB3_VERSION}:*:*:*:*:*:*:*")
# Needed by: Python's `requests` module (so add-ons can authenticate against trusted certificates).
@ -366,9 +369,9 @@ set(WEBP_HASH_TYPE MD5)
set(WEBP_FILE libwebp-${WEBP_VERSION}.tar.gz)
set(WEBP_CPE "cpe:2.3:a:webmproject:libwebp:${WEBP_VERSION}:*:*:*:*:*:*:*")
set(SPNAV_VERSION 0.2.3)
set(SPNAV_URI http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%20${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
set(SPNAV_HASH 44d840540d53326d4a119c0f1aa7bf0a)
set(SPNAV_VERSION 1.1)
set(SPNAV_URI https://github.com/FreeSpacenav/libspnav/releases/download/v${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
set(SPNAV_HASH 7c0032034672dfba3c4bb9b49a440e70)
set(SPNAV_HASH_TYPE MD5)
set(SPNAV_FILE libspnav-${SPNAV_VERSION}.tar.gz)

View File

@ -10,7 +10,8 @@ if(WIN32)
set(YAMLCPP_EXTRA_ARGS
${YAMLCPP_EXTRA_ARGS}
-DBUILD_GMOCK=OFF
-DYAML_MSVC_SHARED_RT=ON)
-DYAML_MSVC_SHARED_RT=ON
)
endif()
ExternalProject_Add(external_yamlcpp

View File

@ -11,19 +11,25 @@ if [ `id -u` -ne 0 ]; then
exit 1
fi
# Packages `ninja-build` and `meson` are not available unless CBR or PowerTools repositories are enabled.
# See: https://wiki.rockylinux.org/rocky/repo/#notes-on-unlisted-repositories
dnf config-manager --set-enabled powertools
# yum-config-manager does not come in the default minimal install,
# so make sure it is installed and available.
yum -y update
yum -y install yum-utils
# Install all the packages needed for a new toolchain.
# Install all the packages needed for a new tool-chain.
#
# NOTE: Keep this separate from the packages install, since otherwise
# older toolchain will be installed.
# older tool-chain will be installed.
yum -y update
yum -y install epel-release
yum -y install centos-release-scl
yum -y install devtoolset-9
yum -y install scl-utils
yum -y install scl-utils-build
# Currently this is defined by the VFX platform (CY2023), see: https://vfxplatform.com
yum -y install gcc-toolset-11
# Install packages needed for Blender's dependencies.
PACKAGES_FOR_LIBS=(
@ -47,19 +53,12 @@ PACKAGES_FOR_LIBS=(
automake
libtool
# Meta-build system used by various packages.
meson
# TODO: why is this needed?
patchelf
# Builds generated by meson use Ninja for the actual build.
ninja-build
# Required by Blender build option: `WITH_GHOST_X11`.
libXrandr-devel
libXinerama-devel
libXcursor-devel
libXi-devel
libX11-devel
libXt-devel
# Required by Blender build option: `WITH_GHOST_WAYLAND`.
mesa-libEGL-devel
# Required by: Blender & `external_opensubdiv` (probably others).
@ -79,52 +78,45 @@ PACKAGES_FOR_LIBS=(
# Why are both needed?
yasm
# Required by: `meson` (Python based build system).
python36
# Required by: `mako` (Python module used for building `external_mesa`)
python-setuptools
# NOTE(@campbellbarton): while `python39` is available, the default Python version is 3.6.
# This is used for the `python3-mako` package for e.g.
# So use the "default" system Python since it means it's most compatible with other packages.
python3
# Required by: `mesa`.
expat-devel
# Required by: `external_igc` & `external_osl` as a build-time dependency.
bison
# Required by: `external_osl` as a build-time dependency.
flex
# TODO: dependencies build without this, consider removal.
# Required by: `external_ispc`.
ncurses-devel
# Required by: `external_ispc` (when building with CLANG).
libstdc++-static
)
# Additional packages needed for building Blender.
PACKAGES_FOR_BLENDER=(
# Required by Blender build option: `WITH_GHOST_WAYLAND`.
libxkbcommon-devel
# Required by Blender build option: `WITH_GHOST_X11`.
libX11-devel
libXcursor-devel
libXi-devel
libXinerama-devel
libXrandr-devel
libXt-devel
libXxf86vm-devel
)
yum -y install -y ${PACKAGES_FOR_LIBS[@]} ${PACKAGES_FOR_BLENDER[@]}
# Dependencies for Mesa
yum -y install expat-devel
python3 -m pip install mako
# Dependencies for pip (needed for buildbot-worker).
yum -y install python36-pip python36-devel
# Dependencies for pip (needed for buildbot-worker), uses Python3.6.
yum -y install python3 python3-pip python3-devel
# Dependencies for asound.
yum -y install -y \
alsa-lib-devel pulseaudio-libs-devel
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake 10 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake \
--family cmake
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest3 \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \
--family cmake
alternatives --install /usr/local/bin/cmake cmake /usr/bin/cmake3 20 \
--slave /usr/local/bin/ctest ctest /usr/bin/ctest3 \
--slave /usr/local/bin/cpack cpack /usr/bin/cpack3 \
--slave /usr/local/bin/ccmake ccmake /usr/bin/ccmake3 \
--family cmake

View File

@ -82,8 +82,8 @@ enum_use_layer_samples = (
)
enum_sampling_pattern = (
('SOBOL', "Sobol-Burley", "Use Sobol-Burley random sampling pattern", 0),
('PROGRESSIVE_MULTI_JITTER', "Progressive Multi-Jitter", "Use Progressive Multi-Jitter random sampling pattern", 1),
('SOBOL_BURLEY', "Sobol-Burley", "Use on-the-fly computed Owen-scrambled Sobol for random sampling", 0),
('TABULATED_SOBOL', "Tabulated Sobol", "Use precomputed tables of Owen-scrambled Sobol for random sampling", 1),
)
enum_emission_sampling = (
@ -412,9 +412,9 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
sampling_pattern: EnumProperty(
name="Sampling Pattern",
description="Random sampling pattern used by the integrator. When adaptive sampling is enabled, Progressive Multi-Jitter is always used instead of Sobol-Burley",
description="Random sampling pattern used by the integrator",
items=enum_sampling_pattern,
default='PROGRESSIVE_MULTI_JITTER',
default='TABULATED_SOBOL',
)
scrambling_distance: FloatProperty(

View File

@ -364,16 +364,13 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
row.prop(cscene, "seed")
row.prop(cscene, "use_animated_seed", text="", icon='TIME')
col = layout.column(align=True)
col.prop(cscene, "sampling_pattern", text="Pattern")
col = layout.column(align=True)
col.prop(cscene, "sample_offset")
layout.separator()
heading = layout.column(align=True, heading="Scrambling Distance")
heading.active = cscene.sampling_pattern != 'SOBOL'
heading.active = cscene.sampling_pattern != 'TABULATED_SOBOL'
heading.prop(cscene, "auto_scrambling_distance", text="Automatic")
heading.prop(cscene, "preview_scrambling_distance", text="Viewport")
heading.prop(cscene, "scrambling_distance", text="Multiplier")
@ -396,11 +393,22 @@ class CYCLES_RENDER_PT_sampling_lights(CyclesButtonsPanel, Panel):
bl_parent_id = "CYCLES_RENDER_PT_sampling"
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
def draw(self, context):
layout = self.layout
scene = context.scene
cscene = scene.cycles
col.prop(cscene, "use_light_tree")
sub = col.row()
sub.prop(cscene, "light_sampling_threshold", text="Light Threshold")
sub.active = not cscene.use_light_tree
class CYCLES_RENDER_PT_sampling_debug(CyclesDebugButtonsPanel, Panel):
bl_label = "Debug"
bl_parent_id = "CYCLES_RENDER_PT_sampling"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
@ -410,10 +418,7 @@ class CYCLES_RENDER_PT_sampling_lights(CyclesButtonsPanel, Panel):
cscene = scene.cycles
col = layout.column(align=True)
col.prop(cscene, "use_light_tree")
sub = col.row()
sub.prop(cscene, "light_sampling_threshold", text="Light Threshold")
sub.active = not cscene.use_light_tree
col.prop(cscene, "sampling_pattern", text="Pattern")
class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel):
@ -2391,6 +2396,7 @@ classes = (
CYCLES_RENDER_PT_sampling_path_guiding_debug,
CYCLES_RENDER_PT_sampling_lights,
CYCLES_RENDER_PT_sampling_advanced,
CYCLES_RENDER_PT_sampling_debug,
CYCLES_RENDER_PT_light_paths,
CYCLES_RENDER_PT_light_paths_max_bounces,
CYCLES_RENDER_PT_light_paths_clamping,

View File

@ -228,7 +228,7 @@ def do_versions(self):
cscene.use_preview_denoising = False
if not cscene.is_property_set("sampling_pattern") or \
cscene.get('sampling_pattern') >= 2:
cscene.sampling_pattern = 'PROGRESSIVE_MULTI_JITTER'
cscene.sampling_pattern = 'TABULATED_SOBOL'
# Removal of square samples.
cscene = scene.cycles
@ -241,6 +241,12 @@ def do_versions(self):
layer.samples *= layer.samples
cscene["use_square_samples"] = False
# Disable light tree for existing scenes.
if version <= (3, 5, 3):
cscene = scene.cycles
if not cscene.is_property_set("use_light_tree"):
cscene.use_light_tree = False
# Lamps
for light in bpy.data.lights:
if light.library not in libraries:

View File

@ -57,7 +57,6 @@ int BlenderDisplayShader::get_tex_coord_attrib_location()
/* TODO move shaders to standalone .glsl file. */
static const char *FALLBACK_VERTEX_SHADER =
"#version 330\n"
"uniform vec2 fullscreen;\n"
"in vec2 texCoord;\n"
"in vec2 pos;\n"
@ -75,7 +74,6 @@ static const char *FALLBACK_VERTEX_SHADER =
"}\n\0";
static const char *FALLBACK_FRAGMENT_SHADER =
"#version 330\n"
"uniform sampler2D image_texture;\n"
"in vec2 texCoord_interp;\n"
"out vec4 fragColor;\n"

View File

@ -367,13 +367,11 @@ static void attr_create_generic(Scene *scene,
{
AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
static const ustring u_velocity("velocity");
int attribute_index = 0;
int render_color_index = b_mesh.attributes.render_color_index();
const ustring default_color_name{b_mesh.attributes.default_color_name().c_str()};
for (BL::Attribute &b_attribute : b_mesh.attributes) {
const ustring name{b_attribute.name().c_str()};
const bool is_render_color = (attribute_index++ == render_color_index);
const bool is_render_color = name == default_color_name;
if (need_motion && name == u_velocity) {
attr_create_motion(mesh, b_attribute, motion_scale);

View File

@ -357,7 +357,7 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
}
SamplingPattern sampling_pattern = (SamplingPattern)get_enum(
cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_PMJ);
cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_TABULATED_SOBOL);
integrator->set_sampling_pattern(sampling_pattern);
int samples = 1;

View File

@ -113,6 +113,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
if ((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) {
if (mesh.use_auto_smooth()) {
mesh.calc_normals_split();
mesh.split_faces(false);
}

View File

@ -952,6 +952,9 @@ void CUDADevice::tex_alloc(device_texture &mem)
case EXTENSION_CLIP:
address_mode = CU_TR_ADDRESS_MODE_BORDER;
break;
case EXTENSION_MIRROR:
address_mode = CU_TR_ADDRESS_MODE_MIRROR;
break;
default:
assert(0);
break;

View File

@ -909,6 +909,9 @@ void HIPDevice::tex_alloc(device_texture &mem)
* because it's unsupported in HIP. */
address_mode = hipAddressModeClamp;
break;
case EXTENSION_MIRROR:
address_mode = hipAddressModeMirror;
break;
default:
assert(0);
break;

View File

@ -856,7 +856,7 @@ void MetalDevice::tex_alloc(device_texture &mem)
/* sampler_index maps into the GPU's constant 'metal_samplers' array */
uint64_t sampler_index = mem.info.extension;
if (mem.info.interpolation != INTERPOLATION_CLOSEST) {
sampler_index += 3;
sampler_index += 4;
}
/* Image Texture Storage */

View File

@ -299,12 +299,12 @@ set(SRC_KERNEL_LIGHT_HEADERS
)
set(SRC_KERNEL_SAMPLE_HEADERS
sample/jitter.h
sample/lcg.h
sample/mapping.h
sample/mis.h
sample/pattern.h
sample/sobol_burley.h
sample/tabulated_sobol.h
sample/util.h
)

View File

@ -77,7 +77,7 @@ KERNEL_DATA_ARRAY(KernelShader, shaders)
/* lookup tables */
KERNEL_DATA_ARRAY(float, lookup_table)
/* PMJ sample pattern */
/* tabulated Sobol sample pattern */
KERNEL_DATA_ARRAY(float, sample_pattern_lut)
/* image textures */

View File

@ -179,7 +179,8 @@ KERNEL_STRUCT_MEMBER(integrator, float, sample_clamp_indirect)
KERNEL_STRUCT_MEMBER(integrator, int, use_caustics)
/* Sampling pattern. */
KERNEL_STRUCT_MEMBER(integrator, int, sampling_pattern)
KERNEL_STRUCT_MEMBER(integrator, int, pmj_sequence_size)
KERNEL_STRUCT_MEMBER(integrator, int, tabulated_sobol_sequence_size)
KERNEL_STRUCT_MEMBER(integrator, int, sobol_index_mask)
KERNEL_STRUCT_MEMBER(integrator, float, scrambling_distance)
/* Volume render. */
KERNEL_STRUCT_MEMBER(integrator, int, use_volumes)
@ -204,7 +205,6 @@ KERNEL_STRUCT_MEMBER(integrator, int, use_guiding_mis_weights)
/* Padding. */
KERNEL_STRUCT_MEMBER(integrator, int, pad1)
KERNEL_STRUCT_MEMBER(integrator, int, pad2)
KERNEL_STRUCT_END(KernelIntegrator)
/* SVM. For shader specialization. */

View File

@ -202,6 +202,14 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
return clamp(x, 0, width - 1);
}
static ccl_always_inline int wrap_mirror(int x, int width)
{
const int m = abs(x + (x < 0)) % (2 * width);
if (m >= width)
return 2 * width - m - 1;
return m;
}
/* ******** 2D interpolation ******** */
static ccl_always_inline OutT interp_closest(const TextureInfo &info, float x, float y)
@ -226,6 +234,10 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
ix = wrap_clamp(ix, width);
iy = wrap_clamp(iy, height);
break;
case EXTENSION_MIRROR:
ix = wrap_mirror(ix, width);
iy = wrap_mirror(iy, height);
break;
default:
kernel_assert(0);
return zero();
@ -268,6 +280,12 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
niy = wrap_clamp(iy + 1, height);
iy = wrap_clamp(iy, height);
break;
case EXTENSION_MIRROR:
nix = wrap_mirror(ix + 1, width);
ix = wrap_mirror(ix, width);
niy = wrap_mirror(iy + 1, height);
iy = wrap_mirror(iy, height);
break;
default:
kernel_assert(0);
return zero();
@ -331,6 +349,17 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
nniy = wrap_clamp(iy + 2, height);
iy = wrap_clamp(iy, height);
break;
case EXTENSION_MIRROR:
pix = wrap_mirror(ix - 1, width);
nix = wrap_mirror(ix + 1, width);
nnix = wrap_mirror(ix + 2, width);
ix = wrap_mirror(ix, width);
piy = wrap_mirror(iy - 1, height);
niy = wrap_mirror(iy + 1, height);
nniy = wrap_mirror(iy + 2, height);
iy = wrap_mirror(iy, height);
break;
default:
kernel_assert(0);
return zero();
@ -403,6 +432,11 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
iy = wrap_clamp(iy, height);
iz = wrap_clamp(iz, depth);
break;
case EXTENSION_MIRROR:
ix = wrap_mirror(ix, width);
iy = wrap_mirror(iy, height);
iz = wrap_mirror(iz, depth);
break;
default:
kernel_assert(0);
return zero();
@ -480,6 +514,16 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
niz = wrap_clamp(iz + 1, depth);
iz = wrap_clamp(iz, depth);
break;
case EXTENSION_MIRROR:
nix = wrap_mirror(ix + 1, width);
ix = wrap_mirror(ix, width);
niy = wrap_mirror(iy + 1, height);
iy = wrap_mirror(iy, height);
niz = wrap_mirror(iz + 1, depth);
iz = wrap_mirror(iz, depth);
break;
default:
kernel_assert(0);
return zero();
@ -595,6 +639,22 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
nniz = wrap_clamp(iz + 2, depth);
iz = wrap_clamp(iz, depth);
break;
case EXTENSION_MIRROR:
pix = wrap_mirror(ix - 1, width);
nix = wrap_mirror(ix + 1, width);
nnix = wrap_mirror(ix + 2, width);
ix = wrap_mirror(ix, width);
piy = wrap_mirror(iy - 1, height);
niy = wrap_mirror(iy + 1, height);
nniy = wrap_mirror(iy + 2, height);
iy = wrap_mirror(iy, height);
piz = wrap_mirror(iz - 1, depth);
niz = wrap_mirror(iz + 1, depth);
nniz = wrap_mirror(iz + 2, depth);
iz = wrap_mirror(iz, depth);
break;
default:
kernel_assert(0);
return zero();

View File

@ -301,10 +301,12 @@ enum SamplerType {
SamplerFilterNearest_AddressRepeat,
SamplerFilterNearest_AddressClampEdge,
SamplerFilterNearest_AddressClampZero,
SamplerFilterNearest_AddressMirroredRepeat,
SamplerFilterLinear_AddressRepeat,
SamplerFilterLinear_AddressClampEdge,
SamplerFilterLinear_AddressClampZero,
SamplerFilterLinear_AddressMirroredRepeat,
SamplerCount
};
@ -313,7 +315,9 @@ constant constexpr array<sampler, SamplerCount> metal_samplers = {
sampler(address::repeat, filter::nearest),
sampler(address::clamp_to_edge, filter::nearest),
sampler(address::clamp_to_zero, filter::nearest),
sampler(address::mirrored_repeat, filter::nearest),
sampler(address::repeat, filter::linear),
sampler(address::clamp_to_edge, filter::linear),
sampler(address::clamp_to_zero, filter::linear),
sampler(address::mirrored_repeat, filter::linear),
};

View File

@ -47,9 +47,11 @@ class MetalKernelContext {
case 0: return texture_array[tid].tex.sample(sampler(address::repeat, filter::nearest), coords);
case 1: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::nearest), coords);
case 2: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::nearest), coords);
case 3: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords);
case 4: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords);
case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords);
case 3: return texture_array[tid].tex.sample(sampler(address::mirrored_repeat, filter::nearest), coords);
case 4: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords);
case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords);
case 6: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords);
case 7: return texture_array[tid].tex.sample(sampler(address::mirrored_repeat, filter::linear), coords);
}
}
#endif

View File

@ -24,6 +24,14 @@ ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width)
return clamp(x, 0, width - 1);
}
ccl_device_inline int svm_image_texture_wrap_mirror(int x, int width)
{
const int m = abs(x + (x < 0)) % (2 * width);
if (m >= width)
return 2 * width - m - 1;
return m;
}
ccl_device_inline float4 svm_image_texture_read(const TextureInfo &info, int x, int y, int z)
{
const int data_offset = x + info.width * y + info.width * info.height * z;
@ -85,6 +93,10 @@ ccl_device_inline float4 svm_image_texture_read_2d(int id, int x, int y)
x = svm_image_texture_wrap_clamp(x, info.width);
y = svm_image_texture_wrap_clamp(y, info.height);
}
else if (info.extension == EXTENSION_MIRROR) {
x = svm_image_texture_wrap_mirror(x, info.width);
y = svm_image_texture_wrap_mirror(y, info.height);
}
else {
if (x < 0 || x >= info.width || y < 0 || y >= info.height) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
@ -109,6 +121,11 @@ ccl_device_inline float4 svm_image_texture_read_3d(int id, int x, int y, int z)
y = svm_image_texture_wrap_clamp(y, info.height);
z = svm_image_texture_wrap_clamp(z, info.depth);
}
else if (info.extension == EXTENSION_MIRROR) {
x = svm_image_texture_wrap_mirror(x, info.width);
y = svm_image_texture_wrap_mirror(y, info.height);
z = svm_image_texture_wrap_mirror(z, info.depth);
}
else {
if (x < 0 || x >= info.width || y < 0 || y >= info.height || z < 0 || z >= info.depth) {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);

View File

@ -26,18 +26,22 @@ ccl_device_inline void integrate_camera_sample(KernelGlobals kg,
const float2 rand_filter = (sample == 0) ? make_float2(0.5f, 0.5f) :
path_rng_2D(kg, rng_hash, sample, PRNG_FILTER);
/* Depth of field sampling. */
const float2 rand_lens = (kernel_data.cam.aperturesize > 0.0f) ?
path_rng_2D(kg, rng_hash, sample, PRNG_LENS) :
zero_float2();
/* Motion blur time sampling. */
const float rand_time = (kernel_data.cam.shuttertime != -1.0f) ?
path_rng_1D(kg, rng_hash, sample, PRNG_TIME) :
0.0f;
/* Motion blur (time) and depth of field (lens) sampling. (time, lens_x, lens_y) */
const float3 rand_time_lens = (kernel_data.cam.shuttertime != -1.0f ||
kernel_data.cam.aperturesize > 0.0f) ?
path_rng_3D(kg, rng_hash, sample, PRNG_LENS_TIME) :
zero_float3();
/* Generate camera ray. */
camera_sample(kg, x, y, rand_filter.x, rand_filter.y, rand_lens.x, rand_lens.y, rand_time, ray);
camera_sample(kg,
x,
y,
rand_filter.x,
rand_filter.y,
rand_time_lens.y,
rand_time_lens.z,
rand_time_lens.x,
ray);
}
/* Return false to indicate that this pixel is finished.

View File

@ -336,6 +336,14 @@ ccl_device_inline float2 path_state_rng_2D(KernelGlobals kg,
kg, rng_state->rng_hash, rng_state->sample, rng_state->rng_offset + dimension);
}
ccl_device_inline float3 path_state_rng_3D(KernelGlobals kg,
ccl_private const RNGState *rng_state,
const int dimension)
{
return path_rng_3D(
kg, rng_state->rng_hash, rng_state->sample, rng_state->rng_offset + dimension);
}
ccl_device_inline float path_branched_rng_1D(KernelGlobals kg,
ccl_private const RNGState *rng_state,
const int branch,
@ -360,6 +368,18 @@ ccl_device_inline float2 path_branched_rng_2D(KernelGlobals kg,
rng_state->rng_offset + dimension);
}
ccl_device_inline float3 path_branched_rng_3D(KernelGlobals kg,
ccl_private const RNGState *rng_state,
const int branch,
const int num_branches,
const int dimension)
{
return path_rng_3D(kg,
rng_state->rng_hash,
rng_state->sample * num_branches + branch,
rng_state->rng_offset + dimension);
}
/* Utility functions to get light termination value,
* since it might not be needed in many cases.
*/

View File

@ -147,10 +147,11 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
const float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_LIGHT);
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
if (!light_sample_from_position(kg,
rng_state,
rand_light.z,
rand_light.x,
rand_light.y,
sd->time,

View File

@ -702,10 +702,11 @@ ccl_device_forceinline bool integrate_volume_equiangular_sample_light(
/* Sample position on a light. */
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
const float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_LIGHT);
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
LightSample ls ccl_optional_struct_init;
if (!light_sample_from_volume_segment(kg,
rand_light.z,
rand_light.x,
rand_light.y,
sd->time,
@ -765,10 +766,11 @@ ccl_device_forceinline void integrate_volume_direct_light(
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
const uint bounce = INTEGRATOR_STATE(state, path, bounce);
const float2 rand_light = path_state_rng_2D(kg, rng_state, PRNG_LIGHT);
const float3 rand_light = path_state_rng_3D(kg, rng_state, PRNG_LIGHT);
if (!light_sample_from_position(kg,
rng_state,
rand_light.z,
rand_light.x,
rand_light.y,
sd->time,

View File

@ -11,7 +11,7 @@ CCL_NAMESPACE_BEGIN
/* Simple CDF based sampling over all lights in the scene, without taking into
* account shading position or normal. */
ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *randu)
ccl_device int light_distribution_sample(KernelGlobals kg, const float randn)
{
/* This is basically std::upper_bound as used by PBRT, to find a point light or
* triangle to emit from, proportional to area. a good improvement would be to
@ -19,7 +19,7 @@ ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *ra
* arbitrary shaders. */
int first = 0;
int len = kernel_data.integrator.num_distribution + 1;
float r = *randu;
float r = randn;
do {
int half_len = len >> 1;
@ -38,18 +38,13 @@ ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *ra
* make this fail on rare occasions. */
int index = clamp(first - 1, 0, kernel_data.integrator.num_distribution - 1);
/* Rescale to reuse random number. this helps the 2D samples within
* each area light be stratified as well. */
float distr_min = kernel_data_fetch(light_distribution, index).totarea;
float distr_max = kernel_data_fetch(light_distribution, index + 1).totarea;
*randu = (r - distr_min) / (distr_max - distr_min);
return index;
}
template<bool in_volume_segment>
ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
float randu,
const float randn,
const float randu,
const float randv,
const float time,
const float3 P,
@ -58,7 +53,7 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg,
ccl_private LightSample *ls)
{
/* Sample light index from distribution. */
const int index = light_distribution_sample(kg, &randu);
const int index = light_distribution_sample(kg, randn);
const float pdf_selection = kernel_data.integrator.distribution_pdf_lights;
return light_sample<in_volume_segment>(
kg, randu, randv, time, P, bounce, path_flag, index, pdf_selection, ls);

View File

@ -324,7 +324,8 @@ ccl_device_inline float light_sample_mis_weight_nee(KernelGlobals kg,
* Uses either a flat distribution or light tree. */
ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
float randu,
const float randn,
const float randu,
const float randv,
const float time,
const float3 P,
@ -337,17 +338,19 @@ ccl_device_inline bool light_sample_from_volume_segment(KernelGlobals kg,
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<true>(
kg, randu, randv, time, P, D, t, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
kg, randn, randu, randv, time, P, D, t, SD_BSDF_HAS_TRANSMISSION, bounce, path_flag, ls);
}
else
#endif
{
return light_distribution_sample<true>(kg, randu, randv, time, P, bounce, path_flag, ls);
return light_distribution_sample<true>(
kg, randn, randu, randv, time, P, bounce, path_flag, ls);
}
}
ccl_device bool light_sample_from_position(KernelGlobals kg,
ccl_private const RNGState *rng_state,
const float randn,
const float randu,
const float randv,
const float time,
@ -361,12 +364,13 @@ ccl_device bool light_sample_from_position(KernelGlobals kg,
#ifdef __LIGHT_TREE__
if (kernel_data.integrator.use_light_tree) {
return light_tree_sample<false>(
kg, randu, randv, time, P, N, 0, shader_flags, bounce, path_flag, ls);
kg, randn, randu, randv, time, P, N, 0, shader_flags, bounce, path_flag, ls);
}
else
#endif
{
return light_distribution_sample<false>(kg, randu, randv, time, P, bounce, path_flag, ls);
return light_distribution_sample<false>(
kg, randn, randu, randv, time, P, bounce, path_flag, ls);
}
}

View File

@ -551,8 +551,9 @@ ccl_device bool get_left_probability(KernelGlobals kg,
template<bool in_volume_segment>
ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
float randu,
float randv,
float randn,
const float randu,
const float randv,
const float time,
const float3 P,
const float3 N_or_D,
@ -580,7 +581,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
if (knode->child_index <= 0) {
/* At a leaf node, we pick an emitter. */
selected_emitter = light_tree_cluster_select_emitter<in_volume_segment>(
kg, randv, P, N_or_D, t, has_transmission, knode, &pdf_selection);
kg, randn, P, N_or_D, t, has_transmission, knode, &pdf_selection);
break;
}
@ -598,7 +599,7 @@ ccl_device_noinline bool light_tree_sample(KernelGlobals kg,
float discard;
float total_prob = left_prob;
node_index = left_index;
sample_resevoir(right_index, 1.0f - left_prob, node_index, discard, total_prob, randu);
sample_resevoir(right_index, 1.0f - left_prob, node_index, discard, total_prob, randn);
pdf_leaf *= (node_index == left_index) ? left_prob : (1.0f - left_prob);
}

View File

@ -14,111 +14,111 @@
namespace DeviceStrings {
/* "" */
ccl_device_constant DeviceString _emptystring_ = {0ull};
ccl_device_constant DeviceString _emptystring_ = 0ull;
/* "common" */
ccl_device_constant DeviceString u_common = {14645198576927606093ull};
ccl_device_constant DeviceString u_common = 14645198576927606093ull;
/* "world" */
ccl_device_constant DeviceString u_world = {16436542438370751598ull};
ccl_device_constant DeviceString u_world = 16436542438370751598ull;
/* "shader" */
ccl_device_constant DeviceString u_shader = {4279676006089868ull};
ccl_device_constant DeviceString u_shader = 4279676006089868ull;
/* "object" */
ccl_device_constant DeviceString u_object = {973692718279674627ull};
ccl_device_constant DeviceString u_object = 973692718279674627ull;
/* "NDC" */
ccl_device_constant DeviceString u_ndc = {5148305047403260775ull};
ccl_device_constant DeviceString u_ndc = 5148305047403260775ull;
/* "screen" */
ccl_device_constant DeviceString u_screen = {14159088609039777114ull};
ccl_device_constant DeviceString u_screen = 14159088609039777114ull;
/* "camera" */
ccl_device_constant DeviceString u_camera = {2159505832145726196ull};
ccl_device_constant DeviceString u_camera = 2159505832145726196ull;
/* "raster" */
ccl_device_constant DeviceString u_raster = {7759263238610201778ull};
ccl_device_constant DeviceString u_raster = 7759263238610201778ull;
/* "hsv" */
ccl_device_constant DeviceString u_hsv = {2177035556331879497ull};
ccl_device_constant DeviceString u_hsv = 2177035556331879497ull;
/* "hsl" */
ccl_device_constant DeviceString u_hsl = {7749766809258288148ull};
ccl_device_constant DeviceString u_hsl = 7749766809258288148ull;
/* "XYZ" */
ccl_device_constant DeviceString u_xyz = {4957977063494975483ull};
ccl_device_constant DeviceString u_xyz = 4957977063494975483ull;
/* "xyY" */
ccl_device_constant DeviceString u_xyy = {5138822319725660255ull};
ccl_device_constant DeviceString u_xyy = 5138822319725660255ull;
/* "sRGB" */
ccl_device_constant DeviceString u_srgb = {15368599878474175032ull};
ccl_device_constant DeviceString u_srgb = 15368599878474175032ull;
/* "object:location" */
ccl_device_constant DeviceString u_object_location = {7846190347358762897ull};
ccl_device_constant DeviceString u_object_location = 7846190347358762897ull;
/* "object:color" */
ccl_device_constant DeviceString u_object_color = {12695623857059169556ull};
ccl_device_constant DeviceString u_object_color = 12695623857059169556ull;
/* "object:alpha" */
ccl_device_constant DeviceString u_object_alpha = {11165053919428293151ull};
ccl_device_constant DeviceString u_object_alpha = 11165053919428293151ull;
/* "object:index" */
ccl_device_constant DeviceString u_object_index = {6588325838217472556ull};
ccl_device_constant DeviceString u_object_index = 6588325838217472556ull;
/* "geom:dupli_generated" */
ccl_device_constant DeviceString u_geom_dupli_generated = {6715607178003388908ull};
ccl_device_constant DeviceString u_geom_dupli_generated = 6715607178003388908ull;
/* "geom:dupli_uv" */
ccl_device_constant DeviceString u_geom_dupli_uv = {1294253317490155849ull};
ccl_device_constant DeviceString u_geom_dupli_uv = 1294253317490155849ull;
/* "material:index" */
ccl_device_constant DeviceString u_material_index = {741770758159634623ull};
ccl_device_constant DeviceString u_material_index = 741770758159634623ull;
/* "object:random" */
ccl_device_constant DeviceString u_object_random = {15789063994977955884ull};
ccl_device_constant DeviceString u_object_random = 15789063994977955884ull;
/* "particle:index" */
ccl_device_constant DeviceString u_particle_index = {9489711748229903784ull};
ccl_device_constant DeviceString u_particle_index = 9489711748229903784ull;
/* "particle:random" */
ccl_device_constant DeviceString u_particle_random = {17993722202766855761ull};
ccl_device_constant DeviceString u_particle_random = 17993722202766855761ull;
/* "particle:age" */
ccl_device_constant DeviceString u_particle_age = {7380730644710951109ull};
ccl_device_constant DeviceString u_particle_age = 7380730644710951109ull;
/* "particle:lifetime" */
ccl_device_constant DeviceString u_particle_lifetime = {16576828923156200061ull};
ccl_device_constant DeviceString u_particle_lifetime = 16576828923156200061ull;
/* "particle:location" */
ccl_device_constant DeviceString u_particle_location = {10309536211423573010ull};
ccl_device_constant DeviceString u_particle_location = 10309536211423573010ull;
/* "particle:rotation" */
ccl_device_constant DeviceString u_particle_rotation = {17858543768041168459ull};
ccl_device_constant DeviceString u_particle_rotation = 17858543768041168459ull;
/* "particle:size" */
ccl_device_constant DeviceString u_particle_size = {16461524249715420389ull};
ccl_device_constant DeviceString u_particle_size = 16461524249715420389ull;
/* "particle:velocity" */
ccl_device_constant DeviceString u_particle_velocity = {13199101248768308863ull};
ccl_device_constant DeviceString u_particle_velocity = 13199101248768308863ull;
/* "particle:angular_velocity" */
ccl_device_constant DeviceString u_particle_angular_velocity = {16327930120486517910ull};
ccl_device_constant DeviceString u_particle_angular_velocity = 16327930120486517910ull;
/* "geom:numpolyvertices" */
ccl_device_constant DeviceString u_geom_numpolyvertices = {382043551489988826ull};
ccl_device_constant DeviceString u_geom_numpolyvertices = 382043551489988826ull;
/* "geom:trianglevertices" */
ccl_device_constant DeviceString u_geom_trianglevertices = {17839267571524187074ull};
ccl_device_constant DeviceString u_geom_trianglevertices = 17839267571524187074ull;
/* "geom:polyvertices" */
ccl_device_constant DeviceString u_geom_polyvertices = {1345577201967881769ull};
ccl_device_constant DeviceString u_geom_polyvertices = 1345577201967881769ull;
/* "geom:name" */
ccl_device_constant DeviceString u_geom_name = {13606338128269760050ull};
ccl_device_constant DeviceString u_geom_name = 13606338128269760050ull;
/* "geom:undisplaced" */
ccl_device_constant DeviceString u_geom_undisplaced = {12431586303019276305ull};
ccl_device_constant DeviceString u_geom_undisplaced = 12431586303019276305ull;
/* "geom:is_smooth" */
ccl_device_constant DeviceString u_is_smooth = {857544214094480123ull};
ccl_device_constant DeviceString u_is_smooth = 857544214094480123ull;
/* "geom:is_curve" */
ccl_device_constant DeviceString u_is_curve = {129742495633653138ull};
ccl_device_constant DeviceString u_is_curve = 129742495633653138ull;
/* "geom:curve_thickness" */
ccl_device_constant DeviceString u_curve_thickness = {10605802038397633852ull};
ccl_device_constant DeviceString u_curve_thickness = 10605802038397633852ull;
/* "geom:curve_length" */
ccl_device_constant DeviceString u_curve_length = {11423459517663715453ull};
ccl_device_constant DeviceString u_curve_length = 11423459517663715453ull;
/* "geom:curve_tangent_normal" */
ccl_device_constant DeviceString u_curve_tangent_normal = {12301397394034985633ull};
ccl_device_constant DeviceString u_curve_tangent_normal = 12301397394034985633ull;
/* "geom:curve_random" */
ccl_device_constant DeviceString u_curve_random = {15293085049960492358ull};
ccl_device_constant DeviceString u_curve_random = 15293085049960492358ull;
/* "geom:is_point" */
ccl_device_constant DeviceString u_is_point = {2511357849436175953ull};
ccl_device_constant DeviceString u_is_point = 2511357849436175953ull;
/* "geom:point_radius" */
ccl_device_constant DeviceString u_point_radius = {9956381140398668479ull};
ccl_device_constant DeviceString u_point_radius = 9956381140398668479ull;
/* "geom:point_position" */
ccl_device_constant DeviceString u_point_position = {15684484280742966916ull};
ccl_device_constant DeviceString u_point_position = 15684484280742966916ull;
/* "geom:point_random" */
ccl_device_constant DeviceString u_point_random = {5632627207092325544ull};
ccl_device_constant DeviceString u_point_random = 5632627207092325544ull;
/* "geom:normal_map_normal" */
ccl_device_constant DeviceString u_normal_map_normal = {10718948685686827073};
ccl_device_constant DeviceString u_normal_map_normal = 10718948685686827073;
/* "path:ray_length" */
ccl_device_constant DeviceString u_path_ray_length = {16391985802412544524ull};
ccl_device_constant DeviceString u_path_ray_length = 16391985802412544524ull;
/* "path:ray_depth" */
ccl_device_constant DeviceString u_path_ray_depth = {16643933224879500399ull};
ccl_device_constant DeviceString u_path_ray_depth = 16643933224879500399ull;
/* "path:diffuse_depth" */
ccl_device_constant DeviceString u_path_diffuse_depth = {13191651286699118408ull};
ccl_device_constant DeviceString u_path_diffuse_depth = 13191651286699118408ull;
/* "path:glossy_depth" */
ccl_device_constant DeviceString u_path_glossy_depth = {15717768399057252940ull};
ccl_device_constant DeviceString u_path_glossy_depth = 15717768399057252940ull;
/* "path:transparent_depth" */
ccl_device_constant DeviceString u_path_transparent_depth = {7821650266475578543ull};
ccl_device_constant DeviceString u_path_transparent_depth = 7821650266475578543ull;
/* "path:transmission_depth" */
ccl_device_constant DeviceString u_path_transmission_depth = {15113408892323917624ull};
ccl_device_constant DeviceString u_path_transmission_depth = 15113408892323917624ull;
} // namespace DeviceStrings
@ -1275,9 +1275,7 @@ ccl_device_extern bool osl_get_attribute(ccl_private ShaderGlobals *sg,
object = sd->object;
}
const uint64_t id = name.hash();
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, sd->type, id);
const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, sd->type, name);
if (desc.offset != ATTR_STD_NOT_FOUND) {
return get_object_attribute(kg, sd, desc, type, derivatives, res);
}

View File

@ -5,47 +5,26 @@
CCL_NAMESPACE_BEGIN
struct DeviceString {
#if defined(__KERNEL_GPU__)
/* Strings are represented by their hashes in CUDA and OptiX. */
size_t str_;
ccl_device_inline_method uint64_t hash() const
{
return str_;
}
/* Strings are represented by their hashes on the GPU. */
typedef size_t DeviceString;
#elif defined(OPENIMAGEIO_USTRING_H)
ustring str_;
ccl_device_inline_method uint64_t hash() const
{
return str_.hash();
}
typedef ustring DeviceString;
#else
const char *str_;
typedef const char *DeviceString;
#endif
ccl_device_inline_method bool operator==(DeviceString b) const
{
return str_ == b.str_;
}
ccl_device_inline_method bool operator!=(DeviceString b) const
{
return str_ != b.str_;
}
};
ccl_device_inline DeviceString make_string(const char *str, size_t hash)
{
#if defined(__KERNEL_GPU__)
(void)str;
return {hash};
return hash;
#elif defined(OPENIMAGEIO_USTRING_H)
(void)hash;
return {ustring(str)};
return ustring(str);
#else
(void)hash;
return {str};
return str;
#endif
}

View File

@ -1,90 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "kernel/sample/util.h"
#include "util/hash.h"
#pragma once
CCL_NAMESPACE_BEGIN
ccl_device uint pmj_shuffled_sample_index(KernelGlobals kg, uint sample, uint dimension, uint seed)
{
const uint sample_count = kernel_data.integrator.pmj_sequence_size;
/* Shuffle the pattern order and sample index to better decorrelate
* dimensions and make the most of the finite patterns we have.
* The funky sample mask stuff is to ensure that we only shuffle
* *within* the current sample pattern, which is necessary to avoid
* early repeat pattern use. */
const uint pattern_i = hash_shuffle_uint(dimension, NUM_PMJ_PATTERNS, seed);
/* sample_count should always be a power of two, so this results in a mask. */
const uint sample_mask = sample_count - 1;
const uint sample_shuffled = nested_uniform_scramble(sample,
hash_wang_seeded_uint(dimension, seed));
sample = (sample & ~sample_mask) | (sample_shuffled & sample_mask);
return ((pattern_i * sample_count) + sample) % (sample_count * NUM_PMJ_PATTERNS);
}
ccl_device float pmj_sample_1D(KernelGlobals kg,
uint sample,
const uint rng_hash,
const uint dimension)
{
uint seed = rng_hash;
/* Use the same sample sequence seed for all pixels when using
* scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
seed = kernel_data.integrator.seed;
}
/* Fetch the sample. */
const uint index = pmj_shuffled_sample_index(kg, sample, dimension, seed);
float x = kernel_data_fetch(sample_pattern_lut, index * NUM_PMJ_DIMENSIONS);
/* Do limited Cranley-Patterson rotation when using scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
kernel_data.integrator.scrambling_distance;
x += jitter_x;
x -= floorf(x);
}
return x;
}
ccl_device float2 pmj_sample_2D(KernelGlobals kg,
uint sample,
const uint rng_hash,
const uint dimension)
{
uint seed = rng_hash;
/* Use the same sample sequence seed for all pixels when using
* scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
seed = kernel_data.integrator.seed;
}
/* Fetch the sample. */
const uint index = pmj_shuffled_sample_index(kg, sample, dimension, seed);
float x = kernel_data_fetch(sample_pattern_lut, index * NUM_PMJ_DIMENSIONS);
float y = kernel_data_fetch(sample_pattern_lut, index * NUM_PMJ_DIMENSIONS + 1);
/* Do limited Cranley-Patterson rotation when using scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
kernel_data.integrator.scrambling_distance;
const float jitter_y = hash_wang_seeded_float(dimension, rng_hash ^ 0xca0e1151) *
kernel_data.integrator.scrambling_distance;
x += jitter_x;
y += jitter_y;
x -= floorf(x);
y -= floorf(y);
}
return make_float2(x, y);
}
CCL_NAMESPACE_END

View File

@ -3,8 +3,8 @@
#pragma once
#include "kernel/sample/jitter.h"
#include "kernel/sample/sobol_burley.h"
#include "kernel/sample/tabulated_sobol.h"
#include "util/hash.h"
CCL_NAMESPACE_BEGIN
@ -23,10 +23,11 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals kg,
#endif
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_SOBOL_BURLEY) {
return sobol_burley_sample_1D(sample, dimension, rng_hash);
const uint index_mask = kernel_data.integrator.sobol_index_mask;
return sobol_burley_sample_1D(sample, dimension, rng_hash, index_mask);
}
else {
return pmj_sample_1D(kg, sample, rng_hash, dimension);
return tabulated_sobol_sample_1D(kg, sample, rng_hash, dimension);
}
}
@ -40,10 +41,47 @@ ccl_device_forceinline float2 path_rng_2D(KernelGlobals kg,
#endif
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_SOBOL_BURLEY) {
return sobol_burley_sample_2D(sample, dimension, rng_hash);
const uint index_mask = kernel_data.integrator.sobol_index_mask;
return sobol_burley_sample_2D(sample, dimension, rng_hash, index_mask);
}
else {
return pmj_sample_2D(kg, sample, rng_hash, dimension);
return tabulated_sobol_sample_2D(kg, sample, rng_hash, dimension);
}
}
ccl_device_forceinline float3 path_rng_3D(KernelGlobals kg,
uint rng_hash,
int sample,
int dimension)
{
#ifdef __DEBUG_CORRELATION__
return make_float3((float)drand48(), (float)drand48(), (float)drand48());
#endif
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_SOBOL_BURLEY) {
const uint index_mask = kernel_data.integrator.sobol_index_mask;
return sobol_burley_sample_3D(sample, dimension, rng_hash, index_mask);
}
else {
return tabulated_sobol_sample_3D(kg, sample, rng_hash, dimension);
}
}
ccl_device_forceinline float4 path_rng_4D(KernelGlobals kg,
uint rng_hash,
int sample,
int dimension)
{
#ifdef __DEBUG_CORRELATION__
return make_float4((float)drand48(), (float)drand48(), (float)drand48(), (float)drand48());
#endif
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_SOBOL_BURLEY) {
const uint index_mask = kernel_data.integrator.sobol_index_mask;
return sobol_burley_sample_4D(sample, dimension, rng_hash, index_mask);
}
else {
return tabulated_sobol_sample_4D(kg, sample, rng_hash, dimension);
}
}
@ -97,7 +135,7 @@ ccl_device_inline uint path_rng_hash_init(KernelGlobals kg,
ccl_device_inline bool sample_is_class_A(int pattern, int sample)
{
#if 0
if (!(pattern == SAMPLING_PATTERN_PMJ || pattern == SAMPLING_PATTERN_SOBOL_BURLEY)) {
if (!(pattern == SAMPLING_PATTERN_TABULATED_SOBOL || pattern == SAMPLING_PATTERN_SOBOL_BURLEY)) {
/* Fallback: assign samples randomly.
* This is guaranteed to work "okay" for any sampler, but isn't good.
* (NOTE: the seed constant is just a random number to guard against
@ -114,8 +152,8 @@ ccl_device_inline bool sample_is_class_A(int pattern, int sample)
* Multi-Jittered Sample Sequences" by Christensen et al., but
* implemented with efficient bit-fiddling.
*
* This approach also turns out to work equally well with Sobol-Burley
* (see https://developer.blender.org/D15746#429471).
* This approach also turns out to work equally well with Owen
* scrambled and shuffled Sobol (see https://developer.blender.org/D15746#429471).
*/
return popcount(uint(sample) & 0xaaaaaaaa) & 1;
}

View File

@ -65,31 +65,75 @@ ccl_device_forceinline float sobol_burley(uint rev_bit_index,
}
/*
* Computes a 1D Owen-scrambled and shuffled Sobol sample.
* NOTE: the functions below intentionally produce samples that are
* uncorrelated between functions. For example, a 1D sample and 2D
* sample produced with the same index, dimension, and seed are
* uncorrelated with each other. This allows more care-free usage
* of the functions together, without having to worry about
* e.g. 1D and 2D samples being accidentally correlated with each
* other.
*/
ccl_device float sobol_burley_sample_1D(uint index, uint const dimension, uint seed)
/*
* Computes a 1D Owen-scrambled and shuffled Sobol sample.
*
* `index` is the index of the sample in the sequence.
*
* `dimension` is which dimensions of the sample you want to fetch. Note
* that different 1D dimensions are uncorrelated. For samples with > 1D
* stratification, use the multi-dimensional sampling methods below.
*
* `seed`: different seeds produce statistically independent,
* uncorrelated sequences.
*
* `shuffled_index_mask` limits the sample sequence length, improving
* performance. It must be a string of binary 1 bits followed by a
* string of binary 0 bits (e.g. 0xffff0000) for the sampler to operate
* correctly. In general, `reverse_integer_bits(shuffled_index_mask)`
* should be >= the maximum number of samples expected to be taken. A safe
* default (but least performant) is 0xffffffff, for maximum sequence
* length.
*/
ccl_device float sobol_burley_sample_1D(uint index,
uint const dimension,
uint seed,
uint shuffled_index_mask)
{
/* Include the dimension in the seed, so we get decorrelated
* sequences for different dimensions via shuffling. */
seed ^= hash_hp_uint(dimension);
/* Shuffle. */
/* Shuffle and mask. The masking is just for better
* performance at low sample counts. */
index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xbff95bfe);
index &= shuffled_index_mask;
return sobol_burley(index, 0, seed ^ 0x635c77bd);
}
/*
* Computes a 2D Owen-scrambled and shuffled Sobol sample.
*
* `dimension_set` is which two dimensions of the sample you want to
* fetch. For example, 0 is the first two, 1 is the second two, etc.
* The dimensions within a single set are stratified, but different sets
* are uncorrelated.
*
* See sobol_burley_sample_1D for further usage details.
*/
ccl_device float2 sobol_burley_sample_2D(uint index, const uint dimension_set, uint seed)
ccl_device float2 sobol_burley_sample_2D(uint index,
const uint dimension_set,
uint seed,
uint shuffled_index_mask)
{
/* Include the dimension set in the seed, so we get decorrelated
* sequences for different dimension sets via shuffling. */
seed ^= hash_hp_uint(dimension_set);
/* Shuffle. */
/* Shuffle and mask. The masking is just for better
* performance at low sample counts. */
index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xf8ade99a);
index &= shuffled_index_mask;
return make_float2(sobol_burley(index, 0, seed ^ 0xe0aaaf76),
sobol_burley(index, 1, seed ^ 0x94964d4e));
@ -97,15 +141,27 @@ ccl_device float2 sobol_burley_sample_2D(uint index, const uint dimension_set, u
/*
* Computes a 3D Owen-scrambled and shuffled Sobol sample.
*
* `dimension_set` is which three dimensions of the sample you want to
* fetch. For example, 0 is the first three, 1 is the second three, etc.
* The dimensions within a single set are stratified, but different sets
* are uncorrelated.
*
* See sobol_burley_sample_1D for further usage details.
*/
ccl_device float3 sobol_burley_sample_3D(uint index, const uint dimension_set, uint seed)
ccl_device float3 sobol_burley_sample_3D(uint index,
const uint dimension_set,
uint seed,
uint shuffled_index_mask)
{
/* Include the dimension set in the seed, so we get decorrelated
* sequences for different dimension sets via shuffling. */
seed ^= hash_hp_uint(dimension_set);
/* Shuffle. */
/* Shuffle and mask. The masking is just for better
* performance at low sample counts. */
index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xcaa726ac);
index &= shuffled_index_mask;
return make_float3(sobol_burley(index, 0, seed ^ 0x9e78e391),
sobol_burley(index, 1, seed ^ 0x67c33241),
@ -114,15 +170,27 @@ ccl_device float3 sobol_burley_sample_3D(uint index, const uint dimension_set, u
/*
* Computes a 4D Owen-scrambled and shuffled Sobol sample.
*
* `dimension_set` is which four dimensions of the sample you want to
* fetch. For example, 0 is the first four, 1 is the second four, etc.
* The dimensions within a single set are stratified, but different sets
* are uncorrelated.
*
* See sobol_burley_sample_1D for further usage details.
*/
ccl_device float4 sobol_burley_sample_4D(uint index, const uint dimension_set, uint seed)
ccl_device float4 sobol_burley_sample_4D(uint index,
const uint dimension_set,
uint seed,
uint shuffled_index_mask)
{
/* Include the dimension set in the seed, so we get decorrelated
* sequences for different dimension sets via shuffling. */
seed ^= hash_hp_uint(dimension_set);
/* Shuffle. */
/* Shuffle and mask. The masking is just for better
* performance at low sample counts. */
index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xc2c1a055);
index &= shuffled_index_mask;
return make_float4(sobol_burley(index, 0, seed ^ 0x39468210),
sobol_burley(index, 1, seed ^ 0xe9d8a845),

View File

@ -0,0 +1,174 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "kernel/sample/util.h"
#include "util/hash.h"
#pragma once
CCL_NAMESPACE_BEGIN
ccl_device uint tabulated_sobol_shuffled_sample_index(KernelGlobals kg,
uint sample,
uint dimension,
uint seed)
{
const uint sample_count = kernel_data.integrator.tabulated_sobol_sequence_size;
/* Shuffle the pattern order and sample index to decorrelate
* dimensions and make the most of the finite patterns we have.
* The funky sample mask stuff is to ensure that we only shuffle
* *within* the current sample pattern, which is necessary to avoid
* early repeat pattern use. */
const uint pattern_i = hash_shuffle_uint(dimension, NUM_TAB_SOBOL_PATTERNS, seed);
/* sample_count should always be a power of two, so this results in a mask. */
const uint sample_mask = sample_count - 1;
const uint sample_shuffled = nested_uniform_scramble(sample,
hash_wang_seeded_uint(dimension, seed));
sample = (sample & ~sample_mask) | (sample_shuffled & sample_mask);
return ((pattern_i * sample_count) + sample) % (sample_count * NUM_TAB_SOBOL_PATTERNS);
}
ccl_device float tabulated_sobol_sample_1D(KernelGlobals kg,
uint sample,
const uint rng_hash,
const uint dimension)
{
uint seed = rng_hash;
/* Use the same sample sequence seed for all pixels when using
* scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
seed = kernel_data.integrator.seed;
}
/* Fetch the sample. */
const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
/* Do limited Cranley-Patterson rotation when using scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
kernel_data.integrator.scrambling_distance;
x += jitter_x;
x -= floorf(x);
}
return x;
}
ccl_device float2 tabulated_sobol_sample_2D(KernelGlobals kg,
uint sample,
const uint rng_hash,
const uint dimension)
{
uint seed = rng_hash;
/* Use the same sample sequence seed for all pixels when using
* scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
seed = kernel_data.integrator.seed;
}
/* Fetch the sample. */
const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
float y = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 1);
/* Do limited Cranley-Patterson rotation when using scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
kernel_data.integrator.scrambling_distance;
const float jitter_y = hash_wang_seeded_float(dimension, rng_hash ^ 0xca0e1151) *
kernel_data.integrator.scrambling_distance;
x += jitter_x;
y += jitter_y;
x -= floorf(x);
y -= floorf(y);
}
return make_float2(x, y);
}
ccl_device float3 tabulated_sobol_sample_3D(KernelGlobals kg,
uint sample,
const uint rng_hash,
const uint dimension)
{
uint seed = rng_hash;
/* Use the same sample sequence seed for all pixels when using
* scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
seed = kernel_data.integrator.seed;
}
/* Fetch the sample. */
const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
float y = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 1);
float z = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 2);
/* Do limited Cranley-Patterson rotation when using scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
kernel_data.integrator.scrambling_distance;
const float jitter_y = hash_wang_seeded_float(dimension, rng_hash ^ 0xca0e1151) *
kernel_data.integrator.scrambling_distance;
const float jitter_z = hash_wang_seeded_float(dimension, rng_hash ^ 0xbf604c5a) *
kernel_data.integrator.scrambling_distance;
x += jitter_x;
y += jitter_y;
z += jitter_z;
x -= floorf(x);
y -= floorf(y);
z -= floorf(z);
}
return make_float3(x, y, z);
}
ccl_device float4 tabulated_sobol_sample_4D(KernelGlobals kg,
uint sample,
const uint rng_hash,
const uint dimension)
{
uint seed = rng_hash;
/* Use the same sample sequence seed for all pixels when using
* scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
seed = kernel_data.integrator.seed;
}
/* Fetch the sample. */
const uint index = tabulated_sobol_shuffled_sample_index(kg, sample, dimension, seed);
float x = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS);
float y = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 1);
float z = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 2);
float w = kernel_data_fetch(sample_pattern_lut, index * NUM_TAB_SOBOL_DIMENSIONS + 3);
/* Do limited Cranley-Patterson rotation when using scrambling distance. */
if (kernel_data.integrator.scrambling_distance < 1.0f) {
const float jitter_x = hash_wang_seeded_float(dimension, rng_hash) *
kernel_data.integrator.scrambling_distance;
const float jitter_y = hash_wang_seeded_float(dimension, rng_hash ^ 0xca0e1151) *
kernel_data.integrator.scrambling_distance;
const float jitter_z = hash_wang_seeded_float(dimension, rng_hash ^ 0xbf604c5a) *
kernel_data.integrator.scrambling_distance;
const float jitter_w = hash_wang_seeded_float(dimension, rng_hash ^ 0x99634d1d) *
kernel_data.integrator.scrambling_distance;
x += jitter_x;
y += jitter_y;
z += jitter_z;
w += jitter_w;
x -= floorf(x);
y -= floorf(y);
z -= floorf(z);
w -= floorf(w);
}
return make_float4(x, y, z, w);
}
CCL_NAMESPACE_END

View File

@ -148,8 +148,7 @@ CCL_NAMESPACE_BEGIN
enum PathTraceDimension {
/* Init bounce */
PRNG_FILTER = 0,
PRNG_LENS = 1,
PRNG_TIME = 2,
PRNG_LENS_TIME = 1,
/* Shade bounce */
PRNG_TERMINATE = 0,
@ -187,7 +186,7 @@ enum PathTraceDimension {
enum SamplingPattern {
SAMPLING_PATTERN_SOBOL_BURLEY = 0,
SAMPLING_PATTERN_PMJ = 1,
SAMPLING_PATTERN_TABULATED_SOBOL = 1,
SAMPLING_NUM_PATTERNS,
};
@ -1032,13 +1031,28 @@ typedef struct LocalIntersection {
typedef struct KernelCamera {
/* type */
int type;
int use_dof_or_motion_blur;
/* depth of field */
float aperturesize;
float blades;
float bladesrotation;
float focaldistance;
/* motion blur */
float shuttertime;
int num_motion_steps, have_perspective_motion;
int pad1;
int pad2;
int pad3;
/* panorama */
int panorama_type;
float fisheye_fov;
float fisheye_lens;
float4 equirectangular_range;
float fisheye_lens_polynomial_bias;
float4 equirectangular_range;
float4 fisheye_lens_polynomial_coefficients;
/* stereo */
@ -1055,16 +1069,6 @@ typedef struct KernelCamera {
float4 dx;
float4 dy;
/* depth of field */
float aperturesize;
float blades;
float bladesrotation;
float focaldistance;
/* motion blur */
float shuttertime;
int num_motion_steps, have_perspective_motion;
/* clipping */
float nearclip;
float cliplength;
@ -1075,7 +1079,6 @@ typedef struct KernelCamera {
/* render size */
float width, height;
int pad1;
/* anamorphic lens bokeh */
float inv_aperture_ratio;
@ -1466,15 +1469,15 @@ typedef struct KernelShaderEvalInput {
} KernelShaderEvalInput;
static_assert_align(KernelShaderEvalInput, 16);
/* Pre-computed sample table sizes for PMJ02 sampler.
/* Pre-computed sample table sizes for the tabulated Sobol sampler.
*
* NOTE: min and max samples *must* be a power of two, and patterns
* ideally should be as well.
*/
#define MIN_PMJ_SAMPLES 256
#define MAX_PMJ_SAMPLES 8192
#define NUM_PMJ_DIMENSIONS 2
#define NUM_PMJ_PATTERNS 256
#define MIN_TAB_SOBOL_SAMPLES 256
#define MAX_TAB_SOBOL_SAMPLES 8192
#define NUM_TAB_SOBOL_DIMENSIONS 4
#define NUM_TAB_SOBOL_PATTERNS 256
/* Device kernels.
*

View File

@ -23,7 +23,6 @@ set(SRC
image_sky.cpp
image_vdb.cpp
integrator.cpp
jitter.cpp
light.cpp
light_tree.cpp
mesh.cpp
@ -43,6 +42,7 @@ set(SRC
stats.cpp
svm.cpp
tables.cpp
tabulated_sobol.cpp
volume.cpp
)
@ -65,7 +65,6 @@ set(SRC_HEADERS
integrator.h
light.h
light_tree.h
jitter.h
mesh.h
object.h
osl.h
@ -81,6 +80,7 @@ set(SRC_HEADERS
stats.h
svm.h
tables.h
tabulated_sobol.h
volume.h
)

View File

@ -8,12 +8,12 @@
#include "scene/camera.h"
#include "scene/film.h"
#include "scene/integrator.h"
#include "scene/jitter.h"
#include "scene/light.h"
#include "scene/object.h"
#include "scene/scene.h"
#include "scene/shader.h"
#include "scene/stats.h"
#include "scene/tabulated_sobol.h"
#include "kernel/types.h"
@ -107,8 +107,11 @@ NODE_DEFINE(Integrator)
static NodeEnum sampling_pattern_enum;
sampling_pattern_enum.insert("sobol_burley", SAMPLING_PATTERN_SOBOL_BURLEY);
sampling_pattern_enum.insert("pmj", SAMPLING_PATTERN_PMJ);
SOCKET_ENUM(sampling_pattern, "Sampling Pattern", sampling_pattern_enum, SAMPLING_PATTERN_PMJ);
sampling_pattern_enum.insert("tabulated_sobol", SAMPLING_PATTERN_TABULATED_SOBOL);
SOCKET_ENUM(sampling_pattern,
"Sampling Pattern",
sampling_pattern_enum,
SAMPLING_PATTERN_TABULATED_SOBOL);
SOCKET_FLOAT(scrambling_distance, "Scrambling Distance", 1.0f);
static NodeEnum denoiser_type_enum;
@ -250,6 +253,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->sampling_pattern = sampling_pattern;
kintegrator->scrambling_distance = scrambling_distance;
kintegrator->sobol_index_mask = reverse_integer_bits(next_power_of_two(aa_samples - 1) - 1);
kintegrator->use_light_tree = scene->integrator->use_light_tree;
if (light_sampling_threshold > 0.0f) {
@ -259,23 +263,23 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
kintegrator->light_inv_rr_threshold = 0.0f;
}
constexpr int num_sequences = NUM_PMJ_PATTERNS;
int sequence_size = clamp(next_power_of_two(aa_samples - 1), MIN_PMJ_SAMPLES, MAX_PMJ_SAMPLES);
if (kintegrator->sampling_pattern == SAMPLING_PATTERN_PMJ &&
/* Build pre-tabulated Sobol samples if needed. */
int sequence_size = clamp(
next_power_of_two(aa_samples - 1), MIN_TAB_SOBOL_SAMPLES, MAX_TAB_SOBOL_SAMPLES);
if (kintegrator->sampling_pattern == SAMPLING_PATTERN_TABULATED_SOBOL &&
dscene->sample_pattern_lut.size() !=
(sequence_size * NUM_PMJ_DIMENSIONS * NUM_PMJ_PATTERNS)) {
kintegrator->pmj_sequence_size = sequence_size;
(sequence_size * NUM_TAB_SOBOL_PATTERNS * NUM_TAB_SOBOL_DIMENSIONS)) {
kintegrator->tabulated_sobol_sequence_size = sequence_size;
if (dscene->sample_pattern_lut.size() != 0) {
dscene->sample_pattern_lut.free();
}
float2 *directions = (float2 *)dscene->sample_pattern_lut.alloc(sequence_size * num_sequences *
NUM_PMJ_DIMENSIONS);
float4 *directions = (float4 *)dscene->sample_pattern_lut.alloc(
sequence_size * NUM_TAB_SOBOL_PATTERNS * NUM_TAB_SOBOL_DIMENSIONS);
TaskPool pool;
for (int j = 0; j < num_sequences; ++j) {
float2 *sequence = directions + j * sequence_size;
pool.push(
function_bind(&progressive_multi_jitter_02_generate_2D, sequence, sequence_size, j));
for (int j = 0; j < NUM_TAB_SOBOL_PATTERNS; ++j) {
float4 *sequence = directions + j * sequence_size;
pool.push(function_bind(&tabulated_sobol_generate_4D, sequence, sequence_size, j));
}
pool.wait_work();

View File

@ -1,57 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2019-2022 Blender Foundation */
/* This file is based on "Progressive Multi-Jittered Sample Sequences"
* by Christensen, Kensler, and Kilpatrick, but with a much simpler and
* faster implementation based on "Stochastic Generation of (t, s)
* Sample Sequences" by Helmer, Christensen, and Kensler.
*/
#include "scene/jitter.h"
#include "util/hash.h"
#include <math.h>
#include <vector>
CCL_NAMESPACE_BEGIN
void progressive_multi_jitter_02_generate_2D(float2 points[], int size, int rng_seed)
{
/* Xor values for generating the PMJ02 sequence. These permute the
* order we visit the strata in, which is what makes the code below
* produce the PMJ02 sequence. Other choices are also possible, but
* result in different sequences. */
static uint xors[2][32] = {
{0x00000000, 0x00000000, 0x00000002, 0x00000006, 0x00000006, 0x0000000e, 0x00000036,
0x0000004e, 0x00000016, 0x0000002e, 0x00000276, 0x000006ce, 0x00000716, 0x00000c2e,
0x00003076, 0x000040ce, 0x00000116, 0x0000022e, 0x00020676, 0x00060ece, 0x00061716,
0x000e2c2e, 0x00367076, 0x004ec0ce, 0x00170116, 0x002c022e, 0x02700676, 0x06c00ece,
0x07001716, 0x0c002c2e, 0x30007076, 0x4000c0ce},
{0x00000000, 0x00000001, 0x00000003, 0x00000003, 0x00000007, 0x0000001b, 0x00000027,
0x0000000b, 0x00000017, 0x0000013b, 0x00000367, 0x0000038b, 0x00000617, 0x0000183b,
0x00002067, 0x0000008b, 0x00000117, 0x0001033b, 0x00030767, 0x00030b8b, 0x00071617,
0x001b383b, 0x00276067, 0x000b808b, 0x00160117, 0x0138033b, 0x03600767, 0x03800b8b,
0x06001617, 0x1800383b, 0x20006067, 0x0000808b}};
uint rng_i = rng_seed;
points[0].x = hash_hp_float(rng_i++);
points[0].y = hash_hp_float(rng_i++);
/* Subdivide the domain into smaller and smaller strata, filling in new
* points as we go. */
for (int log_N = 0, N = 1; N < size; log_N++, N *= 2) {
float strata_count = (float)(N * 2);
for (int i = 0; i < N && (N + i) < size; i++) {
/* Find the strata that are already occupied in this cell. */
uint occupied_x_stratum = (uint)(points[i ^ xors[0][log_N]].x * strata_count);
uint occupied_y_stratum = (uint)(points[i ^ xors[1][log_N]].y * strata_count);
/* Generate a new point in the unoccupied strata. */
points[N + i].x = ((float)(occupied_x_stratum ^ 1) + hash_hp_float(rng_i++)) / strata_count;
points[N + i].y = ((float)(occupied_y_stratum ^ 1) + hash_hp_float(rng_i++)) / strata_count;
}
}
}
CCL_NAMESPACE_END

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2019-2022 Blender Foundation */
#ifndef __JITTER_H__
#define __JITTER_H__
#include "util/types.h"
CCL_NAMESPACE_BEGIN
void progressive_multi_jitter_02_generate_2D(float2 points[], int size, int rng_seed);
CCL_NAMESPACE_END
#endif /* __JITTER_H__ */

View File

@ -226,6 +226,7 @@ NODE_DEFINE(ImageTextureNode)
extension_enum.insert("periodic", EXTENSION_REPEAT);
extension_enum.insert("clamp", EXTENSION_EXTEND);
extension_enum.insert("black", EXTENSION_CLIP);
extension_enum.insert("mirror", EXTENSION_MIRROR);
SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT);
static NodeEnum projection_enum;

View File

@ -0,0 +1,71 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2019-2022 Blender Foundation */
/* This file is based on the paper "Stochastic Generation of (t, s)
* Sample Sequences" by Helmer, Christensen, and Kensler.
*/
#include "scene/tabulated_sobol.h"
#include "util/hash.h"
#include <math.h>
#include <vector>
CCL_NAMESPACE_BEGIN
void tabulated_sobol_generate_4D(float4 points[], int size, int rng_seed)
{
/* Xor values for generating the (4D) Owen-scrambled Sobol sequence.
* These permute the order we visit the strata in, which is what
* makes the code below produce the scrambled Sobol sequence. Other
* choices are also possible, but result in different sequences. */
static uint xors[4][32] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0x00000000, 0x00000001, 0x00000001, 0x00000007, 0x00000001, 0x00000013, 0x00000015,
0x0000007f, 0x00000001, 0x00000103, 0x00000105, 0x0000070f, 0x00000111, 0x00001333,
0x00001555, 0x00007fff, 0x00000001, 0x00010003, 0x00010005, 0x0007000f, 0x00010011,
0x00130033, 0x00150055, 0x007f00ff, 0x00010101, 0x01030303, 0x01050505, 0x070f0f0f,
0x01111111, 0x13333333, 0x15555555, 0x7fffffff},
{0x00000000, 0x00000001, 0x00000003, 0x00000001, 0x00000005, 0x0000001f, 0x0000002b,
0x0000003d, 0x00000011, 0x00000133, 0x00000377, 0x00000199, 0x00000445, 0x00001ccf,
0x00002ddb, 0x0000366d, 0x00000101, 0x00010303, 0x00030707, 0x00010909, 0x00051515,
0x001f3f3f, 0x002b6b6b, 0x003dbdbd, 0x00101011, 0x01303033, 0x03707077, 0x01909099,
0x04515145, 0x1cf3f3cf, 0x2db6b6db, 0x36dbdb6d},
{0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x0000000d, 0x0000000c, 0x00000005,
0x0000004f, 0x00000014, 0x000000e7, 0x00000329, 0x0000039c, 0x00000011, 0x00001033,
0x00000044, 0x000030bb, 0x0000d1cd, 0x0000c2ec, 0x00005415, 0x0004fc3f, 0x00015054,
0x000e5c97, 0x0032e5b9, 0x0039725c, 0x00000101, 0x01000303, 0x00000404, 0x03000b0b,
0x0d001d1d, 0x0c002c2c, 0x05004545, 0x4f00cfcf},
};
/* Randomize the seed, in case it's incrementing. The constant is just a
* random number, and has no other significance. */
uint rng_i = hash_hp_seeded_uint(rng_seed, 0x44605a73);
points[0].x = hash_hp_float(rng_i++);
points[0].y = hash_hp_float(rng_i++);
points[0].z = hash_hp_float(rng_i++);
points[0].w = hash_hp_float(rng_i++);
/* Subdivide the domain into smaller and smaller strata, filling in new
* points as we go. */
for (int log_N = 0, N = 1; N < size; log_N++, N *= 2) {
float strata_count = (float)(N * 2);
for (int i = 0; i < N && (N + i) < size; i++) {
/* Find the strata that are already occupied in this cell. */
uint occupied_x_stratum = (uint)(points[i ^ xors[0][log_N]].x * strata_count);
uint occupied_y_stratum = (uint)(points[i ^ xors[1][log_N]].y * strata_count);
uint occupied_z_stratum = (uint)(points[i ^ xors[2][log_N]].z * strata_count);
uint occupied_w_stratum = (uint)(points[i ^ xors[3][log_N]].w * strata_count);
/* Generate a new point in the unoccupied strata. */
points[N + i].x = ((float)(occupied_x_stratum ^ 1) + hash_hp_float(rng_i++)) / strata_count;
points[N + i].y = ((float)(occupied_y_stratum ^ 1) + hash_hp_float(rng_i++)) / strata_count;
points[N + i].z = ((float)(occupied_z_stratum ^ 1) + hash_hp_float(rng_i++)) / strata_count;
points[N + i].w = ((float)(occupied_w_stratum ^ 1) + hash_hp_float(rng_i++)) / strata_count;
}
}
}
CCL_NAMESPACE_END

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2019-2022 Blender Foundation */
#ifndef __TABULATED_SOBOL_H__
#define __TABULATED_SOBOL_H__
#include "util/types.h"
CCL_NAMESPACE_BEGIN
void tabulated_sobol_generate_4D(float4 points[], int size, int rng_seed);
CCL_NAMESPACE_END
#endif /* __TABULATED_SOBOL_H__ */

View File

@ -22,13 +22,26 @@ static bool validate_cpu_capabilities()
#endif
}
/* These are not just static variables because we don't want to run the
* constructor until we know the instructions are supported. */
static vfloat8 float8_a()
{
return make_vfloat8(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f);
}
static vfloat8 float8_b()
{
return make_vfloat8(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
}
static vfloat8 float8_c()
{
return make_vfloat8(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f);
}
#define INIT_FLOAT8_TEST \
if (!validate_cpu_capabilities()) \
return; \
\
const vfloat8 float8_a = make_vfloat8(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); \
const vfloat8 float8_b = make_vfloat8(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); \
const vfloat8 float8_c = make_vfloat8(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f);
return;
#define compare_vector_scalar(a, b) \
for (size_t index = 0; index < 8; index++) \
@ -57,15 +70,15 @@ static bool validate_cpu_capabilities()
static const float float_b = 1.5f;
TEST(TEST_CATEGORY_NAME,
float8_add_vv){basic_test_vv(float8_a, float8_b, +)} TEST(TEST_CATEGORY_NAME, float8_sub_vv){
basic_test_vv(float8_a, float8_b, -)} TEST(TEST_CATEGORY_NAME, float8_mul_vv){
basic_test_vv(float8_a, float8_b, *)} TEST(TEST_CATEGORY_NAME, float8_div_vv){
basic_test_vv(float8_a, float8_b, /)} TEST(TEST_CATEGORY_NAME, float8_add_vf){
basic_test_vf(float8_a, float_b, +)} TEST(TEST_CATEGORY_NAME, float8_sub_vf){
basic_test_vf(float8_a, float_b, -)} TEST(TEST_CATEGORY_NAME, float8_mul_vf){
basic_test_vf(float8_a, float_b, *)} TEST(TEST_CATEGORY_NAME,
float8_div_vf){basic_test_vf(float8_a, float_b, /)}
TEST(TEST_CATEGORY_NAME, float8_add_vv){
basic_test_vv(float8_a(), float8_b(), +)} TEST(TEST_CATEGORY_NAME, float8_sub_vv){
basic_test_vv(float8_a(), float8_b(), -)} TEST(TEST_CATEGORY_NAME, float8_mul_vv){
basic_test_vv(float8_a(), float8_b(), *)} TEST(TEST_CATEGORY_NAME, float8_div_vv){
basic_test_vv(float8_a(), float8_b(), /)} TEST(TEST_CATEGORY_NAME, float8_add_vf){
basic_test_vf(float8_a(), float_b, +)} TEST(TEST_CATEGORY_NAME, float8_sub_vf){
basic_test_vf(float8_a(), float_b, -)} TEST(TEST_CATEGORY_NAME, float8_mul_vf){
basic_test_vf(float8_a(), float_b, *)} TEST(TEST_CATEGORY_NAME, float8_div_vf){
basic_test_vf(float8_a(), float_b, /)}
TEST(TEST_CATEGORY_NAME, float8_ctor)
{
@ -85,18 +98,18 @@ TEST(TEST_CATEGORY_NAME, float8_sqrt)
TEST(TEST_CATEGORY_NAME, float8_min_max)
{
INIT_FLOAT8_TEST
compare_vector_vector(min(float8_a, float8_b), float8_a);
compare_vector_vector(max(float8_a, float8_b), float8_b);
compare_vector_vector(min(float8_a(), float8_b()), float8_a());
compare_vector_vector(max(float8_a(), float8_b()), float8_b());
}
TEST(TEST_CATEGORY_NAME, float8_shuffle)
{
INIT_FLOAT8_TEST
vfloat8 res0 = shuffle<0, 1, 2, 3, 1, 3, 2, 0>(float8_a);
vfloat8 res0 = shuffle<0, 1, 2, 3, 1, 3, 2, 0>(float8_a());
compare_vector_vector(res0, make_vfloat8(0.1f, 0.2f, 0.3f, 0.4f, 0.6f, 0.8f, 0.7f, 0.5f));
vfloat8 res1 = shuffle<3>(float8_a);
vfloat8 res1 = shuffle<3>(float8_a());
compare_vector_vector(res1, make_vfloat8(0.4f, 0.4f, 0.4f, 0.4f, 0.8f, 0.8f, 0.8f, 0.8f));
vfloat8 res2 = shuffle<3, 2, 1, 0>(float8_a, float8_b);
vfloat8 res2 = shuffle<3, 2, 1, 0>(float8_a(), float8_b());
compare_vector_vector(res2, make_vfloat8(0.4f, 0.3f, 2.0f, 1.0f, 0.8f, 0.7f, 6.0f, 5.0f));
}

View File

@ -65,6 +65,8 @@ typedef enum ExtensionType {
EXTENSION_EXTEND = 1,
/* Clip to image size and set exterior pixels as transparent. */
EXTENSION_CLIP = 2,
/* Repeatedly flip the image horizontally and vertically. */
EXTENSION_MIRROR = 3,
EXTENSION_NUM_TYPES,
} ExtensionType;

View File

@ -5316,7 +5316,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
/* Connect to the Wayland server. */
display_->wl_display = wl_display_connect(nullptr);
if (!display_->wl_display) {
gwl_display_destroy(display_);
this->~GHOST_SystemWayland();
throw std::runtime_error("Wayland: unable to connect to display!");
}
@ -5360,7 +5360,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
"WAYLAND found but libdecor was not, install libdecor for Wayland support, "
"falling back to X11\n");
# endif
gwl_display_destroy(display_);
this->~GHOST_SystemWayland();
throw std::runtime_error("Wayland: unable to find libdecor!");
use_libdecor = true;
@ -5377,7 +5377,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
GWL_LibDecor_System &decor = *display_->libdecor;
decor.context = libdecor_new(display_->wl_display, &libdecor_interface);
if (!decor.context) {
gwl_display_destroy(display_);
this->~GHOST_SystemWayland();
throw std::runtime_error("Wayland: unable to create window decorations!");
}
}
@ -5388,7 +5388,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
{
GWL_XDG_Decor_System &decor = *display_->xdg_decor;
if (!decor.shell) {
gwl_display_destroy(display_);
this->~GHOST_SystemWayland();
throw std::runtime_error("Wayland: unable to access xdg_shell!");
}
}

View File

@ -1061,11 +1061,16 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
int32_t x_screen = screen_co[0], y_screen = screen_co[1];
if (window->getCursorGrabModeIsWarp()) {
/* WORKAROUND:
* Sometimes Windows ignores `SetCursorPos()` or `SendInput()` calls or the mouse event is
* outdated. Identify these cases by checking if the cursor is not yet within bounds. */
static bool is_warping_x = false;
static bool is_warping_y = false;
static uint64_t last_warp_time = 0;
{
/* WORKAROUND: Check the mouse event timestamp so we can ignore mousemove events that were
* already in the queue before we changed the cursor position. */
MOUSEMOVEPOINT mp = {x_screen, y_screen};
::GetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &mp, &mp, 1, GMMP_USE_DISPLAY_POINTS);
if (mp.time <= last_warp_time) {
return NULL;
}
}
int32_t x_new = x_screen;
int32_t y_new = y_screen;
@ -1112,31 +1117,35 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
window->getCursorGrabAccum(x_accum, y_accum);
if (x_new != x_screen || y_new != y_screen) {
system->setCursorPosition(x_new, y_new); /* wrap */
/* WORKAROUND: Store the current time so that we ignore outdated mousemove events. */
last_warp_time = ::GetTickCount64();
/* Do not update the accum values if we are an outdated or failed pos-warp event. */
if (!is_warping_x) {
is_warping_x = x_new != x_screen;
if (is_warping_x) {
x_accum += (x_screen - x_new);
}
}
/* For more control over which timestamp to store in the event, we use `SendInput` instead of
* `SetCursorPos` here.
* It is quite unlikely to happen, but still possible that some event between
* `last_warp_time` and `GHOST_SystemWin32::setCursorPosition` is sent. */
INPUT input[3] = {0};
input[0].type = INPUT_MOUSE;
input[0].mi.dx = (LONG)(x_new * (65535.0f / GetSystemMetrics(SM_CXSCREEN)));
input[0].mi.dy = (LONG)(y_new * (65535.0f / GetSystemMetrics(SM_CYSCREEN)));
input[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
input[0].mi.time = last_warp_time;
if (!is_warping_y) {
is_warping_y = y_new != y_screen;
if (is_warping_y) {
y_accum += (y_screen - y_new);
}
}
/* Send 3 events with a jitter to make sure Windows does not occasionally and
* inexplicably ignore `SetCursorPos` or `SendInput`. */
input[2] = input[1] = input[0];
input[1].mi.dx += 1;
::SendInput(3, input, sizeof(INPUT));
x_accum += (x_screen - x_new);
y_accum += (y_screen - y_new);
window->setCursorGrabAccum(x_accum, y_accum);
/* When wrapping we don't need to add an event because the setCursorPosition call will cause
* a new event after. */
/* When wrapping we don't need to add an event because the `SendInput` call will cause new
* events after. */
return NULL;
}
is_warping_x = false;
is_warping_y = false;
x_screen += x_accum;
y_screen += y_accum;
}
@ -1210,16 +1219,16 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
const bool ctrl_pressed = has_state && state[VK_CONTROL] & 0x80;
const bool alt_pressed = has_state && state[VK_MENU] & 0x80;
if (!key_down) {
/* Pass. */
}
/* We can be here with !key_down if processing dead keys (diacritics). See T103119. */
/* No text with control key pressed (Alt can be used to insert special characters though!). */
else if (ctrl_pressed && !alt_pressed) {
if (ctrl_pressed && !alt_pressed) {
/* Pass. */
}
/* Don't call #ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical
* composition. */
else if (MapVirtualKeyW(vk, 2) != 0) {
* composition. XXX: we are not checking return of MapVirtualKeyW for high bit set, which is
* what is supposed to indicate dead keys. But this is working now so approach cautiously. */
else if (MapVirtualKeyW(vk, MAPVK_VK_TO_CHAR) != 0) {
wchar_t utf16[3] = {0};
int r;
/* TODO: #ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here).
@ -1234,6 +1243,10 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
utf8_char[0] = '\0';
}
}
if (!key_down) {
/* Clear or wm_event_add_ghostevent will warn of unexpected data on key up. */
utf8_char[0] = '\0';
}
}
#ifdef WITH_INPUT_IME

View File

@ -167,7 +167,7 @@ add_library(bli_lib
"../../../source/blender/blenlib/intern/rct.c"
"../../../source/blender/blenlib/intern/string.c"
"../../../source/blender/blenlib/intern/string_utf8.c"
"../../../source/blender/blenlib/intern/listbase.c"
"../../../source/blender/blenlib/intern/listbase.cc"
"../../../source/blender/blenlib/intern/math_color.c"
"../../../source/blender/blenlib/intern/math_geom.c"
"../../../source/blender/blenlib/intern/math_matrix.c"

View File

@ -94,6 +94,16 @@ _namespace = globals()
_modules_loaded = [_namespace[name] for name in _modules]
del _namespace
def _addon_support_items():
"""Return the addon support levels suitable for this Blender build."""
items = [
('OFFICIAL', "Official", "Officially supported"),
('COMMUNITY', "Community", "Maintained by community developers"),
]
if bpy.app.version_cycle == 'alpha':
items.append(('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)"))
return items
def register():
from bpy.utils import register_class
@ -141,11 +151,7 @@ def register():
)
WindowManager.addon_support = EnumProperty(
items=[
('OFFICIAL', "Official", "Officially supported"),
('COMMUNITY', "Community", "Maintained by community developers"),
('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)")
],
items=_addon_support_items(),
name="Support",
description="Display support level",
default={'OFFICIAL', 'COMMUNITY'},

View File

@ -9,7 +9,6 @@
#include "AS_asset_catalog.hh"
#include "AS_asset_catalog_tree.hh"
#include "AS_asset_library.h"
#include "AS_asset_library.hh"
#include "BLI_fileops.hh"

View File

@ -17,7 +17,6 @@
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_set.hh"
#include "DNA_userdef_types.h"

View File

@ -7,8 +7,6 @@
#include "BKE_blender.h"
#include "BKE_preferences.h"
#include "BLI_fileops.h" /* For PATH_MAX (at least on Windows). */
#include "BLI_path_util.h"
#include "BLI_string_ref.hh"
#include "DNA_asset_types.h"

View File

@ -13,8 +13,6 @@
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
#include "BKE_asset.h"
namespace blender::asset_system {
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,

View File

@ -4,7 +4,6 @@
#include "AS_asset_catalog.hh"
#include "AS_asset_catalog_tree.hh"
#include "BKE_appdir.h"
#include "BKE_preferences.h"
#include "BLI_fileops.h"
@ -13,8 +12,6 @@
#include "DNA_asset_types.h"
#include "DNA_userdef_types.h"
#include "CLG_log.h"
#include "testing/testing.h"
#include "asset_library_test_common.hh"

View File

@ -4,17 +4,8 @@
#include "AS_asset_catalog.hh"
#include "AS_asset_catalog_tree.hh"
#include "BKE_appdir.h"
#include "BKE_preferences.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "DNA_asset_types.h"
#include "DNA_userdef_types.h"
#include "CLG_log.h"
#include "testing/testing.h"
#include "asset_library_test_common.hh"

View File

@ -5,7 +5,6 @@
#include "AS_asset_library.h"
#include "AS_asset_library.hh"
#include "BKE_appdir.h"
#include "BKE_callbacks.h"
#include "asset_library_service.hh"

View File

@ -25,13 +25,13 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 3
#define BLENDER_FILE_SUBVERSION 4
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
* was written with too new a version. */
#define BLENDER_FILE_MIN_VERSION 305
#define BLENDER_FILE_MIN_SUBVERSION 3
#define BLENDER_FILE_MIN_SUBVERSION 4
/** User readable version string. */
const char *BKE_blender_version_string(void);

View File

@ -254,14 +254,6 @@ void BKE_mesh_texspace_get_reference(struct Mesh *me,
float **r_size);
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
/**
* Split faces based on the edge angle and loop normals.
* Matches behavior of face splitting in render engines.
*
* \note Will leave #CD_NORMAL loop data layer which is used by render engines to set shading up.
*/
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
/**
* Create new mesh from the given object at its current state.
* The owner of this mesh is unknown, it is up to the caller to decide.

View File

@ -425,6 +425,11 @@ inline const bNode *bNodeTree::group_output_node() const
return this->runtime->group_output_node;
}
inline blender::Span<const bNode *> bNodeTree::group_input_nodes() const
{
return this->nodes_by_type("NodeGroupInput");
}
inline blender::Span<const bNodeSocket *> bNodeTree::all_input_sockets() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));

View File

@ -516,6 +516,11 @@ typedef struct SculptAttribute {
int elem_size, elem_num;
bool data_for_bmesh; /* Temporary data store as array outside of bmesh. */
/* Data is a flat array outside the CustomData system.
* This will be true if simple_array is requested in
* SculptAttributeParams, or the PBVH type is PBVH_GRIDS or PBVH_BMESH.
*/
bool simple_array;
/* Data stored per BMesh element. */
int bmesh_cd_offset;

View File

@ -414,7 +414,8 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, struct Mesh *me);
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
const int *grid_indices,
int totgrid,
int gridsize);
int gridsize,
int display_gridsize);
/**
* Multi-res level, only valid for type == #PBVH_GRIDS.

View File

@ -1436,7 +1436,7 @@ void BKE_fcurve_correct_bezpart(const float v1[2], float v2[2], float v3[2], con
}
/**
* Find roots of cubic equation (c0 x^3 + c1 x^2 + c2 x + c3)
* Find roots of cubic equation (c0 + c1 x + c2 x^2 + c3 x^3)
* \return number of roots in `o`.
*
* \note it is up to the caller to allocate enough memory for `o`.

View File

@ -1363,7 +1363,7 @@ void BKE_mesh_material_index_remove(Mesh *me, short index)
}
MutableVArraySpan<int> indices_span(material_indices.varray);
for (const int i : indices_span.index_range()) {
if (indices_span[i] > 0 && indices_span[i] > index) {
if (indices_span[i] > 0 && indices_span[i] >= index) {
indices_span[i]--;
}
}
@ -1836,267 +1836,6 @@ void BKE_mesh_calc_normals_split(Mesh *mesh)
BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh));
}
/* Split faces helper functions. */
struct SplitFaceNewVert {
struct SplitFaceNewVert *next;
int new_index;
int orig_index;
const float *vnor;
};
struct SplitFaceNewEdge {
struct SplitFaceNewEdge *next;
int new_index;
int orig_index;
int v1;
int v2;
};
/**
* Detect necessary new vertices, and update loop vertex indices accordingly.
* \warning Leaves mesh in invalid state.
* \param lnors_spacearr: Mandatory because trying to do the job in simple way without that data is
* doomed to fail, even when only dealing with smooth/flat faces one can find cases that no simple
* algorithm can handle properly.
*/
static int split_faces_prepare_new_verts(Mesh &mesh,
const MLoopNorSpaceArray &lnors_spacearr,
SplitFaceNewVert **new_verts,
MemArena &memarena)
{
const int loops_len = mesh.totloop;
int verts_len = mesh.totvert;
MutableSpan<MLoop> loops = mesh.loops_for_write();
BKE_mesh_vertex_normals_ensure(&mesh);
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh);
BitVector<> verts_used(verts_len, false);
BitVector<> done_loops(loops_len, false);
BLI_assert(lnors_spacearr.data_type == MLNOR_SPACEARR_LOOP_INDEX);
for (int loop_idx = 0; loop_idx < loops_len; loop_idx++) {
if (done_loops[loop_idx]) {
continue;
}
const MLoopNorSpace &lnor_space = *lnors_spacearr.lspacearr[loop_idx];
const int vert_idx = loops[loop_idx].v;
const bool vert_used = verts_used[vert_idx];
/* If vert is already used by another smooth fan, we need a new vert for this one. */
const int new_vert_idx = vert_used ? verts_len++ : vert_idx;
if (lnor_space.flags & MLNOR_SPACE_IS_SINGLE) {
/* Single loop in this fan... */
BLI_assert(POINTER_AS_INT(lnor_space.loops) == loop_idx);
done_loops[loop_idx].set();
if (vert_used) {
loops[loop_idx].v = new_vert_idx;
}
}
else {
for (const LinkNode *lnode = lnor_space.loops; lnode; lnode = lnode->next) {
const int ml_fan_idx = POINTER_AS_INT(lnode->link);
done_loops[ml_fan_idx].set();
if (vert_used) {
loops[ml_fan_idx].v = new_vert_idx;
}
}
}
if (!vert_used) {
verts_used[vert_idx].set();
/* We need to update that vertex's normal here, we won't go over it again. */
/* This is important! *DO NOT* set vnor to final computed lnor,
* vnor should always be defined to 'automatic normal' value computed from its polys,
* not some custom normal.
* Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */
copy_v3_v3(vert_normals[vert_idx], lnor_space.vec_lnor);
}
else {
/* Add new vert to list. */
SplitFaceNewVert *new_vert = static_cast<SplitFaceNewVert *>(
BLI_memarena_alloc(&memarena, sizeof(*new_vert)));
new_vert->orig_index = vert_idx;
new_vert->new_index = new_vert_idx;
new_vert->vnor = lnor_space.vec_lnor; /* See note above. */
new_vert->next = *new_verts;
*new_verts = new_vert;
}
}
return verts_len - mesh.totvert;
}
/* Detect needed new edges, and update accordingly loops' edge indices.
* WARNING! Leaves mesh in invalid state. */
static int split_faces_prepare_new_edges(Mesh *mesh,
SplitFaceNewEdge **new_edges,
MemArena *memarena)
{
const int num_polys = mesh->totpoly;
int num_edges = mesh->totedge;
MutableSpan<MEdge> edges = mesh->edges_for_write();
MutableSpan<MLoop> loops = mesh->loops_for_write();
const Span<MPoly> polys = mesh->polys();
BitVector<> edges_used(num_edges, false);
EdgeHash *edges_hash = BLI_edgehash_new_ex(__func__, num_edges);
const MPoly *mp = polys.data();
for (int poly_idx = 0; poly_idx < num_polys; poly_idx++, mp++) {
MLoop *ml_prev = &loops[mp->loopstart + mp->totloop - 1];
MLoop *ml = &loops[mp->loopstart];
for (int loop_idx = 0; loop_idx < mp->totloop; loop_idx++, ml++) {
void **eval;
if (!BLI_edgehash_ensure_p(edges_hash, ml_prev->v, ml->v, &eval)) {
const int edge_idx = ml_prev->e;
/* That edge has not been encountered yet, define it. */
if (edges_used[edge_idx]) {
/* Original edge has already been used, we need to define a new one. */
const int new_edge_idx = num_edges++;
*eval = POINTER_FROM_INT(new_edge_idx);
ml_prev->e = new_edge_idx;
SplitFaceNewEdge *new_edge = (SplitFaceNewEdge *)BLI_memarena_alloc(memarena,
sizeof(*new_edge));
new_edge->orig_index = edge_idx;
new_edge->new_index = new_edge_idx;
new_edge->v1 = ml_prev->v;
new_edge->v2 = ml->v;
new_edge->next = *new_edges;
*new_edges = new_edge;
}
else {
/* We can re-use original edge. */
edges[edge_idx].v1 = ml_prev->v;
edges[edge_idx].v2 = ml->v;
*eval = POINTER_FROM_INT(edge_idx);
edges_used[edge_idx].set();
}
}
else {
/* Edge already known, just update loop's edge index. */
ml_prev->e = POINTER_AS_INT(*eval);
}
ml_prev = ml;
}
}
BLI_edgehash_free(edges_hash, nullptr);
return num_edges - mesh->totedge;
}
/* Perform actual split of vertices. */
static void split_faces_split_new_verts(Mesh *mesh,
SplitFaceNewVert *new_verts,
const int num_new_verts)
{
const int verts_len = mesh->totvert - num_new_verts;
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(mesh);
/* Normals were already calculated at the beginning of this operation, we rely on that to update
* them partially here. */
BLI_assert(!BKE_mesh_vertex_normals_are_dirty(mesh));
/* Remember new_verts is a single linklist, so its items are in reversed order... */
for (int i = mesh->totvert - 1; i >= verts_len; i--, new_verts = new_verts->next) {
BLI_assert(new_verts->new_index == i);
BLI_assert(new_verts->new_index != new_verts->orig_index);
CustomData_copy_data(&mesh->vdata, &mesh->vdata, new_verts->orig_index, i, 1);
if (new_verts->vnor) {
copy_v3_v3(vert_normals[i], new_verts->vnor);
}
}
}
/* Perform actual split of edges. */
static void split_faces_split_new_edges(Mesh *mesh,
SplitFaceNewEdge *new_edges,
const int num_new_edges)
{
const int num_edges = mesh->totedge - num_new_edges;
MutableSpan<MEdge> edges = mesh->edges_for_write();
/* Remember new_edges is a single linklist, so its items are in reversed order... */
MEdge *new_med = &edges[mesh->totedge - 1];
for (int i = mesh->totedge - 1; i >= num_edges; i--, new_med--, new_edges = new_edges->next) {
BLI_assert(new_edges->new_index == i);
BLI_assert(new_edges->new_index != new_edges->orig_index);
CustomData_copy_data(&mesh->edata, &mesh->edata, new_edges->orig_index, i, 1);
new_med->v1 = new_edges->v1;
new_med->v2 = new_edges->v2;
}
}
void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
{
const int num_polys = mesh->totpoly;
if (num_polys == 0) {
return;
}
BKE_mesh_tessface_clear(mesh);
MLoopNorSpaceArray lnors_spacearr = {nullptr};
/* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */
BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr, ensure_corner_normal_layer(*mesh));
/* Stealing memarena from loop normals space array. */
MemArena *memarena = lnors_spacearr.mem;
SplitFaceNewVert *new_verts = nullptr;
SplitFaceNewEdge *new_edges = nullptr;
/* Detect loop normal spaces (a.k.a. smooth fans) that will need a new vert. */
const int num_new_verts = split_faces_prepare_new_verts(
*mesh, lnors_spacearr, &new_verts, *memarena);
if (num_new_verts > 0) {
/* Reminder: beyond this point, there is no way out, mesh is in invalid state
* (due to early-reassignment of loops' vertex and edge indices to new,
* to-be-created split ones). */
const int num_new_edges = split_faces_prepare_new_edges(mesh, &new_edges, memarena);
/* We can have to split a vertex without having to add a single new edge... */
const bool do_edges = (num_new_edges > 0);
/* Reallocate all vert and edge related data. */
CustomData_realloc(&mesh->vdata, mesh->totvert, mesh->totvert + num_new_verts);
mesh->totvert += num_new_verts;
if (do_edges) {
CustomData_realloc(&mesh->edata, mesh->totedge, mesh->totedge + num_new_edges);
mesh->totedge += num_new_edges;
}
/* Update normals manually to avoid recalculation after this operation. */
mesh->runtime->vert_normals = (float(*)[3])MEM_reallocN(mesh->runtime->vert_normals,
sizeof(float[3]) * mesh->totvert);
/* Perform actual split of vertices and edges. */
split_faces_split_new_verts(mesh, new_verts, num_new_verts);
if (do_edges) {
split_faces_split_new_edges(mesh, new_edges, num_new_edges);
}
}
/* NOTE: after this point mesh is expected to be valid again. */
/* CD_NORMAL is expected to be temporary only. */
if (free_loop_normals) {
CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
}
/* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */
BKE_lnor_spacearr_free(&lnors_spacearr);
#ifdef VALIDATE_MESH
BKE_mesh_validate(mesh, true, true);
#endif
}
/* **** Depsgraph evaluation **** */
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)

View File

@ -426,6 +426,28 @@ void multires_flush_sculpt_updates(Object *object)
}
Mesh *mesh = static_cast<Mesh *>(object->data);
/* Check that the multires modifier still exists.
* Fixes crash when deleting multires modifier
* from within sculpt mode.
*/
ModifierData *md;
MultiresModifierData *mmd = nullptr;
VirtualModifierData virtualModifierData;
for (md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); md;
md = md->next) {
if (md->type == eModifierType_Multires) {
if (BKE_modifier_is_enabled(nullptr, md, eModifierMode_Realtime)) {
mmd = (MultiresModifierData *)md;
}
}
}
if (!mmd) {
return;
}
multiresModifier_reshapeFromCCG(
sculpt_session->multires.modifier->totlvl, mesh, sculpt_session->subdiv_ccg);

View File

@ -1130,7 +1130,7 @@ static void node_init(const bContext *C, bNodeTree *ntree, bNode *node)
ntype->initfunc(ntree, node);
}
if (ntree->typeinfo->node_add_init != nullptr) {
if (ntree->typeinfo && ntree->typeinfo->node_add_init) {
ntree->typeinfo->node_add_init(ntree, node);
}

View File

@ -340,7 +340,7 @@ static void determine_group_input_states(
}
/* Check if group inputs are required to be single values, because they are (indirectly)
* connected to some socket that does not support fields. */
for (const bNode *node : tree.nodes_by_type("NodeGroupInput")) {
for (const bNode *node : tree.group_input_nodes()) {
for (const bNodeSocket *output_socket : node->output_sockets().drop_back(1)) {
SocketFieldState &state = field_state_by_socket_id[output_socket->index_in_tree()];
if (state.requires_single) {
@ -349,7 +349,7 @@ static void determine_group_input_states(
}
}
/* If an input does not support fields, this should be reflected in all Group Input nodes. */
for (const bNode *node : tree.nodes_by_type("NodeGroupInput")) {
for (const bNode *node : tree.group_input_nodes()) {
for (const bNodeSocket *output_socket : node->output_sockets().drop_back(1)) {
SocketFieldState &state = field_state_by_socket_id[output_socket->index_in_tree()];
const bool supports_field = new_inferencing_interface.inputs[output_socket->index()] !=

View File

@ -75,7 +75,7 @@ static SculptAttribute *sculpt_attribute_ensure_ex(Object *ob,
const SculptAttributeParams *params,
PBVHType pbvhtype,
bool flat_array_for_bmesh);
void sculptsession_bmesh_add_layers(Object *ob);
static void sculptsession_bmesh_add_layers(Object *ob);
using blender::MutableSpan;
using blender::Span;
@ -2454,7 +2454,7 @@ static bool sculpt_attribute_create(SculptSession *ss,
permanent = (out->params.permanent = false);
}
simple_array = (out->params.simple_array = true);
simple_array = true;
}
BLI_assert(!(simple_array && permanent));
@ -2467,6 +2467,7 @@ static bool sculpt_attribute_create(SculptSession *ss,
out->data = MEM_calloc_arrayN(totelem, elemsize, __func__);
out->data_for_bmesh = ss->bm != nullptr;
out->simple_array = true;
out->bmesh_cd_offset = -1;
out->layer = nullptr;
out->elem_size = elemsize;
@ -2476,6 +2477,8 @@ static bool sculpt_attribute_create(SculptSession *ss,
return true;
}
out->simple_array = false;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH: {
CustomData *cdata = nullptr;
@ -2511,8 +2514,6 @@ static bool sculpt_attribute_create(SculptSession *ss,
case PBVH_FACES: {
CustomData *cdata = nullptr;
out->data_for_bmesh = false;
switch (domain) {
case ATTR_DOMAIN_POINT:
cdata = &me->vdata;
@ -2534,10 +2535,10 @@ static bool sculpt_attribute_create(SculptSession *ss,
cdata->layers[index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
}
out->data = nullptr;
out->layer = cdata->layers + index;
out->bmesh_cd_offset = -1;
out->data = out->layer->data;
out->data_for_bmesh = false;
out->bmesh_cd_offset = -1;
out->elem_size = CustomData_get_elem_size(out->layer);
break;
@ -2565,31 +2566,36 @@ static bool sculpt_attr_update(Object *ob, SculptAttribute *attr)
bool bad = false;
if (attr->params.simple_array) {
if (attr->data) {
bad = attr->elem_num != elem_num;
if (bad) {
MEM_SAFE_FREE(attr->data);
}
else {
attr->data_for_bmesh = false;
}
}
else {
CustomData *cdata = sculpt_get_cdata(ob, attr->domain);
if (cdata) {
int layer_index = CustomData_get_named_layer_index(cdata, attr->proptype, attr->name);
/* Check if we are a coerced simple array and shouldn't be. */
bad |= attr->simple_array && !attr->params.simple_array &&
!ELEM(BKE_pbvh_type(ss->pbvh), PBVH_GRIDS, PBVH_BMESH);
bad |= (ss->bm != nullptr) != attr->data_for_bmesh;
CustomData *cdata = sculpt_get_cdata(ob, attr->domain);
if (cdata && !attr->simple_array) {
int layer_index = CustomData_get_named_layer_index(cdata, attr->proptype, attr->name);
bad |= layer_index == -1;
bad |= (ss->bm != nullptr) != attr->data_for_bmesh;
if (!bad) {
if (attr->data_for_bmesh) {
attr->bmesh_cd_offset = cdata->layers[layer_index].offset;
}
else {
attr->data = cdata->layers[layer_index].data;
}
}
}
if (bad) {
if (attr->simple_array) {
MEM_SAFE_FREE(attr->data);
}
sculpt_attribute_create(ss,
ob,
attr->domain,
@ -2598,7 +2604,7 @@ static bool sculpt_attr_update(Object *ob, SculptAttribute *attr)
attr,
&attr->params,
BKE_pbvh_type(ss->pbvh),
true);
attr->data_for_bmesh);
}
return bad;
@ -2724,6 +2730,8 @@ static SculptAttribute *sculpt_attribute_ensure_ex(Object *ob,
SculptAttribute *attr = BKE_sculpt_attribute_get(ob, domain, proptype, name);
if (attr) {
sculpt_attr_update(ob, attr);
return attr;
}
@ -2762,7 +2770,7 @@ static void sculptsession_bmesh_attr_update_internal(Object *ob)
}
}
void sculptsession_bmesh_add_layers(Object *ob)
static void sculptsession_bmesh_add_layers(Object *ob)
{
SculptSession *ss = ob->sculpt;
SculptAttributeParams params = {0};
@ -2869,7 +2877,7 @@ bool BKE_sculpt_attribute_destroy(Object *ob, SculptAttribute *attr)
Mesh *me = BKE_object_get_original_mesh(ob);
if (attr->params.simple_array) {
if (attr->simple_array) {
MEM_SAFE_FREE(attr->data);
}
else if (ss->bm) {

View File

@ -383,7 +383,8 @@ static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
const int *grid_indices,
int totgrid,
int gridsize)
int gridsize,
int display_gridsize)
{
const int gridarea = (gridsize - 1) * (gridsize - 1);
int totquad = 0;
@ -391,13 +392,18 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
/* grid hidden layer is present, so have to check each grid for
* visibility */
int depth1 = (int)(log2((double)gridsize - 1.0) + DBL_EPSILON);
int depth2 = (int)(log2((double)display_gridsize - 1.0) + DBL_EPSILON);
int skip = depth2 < depth1 ? 1 << (depth1 - depth2 - 1) : 1;
for (int i = 0; i < totgrid; i++) {
const BLI_bitmap *gh = grid_hidden[grid_indices[i]];
if (gh) {
/* grid hidden are present, have to check each element */
for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) {
for (int y = 0; y < gridsize - skip; y += skip) {
for (int x = 0; x < gridsize - skip; x += skip) {
if (!paint_is_grid_face_hidden(gh, gridsize, x, y)) {
totquad++;
}
@ -414,8 +420,11 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node)
{
int totquads = BKE_pbvh_count_grid_quads(
pbvh->grid_hidden, node->prim_indices, node->totprim, pbvh->gridkey.grid_size);
int totquads = BKE_pbvh_count_grid_quads(pbvh->grid_hidden,
node->prim_indices,
node->totprim,
pbvh->gridkey.grid_size,
pbvh->gridkey.grid_size);
BKE_pbvh_node_fully_hidden_set(node, (totquads == 0));
BKE_pbvh_node_mark_rebuild_draw(node);
}

View File

@ -89,7 +89,7 @@ set(SRC
intern/lasso_2d.c
intern/lazy_threading.cc
intern/length_parameterize.cc
intern/listbase.c
intern/listbase.cc
intern/math_base.c
intern/math_base_inline.c
intern/math_base_safe_inline.c

View File

@ -22,56 +22,56 @@
void BLI_movelisttolist(ListBase *dst, ListBase *src)
{
if (src->first == NULL) {
if (src->first == nullptr) {
return;
}
if (dst->first == NULL) {
if (dst->first == nullptr) {
dst->first = src->first;
dst->last = src->last;
}
else {
((Link *)dst->last)->next = src->first;
((Link *)src->first)->prev = dst->last;
((Link *)dst->last)->next = static_cast<Link *>(src->first);
((Link *)src->first)->prev = static_cast<Link *>(dst->last);
dst->last = src->last;
}
src->first = src->last = NULL;
src->first = src->last = nullptr;
}
void BLI_movelisttolist_reverse(ListBase *dst, ListBase *src)
{
if (src->first == NULL) {
if (src->first == nullptr) {
return;
}
if (dst->first == NULL) {
if (dst->first == nullptr) {
dst->first = src->first;
dst->last = src->last;
}
else {
((Link *)src->last)->next = dst->first;
((Link *)dst->first)->prev = src->last;
((Link *)src->last)->next = static_cast<Link *>(dst->first);
((Link *)dst->first)->prev = static_cast<Link *>(src->last);
dst->first = src->first;
}
src->first = src->last = NULL;
src->first = src->last = nullptr;
}
void BLI_addhead(ListBase *listbase, void *vlink)
{
Link *link = vlink;
Link *link = static_cast<Link *>(vlink);
if (link == NULL) {
if (link == nullptr) {
return;
}
link->next = listbase->first;
link->prev = NULL;
link->next = static_cast<Link *>(listbase->first);
link->prev = nullptr;
if (listbase->first) {
((Link *)listbase->first)->prev = link;
}
if (listbase->last == NULL) {
if (listbase->last == nullptr) {
listbase->last = link;
}
listbase->first = link;
@ -79,19 +79,19 @@ void BLI_addhead(ListBase *listbase, void *vlink)
void BLI_addtail(ListBase *listbase, void *vlink)
{
Link *link = vlink;
Link *link = static_cast<Link *>(vlink);
if (link == NULL) {
if (link == nullptr) {
return;
}
link->next = NULL;
link->prev = listbase->last;
link->next = nullptr;
link->prev = static_cast<Link *>(listbase->last);
if (listbase->last) {
((Link *)listbase->last)->next = link;
}
if (listbase->first == NULL) {
if (listbase->first == nullptr) {
listbase->first = link;
}
listbase->last = link;
@ -99,9 +99,9 @@ void BLI_addtail(ListBase *listbase, void *vlink)
void BLI_remlink(ListBase *listbase, void *vlink)
{
Link *link = vlink;
Link *link = static_cast<Link *>(vlink);
if (link == NULL) {
if (link == nullptr) {
return;
}
@ -132,8 +132,8 @@ bool BLI_remlink_safe(ListBase *listbase, void *vlink)
void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
{
Link *linka = vlinka;
Link *linkb = vlinkb;
Link *linka = static_cast<Link *>(vlinka);
Link *linkb = static_cast<Link *>(vlinkb);
if (!linka || !linkb) {
return;
@ -185,15 +185,15 @@ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vlinka, void *vlinkb)
{
Link *linka = vlinka;
Link *linkb = vlinkb;
Link linkc = {NULL};
Link *linka = static_cast<Link *>(vlinka);
Link *linkb = static_cast<Link *>(vlinkb);
Link linkc = {nullptr};
if (!linka || !linkb) {
return;
}
/* The reference to `linkc` assigns NULL, not a dangling pointer so it can be ignored. */
/* The reference to `linkc` assigns nullptr, not a dangling pointer so it can be ignored. */
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 1201 /* gcc12.1+ only */
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdangling-pointer"
@ -221,7 +221,7 @@ void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vli
void *BLI_pophead(ListBase *listbase)
{
Link *link;
if ((link = listbase->first)) {
if ((link = static_cast<Link *>(listbase->first))) {
BLI_remlink(listbase, link);
}
return link;
@ -230,7 +230,7 @@ void *BLI_pophead(ListBase *listbase)
void *BLI_poptail(ListBase *listbase)
{
Link *link;
if ((link = listbase->last)) {
if ((link = static_cast<Link *>(listbase->last))) {
BLI_remlink(listbase, link);
}
return link;
@ -238,9 +238,9 @@ void *BLI_poptail(ListBase *listbase)
void BLI_freelinkN(ListBase *listbase, void *vlink)
{
Link *link = vlink;
Link *link = static_cast<Link *>(vlink);
if (link == NULL) {
if (link == nullptr) {
return;
}
@ -253,7 +253,7 @@ void BLI_freelinkN(ListBase *listbase, void *vlink)
*/
static void listbase_double_from_single(Link *iter, ListBase *listbase)
{
Link *prev = NULL;
Link *prev = nullptr;
listbase->first = iter;
do {
iter->prev = prev;
@ -281,7 +281,7 @@ static void listbase_double_from_single(Link *iter, ListBase *listbase)
void BLI_listbase_sort(ListBase *listbase, int (*cmp)(const void *, const void *))
{
if (listbase->first != listbase->last) {
Link *head = listbase->first;
Link *head = static_cast<Link *>(listbase->first);
head = listbase_sort_fn(head, cmp);
listbase_double_from_single(head, listbase);
}
@ -292,7 +292,7 @@ void BLI_listbase_sort_r(ListBase *listbase,
void *thunk)
{
if (listbase->first != listbase->last) {
Link *head = listbase->first;
Link *head = static_cast<Link *>(listbase->first);
head = listbase_sort_fn_r(head, cmp, thunk);
listbase_double_from_single(head, listbase);
}
@ -300,25 +300,25 @@ void BLI_listbase_sort_r(ListBase *listbase,
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
{
Link *prevlink = vprevlink;
Link *newlink = vnewlink;
Link *prevlink = static_cast<Link *>(vprevlink);
Link *newlink = static_cast<Link *>(vnewlink);
/* newlink before nextlink */
if (newlink == NULL) {
if (newlink == nullptr) {
return;
}
/* empty list */
if (listbase->first == NULL) {
if (listbase->first == nullptr) {
listbase->first = newlink;
listbase->last = newlink;
return;
}
/* insert at head of list */
if (prevlink == NULL) {
newlink->prev = NULL;
newlink->next = listbase->first;
if (prevlink == nullptr) {
newlink->prev = nullptr;
newlink->next = static_cast<Link *>(listbase->first);
newlink->next->prev = newlink;
listbase->first = newlink;
return;
@ -339,25 +339,25 @@ void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
{
Link *nextlink = vnextlink;
Link *newlink = vnewlink;
Link *nextlink = static_cast<Link *>(vnextlink);
Link *newlink = static_cast<Link *>(vnewlink);
/* newlink before nextlink */
if (newlink == NULL) {
if (newlink == nullptr) {
return;
}
/* empty list */
if (listbase->first == NULL) {
if (listbase->first == nullptr) {
listbase->first = newlink;
listbase->last = newlink;
return;
}
/* insert at end of list */
if (nextlink == NULL) {
newlink->prev = listbase->last;
newlink->next = NULL;
if (nextlink == nullptr) {
newlink->prev = static_cast<Link *>(listbase->last);
newlink->next = nullptr;
((Link *)listbase->last)->next = newlink;
listbase->last = newlink;
return;
@ -378,14 +378,14 @@ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink)
{
Link *l_old = vreplacelink;
Link *l_new = vnewlink;
Link *l_old = static_cast<Link *>(vreplacelink);
Link *l_new = static_cast<Link *>(vnewlink);
/* update adjacent links */
if (l_old->next != NULL) {
if (l_old->next != nullptr) {
l_old->next->prev = l_new;
}
if (l_old->prev != NULL) {
if (l_old->prev != nullptr) {
l_old->prev->next = l_new;
}
@ -404,7 +404,7 @@ void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlin
bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step)
{
Link *link = vlink;
Link *link = static_cast<Link *>(vlink);
Link *hook = link;
const bool is_up = step < 0;
@ -453,7 +453,7 @@ void BLI_freelist(ListBase *listbase)
{
Link *link, *next;
link = listbase->first;
link = static_cast<Link *>(listbase->first);
while (link) {
next = link->next;
free(link);
@ -467,7 +467,7 @@ void BLI_freelistN(ListBase *listbase)
{
Link *link, *next;
link = listbase->first;
link = static_cast<Link *>(listbase->first);
while (link) {
next = link->next;
MEM_freeN(link);
@ -482,7 +482,8 @@ int BLI_listbase_count_at_most(const ListBase *listbase, const int count_max)
Link *link;
int count = 0;
for (link = listbase->first; link && count != count_max; link = link->next) {
for (link = static_cast<Link *>(listbase->first); link && count != count_max;
link = link->next) {
count++;
}
@ -494,7 +495,7 @@ int BLI_listbase_count(const ListBase *listbase)
Link *link;
int count = 0;
for (link = listbase->first; link; link = link->next) {
for (link = static_cast<Link *>(listbase->first); link; link = link->next) {
count++;
}
@ -503,11 +504,11 @@ int BLI_listbase_count(const ListBase *listbase)
void *BLI_findlink(const ListBase *listbase, int number)
{
Link *link = NULL;
Link *link = nullptr;
if (number >= 0) {
link = listbase->first;
while (link != NULL && number != 0) {
link = static_cast<Link *>(listbase->first);
while (link != nullptr && number != 0) {
number--;
link = link->next;
}
@ -518,11 +519,11 @@ void *BLI_findlink(const ListBase *listbase, int number)
void *BLI_rfindlink(const ListBase *listbase, int number)
{
Link *link = NULL;
Link *link = nullptr;
if (number >= 0) {
link = listbase->last;
while (link != NULL && number != 0) {
link = static_cast<Link *>(listbase->last);
while (link != nullptr && number != 0) {
number--;
link = link->prev;
}
@ -533,11 +534,11 @@ void *BLI_rfindlink(const ListBase *listbase, int number)
void *BLI_findlinkfrom(Link *start, int number)
{
Link *link = NULL;
Link *link = nullptr;
if (number >= 0) {
link = start;
while (link != NULL && number != 0) {
while (link != nullptr && number != 0) {
number--;
link = link->next;
}
@ -548,14 +549,14 @@ void *BLI_findlinkfrom(Link *start, int number)
int BLI_findindex(const ListBase *listbase, const void *vlink)
{
Link *link = NULL;
Link *link = nullptr;
int number = 0;
if (vlink == NULL) {
if (vlink == nullptr) {
return -1;
}
link = listbase->first;
link = static_cast<Link *>(listbase->first);
while (link) {
if (link == vlink) {
return number;
@ -570,14 +571,14 @@ int BLI_findindex(const ListBase *listbase, const void *vlink)
void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;
Link *link = nullptr;
const char *id_iter;
if (id == NULL) {
return NULL;
if (id == nullptr) {
return nullptr;
}
for (link = listbase->first; link; link = link->next) {
for (link = static_cast<Link *>(listbase->first); link; link = link->next) {
id_iter = ((const char *)link) + offset;
if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
@ -585,16 +586,16 @@ void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
}
}
return NULL;
return nullptr;
}
void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset)
{
/* Same as #BLI_findstring but find reverse. */
Link *link = NULL;
Link *link = nullptr;
const char *id_iter;
for (link = listbase->last; link; link = link->prev) {
for (link = static_cast<Link *>(listbase->last); link; link = link->prev) {
id_iter = ((const char *)link) + offset;
if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
@ -602,15 +603,15 @@ void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset
}
}
return NULL;
return nullptr;
}
void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;
Link *link = nullptr;
const char *id_iter;
for (link = listbase->first; link; link = link->next) {
for (link = static_cast<Link *>(listbase->first); link; link = link->next) {
/* exact copy of BLI_findstring(), except for this line */
id_iter = *((const char **)(((const char *)link) + offset));
@ -619,16 +620,16 @@ void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int off
}
}
return NULL;
return nullptr;
}
void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int offset)
{
/* Same as #BLI_findstring_ptr but find reverse. */
Link *link = NULL;
Link *link = nullptr;
const char *id_iter;
for (link = listbase->last; link; link = link->prev) {
for (link = static_cast<Link *>(listbase->last); link; link = link->prev) {
/* exact copy of BLI_rfindstring(), except for this line */
id_iter = *((const char **)(((const char *)link) + offset));
@ -637,15 +638,15 @@ void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int of
}
}
return NULL;
return nullptr;
}
void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset)
{
Link *link = NULL;
Link *link = nullptr;
const void *ptr_iter;
for (link = listbase->first; link; link = link->next) {
for (link = static_cast<Link *>(listbase->first); link; link = link->next) {
/* exact copy of BLI_findstring(), except for this line */
ptr_iter = *((const void **)(((const char *)link) + offset));
@ -654,16 +655,16 @@ void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset)
}
}
return NULL;
return nullptr;
}
void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
{
/* Same as #BLI_findptr but find reverse. */
Link *link = NULL;
Link *link = nullptr;
const void *ptr_iter;
for (link = listbase->last; link; link = link->prev) {
for (link = static_cast<Link *>(listbase->last); link; link = link->prev) {
/* exact copy of BLI_rfindstring(), except for this line */
ptr_iter = *((const void **)(((const char *)link) + offset));
@ -672,7 +673,7 @@ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
}
}
return NULL;
return nullptr;
}
void *BLI_listbase_bytes_find(const ListBase *listbase,
@ -680,10 +681,10 @@ void *BLI_listbase_bytes_find(const ListBase *listbase,
const size_t bytes_size,
const int offset)
{
Link *link = NULL;
Link *link = nullptr;
const void *ptr_iter;
for (link = listbase->first; link; link = link->next) {
for (link = static_cast<Link *>(listbase->first); link; link = link->next) {
ptr_iter = (const void *)(((const char *)link) + offset);
if (memcmp(bytes, ptr_iter, bytes_size) == 0) {
@ -691,7 +692,7 @@ void *BLI_listbase_bytes_find(const ListBase *listbase,
}
}
return NULL;
return nullptr;
}
void *BLI_listbase_bytes_rfind(const ListBase *listbase,
const void *bytes,
@ -700,10 +701,10 @@ void *BLI_listbase_bytes_rfind(const ListBase *listbase,
{
/* Same as #BLI_listbase_bytes_find but find reverse. */
Link *link = NULL;
Link *link = nullptr;
const void *ptr_iter;
for (link = listbase->last; link; link = link->prev) {
for (link = static_cast<Link *>(listbase->last); link; link = link->prev) {
ptr_iter = (const void *)(((const char *)link) + offset);
if (memcmp(bytes, ptr_iter, bytes_size) == 0) {
@ -711,7 +712,7 @@ void *BLI_listbase_bytes_rfind(const ListBase *listbase,
}
}
return NULL;
return nullptr;
}
void *BLI_listbase_string_or_index_find(const ListBase *listbase,
@ -719,12 +720,13 @@ void *BLI_listbase_string_or_index_find(const ListBase *listbase,
const size_t string_offset,
const int index)
{
Link *link = NULL;
Link *link_at_index = NULL;
Link *link = nullptr;
Link *link_at_index = nullptr;
int index_iter;
for (link = listbase->first, index_iter = 0; link; link = link->next, index_iter++) {
if (string != NULL && string[0] != '\0') {
for (link = static_cast<Link *>(listbase->first), index_iter = 0; link;
link = link->next, index_iter++) {
if (string != nullptr && string[0] != '\0') {
const char *string_iter = ((const char *)link) + string_offset;
if (string[0] == string_iter[0] && STREQ(string, string_iter)) {
@ -740,11 +742,11 @@ void *BLI_listbase_string_or_index_find(const ListBase *listbase,
int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;
Link *link = nullptr;
const char *id_iter;
int i = 0;
link = listbase->first;
link = static_cast<Link *>(listbase->first);
while (link) {
id_iter = ((const char *)link) + offset;
@ -761,17 +763,17 @@ int BLI_findstringindex(const ListBase *listbase, const char *id, const int offs
ListBase BLI_listbase_from_link(Link *some_link)
{
ListBase list = {some_link, some_link};
if (some_link == NULL) {
if (some_link == nullptr) {
return list;
}
/* Find the first element. */
while (((Link *)list.first)->prev != NULL) {
while (((Link *)list.first)->prev != nullptr) {
list.first = ((Link *)list.first)->prev;
}
/* Find the last element. */
while (((Link *)list.last)->next != NULL) {
while (((Link *)list.last)->next != nullptr) {
list.last = ((Link *)list.last)->next;
}
@ -783,11 +785,11 @@ void BLI_duplicatelist(ListBase *dst, const ListBase *src)
struct Link *dst_link, *src_link;
/* in this order, to ensure it works if dst == src */
src_link = src->first;
dst->first = dst->last = NULL;
src_link = static_cast<Link *>(src->first);
dst->first = dst->last = nullptr;
while (src_link) {
dst_link = MEM_dupallocN(src_link);
dst_link = static_cast<Link *>(MEM_dupallocN(src_link));
BLI_addtail(dst, dst_link);
src_link = src_link->next;
@ -796,9 +798,9 @@ void BLI_duplicatelist(ListBase *dst, const ListBase *src)
void BLI_listbase_reverse(ListBase *lb)
{
struct Link *curr = lb->first;
struct Link *prev = NULL;
struct Link *next = NULL;
struct Link *curr = static_cast<Link *>(lb->first);
struct Link *prev = nullptr;
struct Link *next = nullptr;
while (curr) {
next = curr->next;
curr->next = prev;
@ -808,7 +810,7 @@ void BLI_listbase_reverse(ListBase *lb)
}
/* swap first/last */
curr = lb->first;
curr = static_cast<Link *>(lb->first);
lb->first = lb->last;
lb->last = curr;
}
@ -816,39 +818,39 @@ void BLI_listbase_reverse(ListBase *lb)
void BLI_listbase_rotate_first(ListBase *lb, void *vlink)
{
/* make circular */
((Link *)lb->first)->prev = lb->last;
((Link *)lb->last)->next = lb->first;
((Link *)lb->first)->prev = static_cast<Link *>(lb->last);
((Link *)lb->last)->next = static_cast<Link *>(lb->first);
lb->first = vlink;
lb->last = ((Link *)vlink)->prev;
((Link *)lb->first)->prev = NULL;
((Link *)lb->last)->next = NULL;
((Link *)lb->first)->prev = nullptr;
((Link *)lb->last)->next = nullptr;
}
void BLI_listbase_rotate_last(ListBase *lb, void *vlink)
{
/* make circular */
((Link *)lb->first)->prev = lb->last;
((Link *)lb->last)->next = lb->first;
((Link *)lb->first)->prev = static_cast<Link *>(lb->last);
((Link *)lb->last)->next = static_cast<Link *>(lb->first);
lb->first = ((Link *)vlink)->next;
lb->last = vlink;
((Link *)lb->first)->prev = NULL;
((Link *)lb->last)->next = NULL;
((Link *)lb->first)->prev = nullptr;
((Link *)lb->last)->next = nullptr;
}
LinkData *BLI_genericNodeN(void *data)
{
LinkData *ld;
if (data == NULL) {
return NULL;
if (data == nullptr) {
return nullptr;
}
/* create new link, and make it hold the given data */
ld = MEM_callocN(sizeof(LinkData), __func__);
ld = MEM_cnew<LinkData>(__func__);
ld->data = data;
return ld;

View File

@ -823,6 +823,99 @@ static void version_geometry_nodes_replace_transfer_attribute_node(bNodeTree *nt
}
}
/**
* The mesh primitive nodes created a uv map with a hardcoded name. Now they are outputting the uv
* map as a socket instead. The versioning just inserts a Store Named Attribute node after
* primitive nodes.
*/
static void version_geometry_nodes_primitive_uv_maps(bNodeTree &ntree)
{
blender::Vector<bNode *> new_nodes;
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree.nodes) {
if (!ELEM(node->type,
GEO_NODE_MESH_PRIMITIVE_CONE,
GEO_NODE_MESH_PRIMITIVE_CUBE,
GEO_NODE_MESH_PRIMITIVE_CYLINDER,
GEO_NODE_MESH_PRIMITIVE_GRID,
GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE,
GEO_NODE_MESH_PRIMITIVE_UV_SPHERE)) {
continue;
}
bNodeSocket *primitive_output_socket = nullptr;
bNodeSocket *uv_map_output_socket = nullptr;
LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
if (STREQ(socket->name, "UV Map")) {
uv_map_output_socket = socket;
}
if (socket->type == SOCK_GEOMETRY) {
primitive_output_socket = socket;
}
}
if (uv_map_output_socket != nullptr) {
continue;
}
uv_map_output_socket = nodeAddStaticSocket(
&ntree, node, SOCK_OUT, SOCK_VECTOR, PROP_NONE, "UV Map", "UV Map");
bNode *store_attribute_node = nodeAddStaticNode(
nullptr, &ntree, GEO_NODE_STORE_NAMED_ATTRIBUTE);
new_nodes.append(store_attribute_node);
store_attribute_node->parent = node->parent;
store_attribute_node->locx = node->locx + 25;
store_attribute_node->locy = node->locy;
store_attribute_node->offsetx = node->offsetx;
store_attribute_node->offsety = node->offsety;
NodeGeometryStoreNamedAttribute &storage = *static_cast<NodeGeometryStoreNamedAttribute *>(
store_attribute_node->storage);
storage.domain = ATTR_DOMAIN_CORNER;
/* Intentionally use 3D instead of 2D vectors, because 2D vectors did not exist in older
* releases and would make the file crash when trying to open it. */
storage.data_type = CD_PROP_FLOAT3;
bNodeSocket *store_attribute_geometry_input = static_cast<bNodeSocket *>(
store_attribute_node->inputs.first);
bNodeSocket *store_attribute_name_input = store_attribute_geometry_input->next;
bNodeSocket *store_attribute_value_input = nullptr;
LISTBASE_FOREACH (bNodeSocket *, socket, &store_attribute_node->inputs) {
if (socket->type == SOCK_VECTOR) {
store_attribute_value_input = socket;
break;
}
}
bNodeSocket *store_attribute_geometry_output = static_cast<bNodeSocket *>(
store_attribute_node->outputs.first);
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
if (link->fromsock == primitive_output_socket) {
link->fromnode = store_attribute_node;
link->fromsock = store_attribute_geometry_output;
}
}
bNodeSocketValueString *name_value = static_cast<bNodeSocketValueString *>(
store_attribute_name_input->default_value);
const char *uv_map_name = node->type == GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE ? "UVMap" :
"uv_map";
BLI_strncpy(name_value->value, uv_map_name, sizeof(name_value->value));
nodeAddLink(&ntree,
node,
primitive_output_socket,
store_attribute_node,
store_attribute_geometry_input);
nodeAddLink(
&ntree, node, uv_map_output_socket, store_attribute_node, store_attribute_value_input);
}
/* Move nodes to the front so that they are drawn behind existing nodes. */
for (bNode *node : new_nodes) {
BLI_remlink(&ntree.nodes, node);
BLI_addhead(&ntree.nodes, node);
}
if (!new_nodes.is_empty()) {
nodeRebuildIDVector(&ntree);
}
}
void do_versions_after_linking_300(Main *bmain, ReportList * /*reports*/)
{
if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
@ -3708,18 +3801,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
if (!MAIN_VERSION_ATLEAST(bmain, 305, 4)) {
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type == NTREE_GEOMETRY) {
version_node_socket_name(ntree, GEO_NODE_COLLECTION_INFO, "Geometry", "Instances");
@ -3732,5 +3814,24 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
image->seam_margin = 8;
}
}
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type == NTREE_GEOMETRY) {
version_geometry_nodes_primitive_uv_maps(*ntree);
}
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
}
}

View File

@ -86,12 +86,14 @@ struct GPUBatch *DRW_pbvh_tris_get(PBVHBatches *batches,
struct PBVHAttrReq *attrs,
int attrs_num,
PBVH_GPU_Args *args,
int *r_prim_count);
int *r_prim_count,
bool do_coarse_grids);
struct GPUBatch *DRW_pbvh_lines_get(struct PBVHBatches *batches,
struct PBVHAttrReq *attrs,
int attrs_num,
PBVH_GPU_Args *args,
int *r_prim_count);
int *r_prim_count,
bool do_coarse_grids);
#ifdef __cplusplus
}

View File

@ -1552,7 +1552,8 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob)
const bool is_select_mode = DRW_state_is_select();
const bool is_paint_mode = (draw_ctx->object_mode &
(OB_MODE_ALL_PAINT | OB_MODE_ALL_PAINT_GPENCIL)) != 0;
(OB_MODE_ALL_PAINT | OB_MODE_ALL_PAINT_GPENCIL |
OB_MODE_SCULPT_CURVES)) != 0;
const bool from_dupli = (ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) != 0;
const bool has_bounds = !ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_EMPTY, OB_SPEAKER, OB_LIGHTPROBE);
const bool has_texspace = has_bounds &&

View File

@ -97,11 +97,13 @@ BLI_INLINE void workbench_material_get_image(
case SH_NODE_TEX_IMAGE: {
const NodeTexImage *storage = static_cast<NodeTexImage *>(node->storage);
const bool use_filter = (storage->interpolation != SHD_INTERP_CLOSEST);
const bool use_repeat = (storage->extension == SHD_IMAGE_EXTENSION_REPEAT);
const bool use_mirror = (storage->extension == SHD_IMAGE_EXTENSION_MIRROR);
const bool use_repeat = use_mirror || (storage->extension == SHD_IMAGE_EXTENSION_REPEAT);
const bool use_clip = (storage->extension == SHD_IMAGE_EXTENSION_CLIP);
SET_FLAG_FROM_TEST(*r_sampler, use_filter, GPU_SAMPLER_FILTER);
SET_FLAG_FROM_TEST(*r_sampler, use_repeat, GPU_SAMPLER_REPEAT);
SET_FLAG_FROM_TEST(*r_sampler, use_clip, GPU_SAMPLER_CLAMP_BORDER);
SET_FLAG_FROM_TEST(*r_sampler, use_mirror, GPU_SAMPLER_MIRROR_REPEAT);
break;
}
case SH_NODE_TEX_ENVIRONMENT: {

View File

@ -1220,10 +1220,12 @@ static void sculpt_draw_cb(DRWSculptCallbackData *scd,
GPUBatch *geom;
if (!scd->use_wire) {
geom = DRW_pbvh_tris_get(batches, scd->attrs, scd->attrs_num, pbvh_draw_args, &primcount);
geom = DRW_pbvh_tris_get(
batches, scd->attrs, scd->attrs_num, pbvh_draw_args, &primcount, scd->fast_mode);
}
else {
geom = DRW_pbvh_lines_get(batches, scd->attrs, scd->attrs_num, pbvh_draw_args, &primcount);
geom = DRW_pbvh_lines_get(
batches, scd->attrs, scd->attrs_num, pbvh_draw_args, &primcount, scd->fast_mode);
}
short index = 0;

View File

@ -66,6 +66,22 @@ using blender::Vector;
using string = std::string;
static bool valid_pbvh_attr(int type)
{
switch (type) {
case CD_PBVH_CO_TYPE:
case CD_PBVH_NO_TYPE:
case CD_PBVH_FSET_TYPE:
case CD_PBVH_MASK_TYPE:
case CD_PROP_COLOR:
case CD_PROP_BYTE_COLOR:
case CD_MLOOPUV:
return true;
}
return false;
}
struct PBVHVbo {
uint64_t type;
eAttrDomain domain;
@ -99,6 +115,8 @@ struct PBVHBatch {
string key;
GPUBatch *tris = nullptr, *lines = nullptr;
int tris_count = 0, lines_count = 0;
bool is_coarse =
false; /* Coarse multires, will use full-sized VBOs only index buffer changes. */
void sort_vbos(Vector<PBVHVbo> &master_vbos)
{
@ -122,6 +140,10 @@ struct PBVHBatch {
{
key = "";
if (is_coarse) {
key += "c:";
}
sort_vbos(master_vbos);
for (int vbo_i : vbos) {
@ -157,6 +179,12 @@ struct PBVHBatches {
int material_index = 0;
/* Stuff for displaying coarse multires grids. */
GPUIndexBuf *tri_index_coarse = nullptr;
GPUIndexBuf *lines_index_coarse = nullptr;
int coarse_level = 0; /* Coarse multires depth. */
int tris_count_coarse = 0, lines_count_coarse = 0;
int count_faces(PBVH_GPU_Args *args)
{
int count = 0;
@ -178,6 +206,7 @@ struct PBVHBatches {
count = BKE_pbvh_count_grid_quads((BLI_bitmap **)args->grid_hidden,
args->grid_indices,
args->totprim,
args->ccg_key.grid_size,
args->ccg_key.grid_size);
break;
@ -217,9 +246,11 @@ struct PBVHBatches {
GPU_INDEXBUF_DISCARD_SAFE(tri_index);
GPU_INDEXBUF_DISCARD_SAFE(lines_index);
GPU_INDEXBUF_DISCARD_SAFE(tri_index_coarse);
GPU_INDEXBUF_DISCARD_SAFE(lines_index_coarse);
}
string build_key(PBVHAttrReq *attrs, int attrs_num)
string build_key(PBVHAttrReq *attrs, int attrs_num, bool do_coarse_grids)
{
string key;
PBVHBatch batch;
@ -228,6 +259,10 @@ struct PBVHBatches {
for (int i : IndexRange(attrs_num)) {
PBVHAttrReq *attr = attrs + i;
if (!valid_pbvh_attr(attr->type)) {
continue;
}
PBVHVbo vbo(attr->domain, attr->type, string(attr->name));
vbo.build_key();
@ -235,6 +270,7 @@ struct PBVHBatches {
batch.vbos.append(i);
}
batch.is_coarse = do_coarse_grids;
batch.build_key(vbos);
return batch.key;
}
@ -272,18 +308,21 @@ struct PBVHBatches {
return nullptr;
}
bool has_batch(PBVHAttrReq *attrs, int attrs_num)
bool has_batch(PBVHAttrReq *attrs, int attrs_num, bool do_coarse_grids)
{
return batches.contains(build_key(attrs, attrs_num));
return batches.contains(build_key(attrs, attrs_num, do_coarse_grids));
}
PBVHBatch &ensure_batch(PBVHAttrReq *attrs, int attrs_num, PBVH_GPU_Args *args)
PBVHBatch &ensure_batch(PBVHAttrReq *attrs,
int attrs_num,
PBVH_GPU_Args *args,
bool do_coarse_grids)
{
if (!has_batch(attrs, attrs_num)) {
create_batch(attrs, attrs_num, args);
if (!has_batch(attrs, attrs_num, do_coarse_grids)) {
create_batch(attrs, attrs_num, args, do_coarse_grids);
}
return batches.lookup(build_key(attrs, attrs_num));
return batches.lookup(build_key(attrs, attrs_num, do_coarse_grids));
}
void fill_vbo_normal_faces(
@ -484,9 +523,12 @@ struct PBVHBatches {
for (int x = 0; x < gridsize; x++) {
CCGElem *elems[4] = {
CCG_grid_elem(&args->ccg_key, grid, x, y),
CCG_grid_elem(&args->ccg_key, grid, x + 1, y),
CCG_grid_elem(&args->ccg_key, grid, x + 1, y + 1),
CCG_grid_elem(&args->ccg_key, grid, x, y + 1),
CCG_grid_elem(&args->ccg_key, grid, min_ii(x + 1, gridsize - 1), y),
CCG_grid_elem(&args->ccg_key,
grid,
min_ii(x + 1, gridsize - 1),
min_ii(y + 1, gridsize - 1)),
CCG_grid_elem(&args->ccg_key, grid, x, min_ii(y + 1, gridsize - 1)),
};
func(x, y, grid_index, elems, 0);
@ -858,10 +900,10 @@ struct PBVHBatches {
break;
}
default:
BLI_assert(0);
printf("%s: error\n", __func__);
printf("%s: Unsupported attribute type %u\n", __func__, type);
BLI_assert_unreachable();
break;
return;
}
if (need_aliases) {
@ -944,8 +986,10 @@ struct PBVHBatches {
GPU_INDEXBUF_DISCARD_SAFE(tri_index);
GPU_INDEXBUF_DISCARD_SAFE(lines_index);
GPU_INDEXBUF_DISCARD_SAFE(tri_index_coarse);
GPU_INDEXBUF_DISCARD_SAFE(lines_index_coarse);
tri_index = lines_index = nullptr;
tri_index = lines_index = tri_index_coarse = lines_index_coarse = nullptr;
faces_count = tris_count = count;
}
}
@ -1041,7 +1085,7 @@ struct PBVHBatches {
lines_index = GPU_indexbuf_build(&elb_lines);
}
void create_index_grids(PBVH_GPU_Args *args)
void create_index_grids(PBVH_GPU_Args *args, bool do_coarse)
{
int *mat_index = static_cast<int *>(
CustomData_get_layer_named(args->pdata, CD_PROP_INT32, "material_index"));
@ -1053,15 +1097,24 @@ struct PBVHBatches {
needs_tri_index = true;
int gridsize = args->ccg_key.grid_size;
int display_gridsize = gridsize;
int totgrid = args->totprim;
int skip = 1;
const int display_level = do_coarse ? coarse_level : args->ccg_key.level;
if (display_level < args->ccg_key.level) {
display_gridsize = (1 << display_level) + 1;
skip = 1 << (args->ccg_key.level - display_level - 1);
}
for (int i : IndexRange(args->totprim)) {
int grid_index = args->grid_indices[i];
bool smooth = args->grid_flag_mats[grid_index].flag & ME_SMOOTH;
BLI_bitmap *gh = args->grid_hidden[grid_index];
for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) {
for (int y = 0; y < gridsize - 1; y += skip) {
for (int x = 0; x < gridsize - 1; x += skip) {
if (gh && paint_is_grid_face_hidden(gh, gridsize, x, y)) {
/* Skip hidden faces by just setting smooth to true. */
smooth = true;
@ -1082,12 +1135,17 @@ struct PBVHBatches {
CCGKey *key = &args->ccg_key;
uint visible_quad_len = BKE_pbvh_count_grid_quads(
(BLI_bitmap **)args->grid_hidden, args->grid_indices, totgrid, key->grid_size);
uint visible_quad_len = BKE_pbvh_count_grid_quads((BLI_bitmap **)args->grid_hidden,
args->grid_indices,
totgrid,
key->grid_size,
display_gridsize);
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * visible_quad_len, INT_MAX);
GPU_indexbuf_init(
&elb_lines, GPU_PRIM_LINES, 2 * totgrid * gridsize * (gridsize - 1), INT_MAX);
GPU_indexbuf_init(&elb_lines,
GPU_PRIM_LINES,
2 * totgrid * display_gridsize * (display_gridsize - 1),
INT_MAX);
if (needs_tri_index) {
uint offset = 0;
@ -1098,17 +1156,17 @@ struct PBVHBatches {
BLI_bitmap *gh = args->grid_hidden[args->grid_indices[i]];
for (int j = 0; j < gridsize - 1; j++) {
for (int k = 0; k < gridsize - 1; k++) {
for (int j = 0; j < gridsize - skip; j += skip) {
for (int k = 0; k < gridsize - skip; k += skip) {
/* Skip hidden grid face */
if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) {
continue;
}
/* Indices in a Clockwise QUAD disposition. */
v0 = offset + j * gridsize + k;
v1 = v0 + 1;
v2 = v1 + gridsize;
v3 = v2 - 1;
v1 = offset + j * gridsize + k + skip;
v2 = offset + (j + skip) * gridsize + k + skip;
v3 = offset + (j + skip) * gridsize + k;
GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1);
GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2);
@ -1116,7 +1174,7 @@ struct PBVHBatches {
GPU_indexbuf_add_line_verts(&elb_lines, v0, v1);
GPU_indexbuf_add_line_verts(&elb_lines, v0, v3);
if (j + 2 == gridsize) {
if (j / skip + 2 == display_gridsize) {
GPU_indexbuf_add_line_verts(&elb_lines, v2, v3);
}
grid_visible = true;
@ -1131,22 +1189,38 @@ struct PBVHBatches {
else {
uint offset = 0;
const uint grid_vert_len = square_uint(gridsize - 1) * 4;
for (int i = 0; i < totgrid; i++, offset += grid_vert_len) {
bool grid_visible = false;
BLI_bitmap *gh = args->grid_hidden[args->grid_indices[i]];
uint v0, v1, v2, v3;
for (int j = 0; j < gridsize - 1; j++) {
for (int k = 0; k < gridsize - 1; k++) {
for (int j = 0; j < gridsize - skip; j += skip) {
for (int k = 0; k < gridsize - skip; k += skip) {
/* Skip hidden grid face */
if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) {
continue;
}
/* VBO data are in a Clockwise QUAD disposition. */
v0 = offset + (j * (gridsize - 1) + k) * 4;
v1 = v0 + 1;
v2 = v0 + 2;
v3 = v0 + 3;
v0 = (j * (gridsize - 1) + k) * 4;
if (skip > 1) {
v1 = (j * (gridsize - 1) + k + skip - 1) * 4;
v2 = ((j + skip - 1) * (gridsize - 1) + k + skip - 1) * 4;
v3 = ((j + skip - 1) * (gridsize - 1) + k) * 4;
}
else {
v1 = v2 = v3 = v0;
}
/* VBO data are in a Clockwise QUAD disposition. Note
* that vertices might be in different quads if we're
* building a coarse index buffer.
*/
v0 += offset;
v1 += offset + 1;
v2 += offset + 2;
v3 += offset + 3;
GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1);
GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2);
@ -1154,7 +1228,7 @@ struct PBVHBatches {
GPU_indexbuf_add_line_verts(&elb_lines, v0, v1);
GPU_indexbuf_add_line_verts(&elb_lines, v0, v3);
if (j + 2 == gridsize) {
if ((j / skip) + 2 == display_gridsize) {
GPU_indexbuf_add_line_verts(&elb_lines, v2, v3);
}
grid_visible = true;
@ -1167,8 +1241,16 @@ struct PBVHBatches {
}
}
tri_index = GPU_indexbuf_build(&elb);
lines_index = GPU_indexbuf_build(&elb_lines);
if (do_coarse) {
tri_index_coarse = GPU_indexbuf_build(&elb);
lines_index_coarse = GPU_indexbuf_build(&elb_lines);
tris_count_coarse = visible_quad_len;
lines_count_coarse = totgrid * display_gridsize * (display_gridsize - 1);
}
else {
tri_index = GPU_indexbuf_build(&elb);
lines_index = GPU_indexbuf_build(&elb_lines);
}
}
void create_index(PBVH_GPU_Args *args)
@ -1181,7 +1263,12 @@ struct PBVHBatches {
create_index_bmesh(args);
break;
case PBVH_GRIDS:
create_index_grids(args);
create_index_grids(args, false);
if (args->ccg_key.level > coarse_level) {
create_index_grids(args, true);
}
break;
}
@ -1207,7 +1294,7 @@ struct PBVHBatches {
}
}
void create_batch(PBVHAttrReq *attrs, int attrs_num, PBVH_GPU_Args *args)
void create_batch(PBVHAttrReq *attrs, int attrs_num, PBVH_GPU_Args *args, bool do_coarse_grids)
{
check_index_buffers(args);
@ -1216,17 +1303,23 @@ struct PBVHBatches {
batch.tris = GPU_batch_create(GPU_PRIM_TRIS,
nullptr,
/* can be nullptr if buffer is empty */
tri_index);
batch.tris_count = tris_count;
do_coarse_grids ? tri_index_coarse : tri_index);
batch.tris_count = do_coarse_grids ? tris_count_coarse : tris_count;
batch.is_coarse = do_coarse_grids;
if (lines_index) {
batch.lines = GPU_batch_create(GPU_PRIM_LINES, nullptr, lines_index);
batch.lines_count = lines_count;
batch.lines = GPU_batch_create(
GPU_PRIM_LINES, nullptr, do_coarse_grids ? lines_index_coarse : lines_index);
batch.lines_count = do_coarse_grids ? lines_count_coarse : lines_count;
}
for (int i : IndexRange(attrs_num)) {
PBVHAttrReq *attr = attrs + i;
if (!valid_pbvh_attr(attr->type)) {
continue;
}
if (!has_vbo(attr->domain, int(attr->type), attr->name)) {
create_vbo(attr->domain, uint32_t(attr->type), attr->name, args);
}
@ -1272,9 +1365,12 @@ GPUBatch *DRW_pbvh_tris_get(PBVHBatches *batches,
PBVHAttrReq *attrs,
int attrs_num,
PBVH_GPU_Args *args,
int *r_prim_count)
int *r_prim_count,
bool do_coarse_grids)
{
PBVHBatch &batch = batches->ensure_batch(attrs, attrs_num, args);
do_coarse_grids &= args->pbvh_type == PBVH_GRIDS;
PBVHBatch &batch = batches->ensure_batch(attrs, attrs_num, args, do_coarse_grids);
*r_prim_count = batch.tris_count;
@ -1285,9 +1381,12 @@ GPUBatch *DRW_pbvh_lines_get(PBVHBatches *batches,
PBVHAttrReq *attrs,
int attrs_num,
PBVH_GPU_Args *args,
int *r_prim_count)
int *r_prim_count,
bool do_coarse_grids)
{
PBVHBatch &batch = batches->ensure_batch(attrs, attrs_num, args);
do_coarse_grids &= args->pbvh_type == PBVH_GRIDS;
PBVHBatch &batch = batches->ensure_batch(attrs, attrs_num, args, do_coarse_grids);
*r_prim_count = batch.lines_count;

View File

@ -59,7 +59,7 @@ static bool is_cursor_visible(const DRWContextState *draw_ctx, Scene *scene, Vie
}
/* don't draw cursor in paint modes, but with a few exceptions */
if (draw_ctx->object_mode & OB_MODE_ALL_PAINT) {
if ((draw_ctx->object_mode & (OB_MODE_ALL_PAINT | OB_MODE_SCULPT_CURVES)) != 0) {
/* exception: object is in weight paint and has deforming armature in pose mode */
if (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) {
if (BKE_object_pose_armature_get(draw_ctx->obact) != NULL) {

View File

@ -6,7 +6,6 @@
#include <string>
#include "AS_asset_identifier.hh"
#include "AS_asset_representation.h"
#include "AS_asset_representation.hh"
@ -15,7 +14,6 @@
#include "BLO_readfile.h"
#include "ED_asset_handle.h"
#include "ED_asset_list.hh"
#include "WM_api.h"

View File

@ -26,7 +26,6 @@
#include "BKE_appdir.h"
#include "BKE_asset.h"
#include "BKE_idprop.hh"
#include "BKE_preferences.h"
#include "CLG_log.h"

View File

@ -15,7 +15,6 @@
#include "BKE_context.h"
#include "BLI_map.hh"
#include "BLI_path_util.h"
#include "BLI_utility_mixins.hh"
#include "DNA_space_types.h"
@ -112,6 +111,7 @@ class AssetList : NonCopyable {
void clear(bContext *C);
bool needsRefetch() const;
bool isLoaded() const;
void iterate(AssetListIterFn fn) const;
bool listen(const wmNotifier &notifier) const;
int size() const;
@ -190,6 +190,11 @@ bool AssetList::needsRefetch() const
return filelist_needs_force_reset(filelist_) || filelist_needs_reading(filelist_);
}
bool AssetList::isLoaded() const
{
return filelist_is_ready(filelist_);
}
void AssetList::iterate(AssetListIterFn fn) const
{
FileList *files = filelist_;
@ -423,7 +428,7 @@ bool ED_assetlist_is_loaded(const AssetLibraryReference *library_reference)
if (list->needsRefetch()) {
return false;
}
return true;
return list->isLoaded();
}
void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference,

View File

@ -9,13 +9,12 @@
#include "BKE_bpath.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_preferences.h"
#include "BKE_report.h"
#include "BLI_fileops.h"
#include "BLI_fileops.h" /* MSVC needs this for `PATH_MAX` */
#include "BLI_fnmatch.h"
#include "BLI_path_util.h"
#include "BLI_set.hh"
@ -37,8 +36,6 @@
#include "DNA_space_types.h"
#include "BLO_writefile.h"
using namespace blender;
/* -------------------------------------------------------------------- */

View File

@ -581,6 +581,12 @@ void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail, c
*/
struct Mesh *ED_mesh_context(struct bContext *C);
/**
* Split all edges that would appear sharp based onface and edge sharpness tags and the auto smooth
* angle.
*/
void ED_mesh_split_faces(struct Mesh *mesh);
/* mesh backup */
typedef struct BMBackup {
struct BMesh *bmcopy;

View File

@ -10,6 +10,7 @@ set(INC
../../bmesh
../../depsgraph
../../draw
../../geometry
../../gpu
../../imbuf
../../makesdna
@ -76,6 +77,17 @@ if(WITH_GMP)
add_definitions(-DWITH_GMP)
endif()
if(WITH_TBB)
add_definitions(-DWITH_TBB)
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
)
list(APPEND LIB
${TBB_LIBRARIES}
)
endif()
blender_add_lib(bf_editor_mesh "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -14,6 +14,7 @@
#include "DNA_view3d_types.h"
#include "BLI_array.hh"
#include "BLI_index_mask_ops.hh"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@ -42,6 +43,8 @@
#include "ED_uvedit.h"
#include "ED_view3d.h"
#include "GEO_mesh_split_edges.hh"
#include "mesh_intern.h" /* own include */
using blender::Array;
@ -1464,3 +1467,43 @@ Mesh *ED_mesh_context(bContext *C)
return (Mesh *)data;
}
void ED_mesh_split_faces(Mesh *mesh)
{
using namespace blender;
Array<MEdge> edges(mesh->edges());
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI);
BKE_edges_sharp_from_angle_set(edges.data(),
edges.size(),
loops.data(),
loops.size(),
polys.data(),
BKE_mesh_poly_normals_ensure(mesh),
polys.size(),
split_angle);
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int poly_i : range) {
const MPoly &poly = polys[poly_i];
if (!(poly.flag & ME_SMOOTH)) {
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
edges[loop.e].flag |= ME_SHARP;
}
}
}
});
Vector<int64_t> split_indices;
const IndexMask split_mask = index_mask_ops::find_indices_based_on_predicate(
edges.index_range(), 4096, split_indices, [&](const int64_t i) {
return edges[i].flag & ME_SHARP;
});
if (split_mask.is_empty()) {
return;
}
geometry::split_edges(*mesh, split_mask);
}

View File

@ -55,6 +55,7 @@
#include "WM_api.h"
#include "WM_types.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
@ -670,7 +671,8 @@ static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph,
Mesh *me = BKE_mesh_new_from_object(depsgraph, object, false, preserve_origindex);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
ED_mesh_split_faces(me);
CustomData_free_layers(&me->ldata, CD_NORMAL, me->totloop);
}
return me;

View File

@ -3531,6 +3531,9 @@ void ED_region_info_draw_multiline(ARegion *region,
/* background box */
rcti rect = *ED_region_visible_rect(region);
/* Needed in case scripts leave the font size at an unexpected value, see: T102213. */
BLF_size(fontid, style->widget.points * U.dpi_fac);
/* Box fill entire width or just around text. */
if (!full_redraw) {
const char **text = &text_array[0];

View File

@ -4812,28 +4812,19 @@ bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
int ED_screen_animation_play(bContext *C, int sync, int mode)
{
bScreen *screen = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
Scene *scene_eval = DEG_get_evaluated_scene(CTX_data_ensure_evaluated_depsgraph(C));
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
/* stop playback now */
ED_screen_animation_timer(C, 0, 0, 0);
Main *bmain = CTX_data_main(C);
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
Depsgraph *graph = BKE_scene_get_depsgraph(scene, view_layer);
if (graph) {
Scene *scene_eval = DEG_get_evaluated_scene(graph);
/* The audio handles are preserved throughout the dependency graph evaluation.
* Checking for scene->playback_handle even for non-evaluated scene should be okay. */
BKE_sound_stop_scene(scene_eval);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
}
}
BKE_sound_stop_scene(scene_eval);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
else {
/* these settings are currently only available from a menu in the TimeLine */
if (mode == 1) { /* XXX only play audio forwards!? */
Scene *scene_eval = DEG_get_evaluated_scene(CTX_data_ensure_evaluated_depsgraph(C));
BKE_sound_play_scene(scene_eval);
}

Some files were not shown because too many files have changed in this diff Show More