Compare commits
19 Commits
eevee-dof-
...
df0bce3f7d
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bb0b250cbd | ||
4402f43b71 | |||
eccc57aa5c | |||
a563775649 | |||
4212ea7b7d | |||
0a546beb1f | |||
7fb540b4cf | |||
760a16b88b | |||
![]() |
bec08621d6 | ||
3f90c11621 | |||
ebd2aa789e | |||
0f238c5bcb | |||
1081eee4c5 | |||
![]() |
7bde2844ae | ||
5eb5a7f4b7 | |||
bbd74e9fd4 | |||
9042532085 | |||
8c7b78672e | |||
![]() |
e54f88f092 |
@@ -10,9 +10,8 @@
|
||||
# Changes that belong here:
|
||||
# - Massive comment, doxy-sections, or spelling corrections.
|
||||
# - Clang-format, PEP8 or other automated changes which are *strictly* "no functional change".
|
||||
# - Several commits should be added to this list at once, because adding
|
||||
# one extra commit (to edit this file) after every cleanup is noisy.
|
||||
# - No clang-tidy changes.
|
||||
# - Several smaller commits should be added to this list at once, because adding
|
||||
# one extra commit (to edit this file) after every small cleanup is noisy.
|
||||
#
|
||||
# Note:
|
||||
# - The comment above the SHA should be the first line of the commit.
|
||||
@@ -93,12 +92,78 @@ c42a6b77b52560d257279de2cb624b4ef2c0d24c
|
||||
# Cleanup: use doxy sections for imbuf
|
||||
c207f7c22e1439e0b285fba5d2c072bdae23f981
|
||||
|
||||
# Cleanup: Clang-Tidy, modernize-use-bool-literals
|
||||
af35ada2f3fa8da4d46b3a71de724d353d716820
|
||||
|
||||
# Cleanup: Use nullptr everywhere in fluid code
|
||||
311031ecd03dbfbf43e1df672a395f24b2e7d4d3
|
||||
|
||||
# Cleanup: Clang-Tidy, modernize-redundant-void-arg
|
||||
a331d5c99299c4514ca33c843b1c79b872f2728d
|
||||
|
||||
# Cleanup: Clang-Tidy modernize-use-nullptr
|
||||
16732def37c5a66f3ea28dbe247b09cc6bca6677
|
||||
|
||||
# Cleanup: Clang-tidy, modernize-concat-nested-namespaces
|
||||
4525049aa0cf818f6483dce589ac9791eb562338
|
||||
|
||||
# Cleanup: Clang-tidy else-after-return
|
||||
ae342ed4511cf2e144dcd27ce2c635d3d536f9ad
|
||||
|
||||
# Cleanup: Clang-Tidy, readability-redundant-member-init
|
||||
190170d4cc92ff34abe1744a10474ac4f1074086
|
||||
|
||||
# Cleanup: use 'filepath' instead of 'name' for ImBuf utilities
|
||||
99f56b4c16323f96c0cbf54e392fb509fcac5bda
|
||||
|
||||
# Cleanup: clang-format
|
||||
c4d8f6a4a8ddc29ed27311ed7578b3c8c31399d2
|
||||
b5d310b569e07a937798a2d38539cfd290149f1c
|
||||
8c846cccd6bdfd3e90a695fabbf05f53e5466a57
|
||||
4eac03d821fa17546f562485f7d073813a5e5943
|
||||
1166110a9d66af9c5a47cee2be591f50fdc445e8
|
||||
|
||||
# Cleanup: clang-format.
|
||||
40d4a4cb1a6b4c3c2a486e8f2868f547530e0811
|
||||
4eac03d821fa17546f562485f7d073813a5e5943
|
||||
|
||||
# Cleanup: use preprocessor version check for PyTypeObject declaration
|
||||
cd9acfed4f7674b84be965d469a367aef96f8af3
|
||||
|
||||
# Cycles: fix compilation of OSL shaders following API change
|
||||
b980cd163a9d5d77eeffc2e353333e739fa9e719
|
||||
|
||||
# Cleanup: clang-tidy suppress warnings for PyTypeObject.tp_print
|
||||
efd71aad4f22ec0073d80b8dd296015d3f395aa8
|
||||
|
||||
# Cleanup: fix wrong merge, remove extra unique_ptr.
|
||||
6507449e54a167c63a72229e4d0119dd2af68ae5
|
||||
|
||||
# Cleanup: fix some clang tidy issues
|
||||
525a042c5c7513c41240b118acca002f6c60cc12
|
||||
|
||||
# Fix T82520: error building freestyle with Python3.8
|
||||
e118426e4695a97d67e65d69677f3c4e2db50a56
|
||||
|
||||
# Cleanup: Clang-tidy, readability-else-after-return
|
||||
7be47dadea5066ae095c644e0b4f1f10d75f5ab3
|
||||
|
||||
# Cleanup: Add `r_` to return parameter
|
||||
45dca05b1cd2a5ead59144c93d790fdfe7c35ee6
|
||||
|
||||
# Cleanup: Typo in `print_default_info` function name.
|
||||
41a73909dec716642f044e60b40a28335c9fdb10
|
||||
|
||||
# Cleanup: Reduce indentation
|
||||
1cc3a0e2cf73a5ff4f9e0a7f5338eda77266b300
|
||||
|
||||
# Build-system: Force C linkage for all DNA type headers
|
||||
ad4b7741dba45a2be210942c18af6b6e4438f129
|
||||
|
||||
# Cleanup: Move function to proper section
|
||||
c126e27cdc8b28365a9d5f9fafc4d521d1eb83df
|
||||
|
||||
# Cleanup: remove break after return statements
|
||||
bbdfeb751e16d939482d2e4b95c4d470f53f18a5
|
||||
|
||||
# Cleanup: clang-tidy
|
||||
af013ff76feef7e8b8ba642279c62a5dc275d59f
|
||||
|
||||
# Cleanup: Make panel type flag names more clear
|
||||
9d28353b525ecfbcca1501be72e4276dfb2bbc2a
|
||||
|
@@ -205,7 +205,6 @@ option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if
|
||||
option(WITH_OPENVDB_3_ABI_COMPATIBLE "Assume OpenVDB library has been compiled with version 3 ABI compatibility" OFF)
|
||||
mark_as_advanced(WITH_OPENVDB_3_ABI_COMPATIBLE)
|
||||
option(WITH_NANOVDB "Enable usage of NanoVDB data structure for rendering on the GPU" ON)
|
||||
option(WITH_HARU "Enable features relying on Libharu (Grease pencil PDF export)" ON)
|
||||
|
||||
# GHOST Windowing Library Options
|
||||
option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF)
|
||||
@@ -731,9 +730,6 @@ set_and_warn_dependency(WITH_OPENVDB WITH_NANOVDB OFF)
|
||||
# OpenVDB uses 'half' type from OpenEXR & fails to link without OpenEXR enabled.
|
||||
set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENVDB OFF)
|
||||
|
||||
# Haru needs `TIFFFaxBlackCodes` & `TIFFFaxWhiteCodes` symbols from TIFF.
|
||||
set_and_warn_dependency(WITH_IMAGE_TIFF WITH_HARU OFF)
|
||||
|
||||
# auto enable openimageio for cycles
|
||||
if(WITH_CYCLES)
|
||||
set(WITH_OPENIMAGEIO ON)
|
||||
@@ -1853,7 +1849,6 @@ if(FIRST_RUN)
|
||||
info_cfg_option(WITH_FFTW3)
|
||||
info_cfg_option(WITH_FREESTYLE)
|
||||
info_cfg_option(WITH_GMP)
|
||||
info_cfg_option(WITH_HARU)
|
||||
info_cfg_option(WITH_IK_ITASC)
|
||||
info_cfg_option(WITH_IK_SOLVER)
|
||||
info_cfg_option(WITH_INPUT_NDOF)
|
||||
|
13
GNUmakefile
13
GNUmakefile
@@ -183,13 +183,8 @@ endif
|
||||
ifndef DEPS_INSTALL_DIR
|
||||
DEPS_INSTALL_DIR:=$(shell dirname "$(BLENDER_DIR)")/lib/$(OS_NCASE)
|
||||
|
||||
# Add processor type to directory name, except for darwin x86_64
|
||||
# which by convention does not have it.
|
||||
ifeq ($(OS_NCASE),darwin)
|
||||
ifneq ($(CPU),x86_64)
|
||||
DEPS_INSTALL_DIR:=$(DEPS_INSTALL_DIR)_$(CPU)
|
||||
endif
|
||||
else
|
||||
ifneq ($(OS_NCASE),darwin)
|
||||
# Add processor type to directory name
|
||||
DEPS_INSTALL_DIR:=$(DEPS_INSTALL_DIR)_$(CPU)
|
||||
endif
|
||||
endif
|
||||
@@ -203,7 +198,7 @@ endif
|
||||
# in libraries, or python 2 for running make update to get it.
|
||||
ifeq ($(OS_NCASE),darwin)
|
||||
ifeq (, $(shell command -v $(PYTHON)))
|
||||
PYTHON:=$(DEPS_INSTALL_DIR)/python/bin/python3.7m
|
||||
PYTHON:=../lib/darwin/python/bin/python3.7m
|
||||
ifeq (, $(shell command -v $(PYTHON)))
|
||||
PYTHON:=python
|
||||
endif
|
||||
@@ -525,7 +520,7 @@ format: .FORCE
|
||||
|
||||
# Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation.
|
||||
doc_py: .FORCE
|
||||
ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \
|
||||
ASAN_OPTIONS=halt_on_error=0 \
|
||||
$(BLENDER_BIN) --background -noaudio --factory-startup \
|
||||
--python doc/python_api/sphinx_doc_gen.py
|
||||
sphinx-build -b html -j $(NPROCS) doc/python_api/sphinx-in doc/python_api/sphinx-out
|
||||
|
@@ -92,7 +92,6 @@ include(cmake/package_python.cmake)
|
||||
include(cmake/numpy.cmake)
|
||||
include(cmake/usd.cmake)
|
||||
include(cmake/potrace.cmake)
|
||||
include(cmake/haru.cmake)
|
||||
# Boost needs to be included after python.cmake due to the PYTHON_BINARY variable being needed.
|
||||
include(cmake/boost.cmake)
|
||||
include(cmake/pugixml.cmake)
|
||||
|
@@ -1,46 +0,0 @@
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(HARU_EXTRA_ARGS
|
||||
-DLIBHPDF_SHARED=OFF
|
||||
-DLIBHPDF_STATIC=ON
|
||||
-DLIBHPDF_EXAMPLES=OFF
|
||||
-DLIBHPDF_ENABLE_EXCEPTIONS=ON
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_haru
|
||||
URL ${HARU_URI}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${HARU_HASH}
|
||||
PREFIX ${BUILD_DIR}/haru
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/haru/src/external_haru < ${PATCH_DIR}/haru.diff
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=${LIBDIR}/haru
|
||||
${DEFAULT_CMAKE_FLAGS} ${HARU_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/haru
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_haru after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/haru/include ${HARVEST_TARGET}/haru/include
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/haru/lib/libhpdfs.lib ${HARVEST_TARGET}/haru/lib/libhpdfs.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
endif()
|
@@ -187,8 +187,6 @@ harvest(usd/lib/usd usd/lib/usd "*")
|
||||
harvest(usd/plugin usd/plugin "*")
|
||||
harvest(potrace/include potrace/include "*.h")
|
||||
harvest(potrace/lib potrace/lib "*.a")
|
||||
harvest(haru/include haru/include "*.h")
|
||||
harvest(haru/lib haru/lib "*.a")
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
harvest(libglu/lib mesa/lib "*.so*")
|
||||
|
@@ -331,7 +331,3 @@ set(GMP_HASH a325e3f09e6d91e62101e59f9bda3ec1)
|
||||
set(POTRACE_VERSION 1.16)
|
||||
set(POTRACE_URI http://potrace.sourceforge.net/download/${POTRACE_VERSION}/potrace-${POTRACE_VERSION}.tar.gz)
|
||||
set(POTRACE_HASH 5f0bd87ddd9a620b0c4e65652ef93d69)
|
||||
|
||||
set(HARU_VERSION 2_3_0)
|
||||
set(HARU_URI https://github.com/libharu/libharu/archive/RELEASE_${HARU_VERSION}.tar.gz)
|
||||
set(HARU_HASH 4f916aa49c3069b3a10850013c507460)
|
||||
|
@@ -385,25 +385,25 @@ USE_CXX11=true
|
||||
CLANG_FORMAT_VERSION_MIN="6.0"
|
||||
CLANG_FORMAT_VERSION_MAX="10.0"
|
||||
|
||||
PYTHON_VERSION="3.9.1"
|
||||
PYTHON_VERSION_SHORT="3.9"
|
||||
PYTHON_VERSION="3.7.7"
|
||||
PYTHON_VERSION_SHORT="3.7"
|
||||
PYTHON_VERSION_MIN="3.7"
|
||||
PYTHON_VERSION_MAX="3.10"
|
||||
PYTHON_VERSION_MAX="3.9"
|
||||
PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_MIN
|
||||
PYTHON_FORCE_BUILD=false
|
||||
PYTHON_FORCE_REBUILD=false
|
||||
PYTHON_SKIP=false
|
||||
|
||||
NUMPY_VERSION="1.19.5"
|
||||
NUMPY_VERSION_SHORT="1.19"
|
||||
NUMPY_VERSION="1.17.5"
|
||||
NUMPY_VERSION_SHORT="1.17"
|
||||
NUMPY_VERSION_MIN="1.8"
|
||||
NUMPY_VERSION_MAX="2.0"
|
||||
NUMPY_FORCE_BUILD=false
|
||||
NUMPY_FORCE_REBUILD=false
|
||||
NUMPY_SKIP=false
|
||||
|
||||
BOOST_VERSION="1.73.0"
|
||||
BOOST_VERSION_SHORT="1.73"
|
||||
BOOST_VERSION="1.70.0"
|
||||
BOOST_VERSION_SHORT="1.70"
|
||||
BOOST_VERSION_MIN="1.49"
|
||||
BOOST_VERSION_MAX="2.0"
|
||||
BOOST_FORCE_BUILD=false
|
||||
@@ -439,7 +439,7 @@ _with_built_openexr=false
|
||||
OIIO_VERSION="2.1.15.0"
|
||||
OIIO_VERSION_SHORT="2.1"
|
||||
OIIO_VERSION_MIN="2.1.12"
|
||||
OIIO_VERSION_MAX="2.2.10"
|
||||
OIIO_VERSION_MAX="3.0"
|
||||
OIIO_FORCE_BUILD=false
|
||||
OIIO_FORCE_REBUILD=false
|
||||
OIIO_SKIP=false
|
||||
@@ -483,7 +483,7 @@ OPENVDB_FORCE_REBUILD=false
|
||||
OPENVDB_SKIP=false
|
||||
|
||||
# Alembic needs to be compiled for now
|
||||
ALEMBIC_VERSION="1.7.16"
|
||||
ALEMBIC_VERSION="1.7.12"
|
||||
ALEMBIC_VERSION_SHORT="1.7"
|
||||
ALEMBIC_VERSION_MIN="1.7"
|
||||
ALEMBIC_VERSION_MAX="2.0"
|
||||
@@ -2064,6 +2064,7 @@ compile_OIIO() {
|
||||
cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
|
||||
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
|
||||
cmake_d="$cmake_d -D STOP_ON_WARNING=OFF"
|
||||
cmake_d="$cmake_d -D BUILDSTATIC=OFF"
|
||||
cmake_d="$cmake_d -D LINKSTATIC=OFF"
|
||||
cmake_d="$cmake_d -D USE_SIMD=sse2"
|
||||
|
||||
@@ -2098,6 +2099,9 @@ compile_OIIO() {
|
||||
# if [ -d $INST/ocio ]; then
|
||||
# cmake_d="$cmake_d -D OCIO_PATH=$INST/ocio"
|
||||
# fi
|
||||
cmake_d="$cmake_d -D USE_OCIO=OFF"
|
||||
|
||||
cmake_d="$cmake_d -D OIIO_BUILD_CPP11=ON"
|
||||
|
||||
if file /bin/cp | grep -q '32-bit'; then
|
||||
cflags="-fPIC -m32 -march=i686"
|
||||
|
@@ -1,12 +0,0 @@
|
||||
diff --git a/src/hpdf_image_ccitt.c b/src/hpdf_image_ccitt.c
|
||||
index 8672763..9be531a 100644
|
||||
--- a/src/hpdf_image_ccitt.c
|
||||
+++ b/src/hpdf_image_ccitt.c
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <memory.h>
|
||||
#include <assert.h>
|
||||
|
||||
-#define G3CODES
|
||||
#include "t4.h"
|
||||
|
||||
typedef unsigned int uint32;
|
@@ -34,8 +34,6 @@ set(_clang_tidy_SEARCH_DIRS
|
||||
# TODO(sergey): Find more reliable way of finding the latest clang-tidy.
|
||||
find_program(CLANG_TIDY_EXECUTABLE
|
||||
NAMES
|
||||
clang-tidy-12
|
||||
clang-tidy-11
|
||||
clang-tidy-10
|
||||
clang-tidy-9
|
||||
clang-tidy-8
|
||||
|
@@ -1,64 +0,0 @@
|
||||
# - Find HARU library
|
||||
# Find the native Haru includes and library
|
||||
# This module defines
|
||||
# HARU_INCLUDE_DIRS, where to find hpdf.h, set when
|
||||
# HARU_INCLUDE_DIR is found.
|
||||
# HARU_LIBRARIES, libraries to link against to use Haru.
|
||||
# HARU_ROOT_DIR, The base directory to search for Haru.
|
||||
# This can also be an environment variable.
|
||||
# HARU_FOUND, If false, do not try to use Haru.
|
||||
#
|
||||
# also defined, but not for general use are
|
||||
# HARU_LIBRARY, where to find the Haru library.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2021 Blender Foundation.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD 3-Clause License,
|
||||
# see accompanying file BSD-3-Clause-license.txt for details.
|
||||
#=============================================================================
|
||||
|
||||
# If HARU_ROOT_DIR was defined in the environment, use it.
|
||||
if(NOT HARU_ROOT_DIR AND NOT $ENV{HARU_ROOT_DIR} STREQUAL "")
|
||||
set(HARU_ROOT_DIR $ENV{HARU_ROOT_DIR})
|
||||
endif()
|
||||
|
||||
set(_haru_SEARCH_DIRS
|
||||
${HARU_ROOT_DIR}
|
||||
/opt/lib/haru
|
||||
)
|
||||
|
||||
find_path(HARU_INCLUDE_DIR
|
||||
NAMES
|
||||
hpdf.h
|
||||
HINTS
|
||||
${_haru_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
include/haru
|
||||
)
|
||||
|
||||
find_library(HARU_LIBRARY
|
||||
NAMES
|
||||
hpdfs
|
||||
HINTS
|
||||
${_haru_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments and set HARU_FOUND to TRUE if
|
||||
# all listed variables are TRUE.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Haru DEFAULT_MSG HARU_LIBRARY HARU_INCLUDE_DIR)
|
||||
|
||||
if(HARU_FOUND)
|
||||
set(HARU_LIBRARIES ${HARU_LIBRARY})
|
||||
set(HARU_INCLUDE_DIRS ${HARU_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
HARU_INCLUDE_DIR
|
||||
HARU_LIBRARY
|
||||
)
|
||||
|
||||
unset(_haru_SEARCH_DIRS)
|
@@ -99,9 +99,7 @@ macro(BLENDER_SRC_GTEST_EX)
|
||||
|
||||
# Don't fail tests on leaks since these often happen in external libraries
|
||||
# that we can't fix.
|
||||
set_tests_properties(${TARGET_NAME} PROPERTIES
|
||||
ENVIRONMENT LSAN_OPTIONS=exitcode=0:$ENV{LSAN_OPTIONS}
|
||||
)
|
||||
set_tests_properties(${TARGET_NAME} PROPERTIES ENVIRONMENT LSAN_OPTIONS=exitcode=0)
|
||||
endif()
|
||||
if(WIN32)
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES VS_GLOBAL_VcpkgEnabled "false")
|
||||
|
@@ -19,7 +19,6 @@ set(WITH_DRACO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_GMP ON CACHE BOOL "" FORCE)
|
||||
set(WITH_HARU ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
|
||||
|
@@ -24,7 +24,6 @@ set(WITH_DRACO OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_GMP OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_HARU OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE)
|
||||
|
@@ -20,7 +20,6 @@ set(WITH_DRACO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_GMP ON CACHE BOOL "" FORCE)
|
||||
set(WITH_HARU ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
|
||||
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)
|
||||
|
@@ -72,11 +72,7 @@ if(WITH_JACK)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED LIBDIR)
|
||||
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin)
|
||||
else()
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin_${CMAKE_OSX_ARCHITECTURES})
|
||||
endif()
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin)
|
||||
else()
|
||||
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
||||
endif()
|
||||
@@ -432,14 +428,6 @@ if(WITH_GMP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_HARU)
|
||||
find_package(Haru)
|
||||
if(NOT HARU_FOUND)
|
||||
message(WARNING "Haru not found, disabling WITH_HARU")
|
||||
set(WITH_HARU OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(EXISTS ${LIBDIR})
|
||||
without_system_libs_end()
|
||||
endif()
|
||||
|
@@ -800,15 +800,3 @@ if(WITH_POTRACE)
|
||||
set(POTRACE_LIBRARIES ${LIBDIR}/potrace/lib/potrace.lib)
|
||||
set(POTRACE_FOUND On)
|
||||
endif()
|
||||
|
||||
if(WITH_HARU)
|
||||
if(EXISTS ${LIBDIR}/haru)
|
||||
set(HARU_FOUND On)
|
||||
set(HARU_ROOT_DIR ${LIBDIR}/haru)
|
||||
set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include)
|
||||
set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib)
|
||||
else()
|
||||
message(WARNING "Haru was not found, disabling WITH_HARU")
|
||||
set(WITH_HARU OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
@@ -8,7 +8,6 @@
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
@@ -50,12 +49,7 @@ def svn_update(args, release_version):
|
||||
|
||||
# Checkout precompiled libraries
|
||||
if sys.platform == 'darwin':
|
||||
if platform.machine() == 'x86_64':
|
||||
lib_platform = "darwin"
|
||||
elif platform.machine() == 'arm64':
|
||||
lib_platform = "darwin_arm64"
|
||||
else:
|
||||
lib_platform = None
|
||||
lib_platform = "darwin"
|
||||
elif sys.platform == 'win32':
|
||||
# Windows checkout is usually handled by bat scripts since python3 to run
|
||||
# this script is bundled as part of the precompiled libraries. However it
|
||||
|
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "V2.93"
|
||||
PROJECT_NUMBER = "V2.92"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
@@ -52,11 +52,10 @@ outfilename = sys.argv[2]
|
||||
|
||||
cmd = [blender_bin, "--help"]
|
||||
print(" executing:", " ".join(cmd))
|
||||
ASAN_OPTIONS = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "")
|
||||
blender_help = subprocess.run(
|
||||
cmd, env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8")
|
||||
cmd, env={"ASAN_OPTIONS": "exitcode=0"}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8")
|
||||
blender_version = subprocess.run(
|
||||
[blender_bin, "--version"], env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip()
|
||||
[blender_bin, "--version"], env={"ASAN_OPTIONS": "exitcode=0"}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip()
|
||||
blender_version, blender_date = (blender_version.split("build") + [None, None])[0:2]
|
||||
blender_version = blender_version.rstrip().partition(" ")[2] # remove 'Blender' prefix.
|
||||
if blender_date is None:
|
||||
|
@@ -55,7 +55,7 @@ if $DO_EXE_BLENDER ; then
|
||||
# Don't delete existing docs, now partial updates are used for quick builds.
|
||||
#
|
||||
# Disable ASAN error halt since it results in nonzero exit code on any minor issue.
|
||||
ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \
|
||||
ASAN_OPTIONS=halt_on_error=0 \
|
||||
$BLENDER_BIN \
|
||||
--background \
|
||||
-noaudio \
|
||||
|
5
extern/mantaflow/helper/util/vectorbase.h
vendored
5
extern/mantaflow/helper/util/vectorbase.h
vendored
@@ -664,6 +664,11 @@ template<class T> inline Vec3i toVec3iRound(T v)
|
||||
return Vec3i((int)round(v[0]), (int)round(v[1]), (int)round(v[2]));
|
||||
}
|
||||
|
||||
template<class T> inline Vec3i toVec3iFloor(T v)
|
||||
{
|
||||
return Vec3i((int)floor(v[0]), (int)floor(v[1]), (int)floor(v[2]));
|
||||
}
|
||||
|
||||
//! convert to int Vector if values are close enough to an int
|
||||
template<class T> inline Vec3i toVec3iChecked(T v)
|
||||
{
|
||||
|
10
extern/mantaflow/preprocessed/fileio/iovdb.cpp
vendored
10
extern/mantaflow/preprocessed/fileio/iovdb.cpp
vendored
@@ -209,11 +209,11 @@ typename GridType::Ptr exportVDB(Grid<T> *from, float clip, openvdb::FloatGrid::
|
||||
openvdb::Coord(from->getSizeX() - 1, from->getSizeY() - 1, from->getSizeZ() - 1));
|
||||
openvdb::tools::Dense<ValueT, openvdb::tools::MemoryLayout::LayoutXYZ> dense(bbox, data);
|
||||
|
||||
// Trick: Set clip value to very small / negative value in order to copy all values of dense
|
||||
// grids
|
||||
float tmpClip = (from->saveSparse()) ? clip : -std::numeric_limits<Real>::max();
|
||||
// Use clip value, or (when not exporting in sparse mode) clear it in order to copy all values
|
||||
// of dense grid
|
||||
ValueT tmpClip = (from->saveSparse()) ? ValueT(clip) : ValueT(0);
|
||||
// Copy from dense to sparse grid structure considering clip value
|
||||
openvdb::tools::copyFromDense(dense, *to, ValueT(tmpClip));
|
||||
openvdb::tools::copyFromDense(dense, *to, tmpClip);
|
||||
|
||||
// If present, use clip grid to trim down current vdb grid even more
|
||||
if (from->saveSparse() && clipGrid && !clipGrid->empty()) {
|
||||
@@ -245,10 +245,10 @@ void exportVDB(ParticleDataImpl<MantaType> *from,
|
||||
std::vector<VDBType> vdbValues;
|
||||
std::string name = from->getName();
|
||||
|
||||
BasicParticleSystem *pp = dynamic_cast<BasicParticleSystem *>(from->getParticleSys());
|
||||
FOR_PARTS(*from)
|
||||
{
|
||||
// Optionally, skip exporting particles that have been marked as deleted
|
||||
BasicParticleSystem *pp = dynamic_cast<BasicParticleSystem *>(from->getParticleSys());
|
||||
if (skipDeletedParts && !pp->isActive(idx)) {
|
||||
continue;
|
||||
}
|
||||
|
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
#define MANTA_GIT_VERSION "commit 1c86d86496e7f7473c36248d12ef07bf4d9d2840"
|
||||
#define MANTA_GIT_VERSION "commit 39b7a415721ecbf6643612a24e8eadd221aeb934"
|
||||
|
15
extern/mantaflow/preprocessed/grid.h
vendored
15
extern/mantaflow/preprocessed/grid.h
vendored
@@ -204,14 +204,12 @@ class GridBase : public PbClass {
|
||||
inline void checkIndex(int i, int j, int k) const;
|
||||
//! Check if indices are within bounds, otherwise error (should only be called when debugging)
|
||||
inline void checkIndex(IndexInt idx) const;
|
||||
//! Check if index is within given boundaries
|
||||
inline bool isInBounds(const Vec3i &p, int bnd) const;
|
||||
//! Check if index is within given boundaries
|
||||
inline bool isInBounds(const Vec3i &p) const;
|
||||
//! Check if index is within given boundaries
|
||||
//! Check if vector int is within given boundaries
|
||||
inline bool isInBounds(const Vec3i &p, int bnd = 0) const;
|
||||
//! Check if vector real is within given boundaries
|
||||
inline bool isInBounds(const Vec3 &p, int bnd = 0) const
|
||||
{
|
||||
return isInBounds(toVec3i(p), bnd);
|
||||
return isInBounds(toVec3iFloor(p), bnd);
|
||||
}
|
||||
//! Check if linear index is in the range of the array
|
||||
inline bool isInBounds(IndexInt idx) const;
|
||||
@@ -1785,11 +1783,6 @@ inline void GridBase::checkIndex(IndexInt idx) const
|
||||
}
|
||||
}
|
||||
|
||||
bool GridBase::isInBounds(const Vec3i &p) const
|
||||
{
|
||||
return (p.x >= 0 && p.y >= 0 && p.z >= 0 && p.x < mSize.x && p.y < mSize.y && p.z < mSize.z);
|
||||
}
|
||||
|
||||
bool GridBase::isInBounds(const Vec3i &p, int bnd) const
|
||||
{
|
||||
bool ret = (p.x >= bnd && p.y >= bnd && p.x < mSize.x - bnd && p.y < mSize.y - bnd);
|
||||
|
10
extern/mantaflow/preprocessed/plugin/flip.cpp
vendored
10
extern/mantaflow/preprocessed/plugin/flip.cpp
vendored
@@ -429,7 +429,7 @@ void markFluidCells(const BasicParticleSystem &parts,
|
||||
for (IndexInt idx = 0; idx < parts.size(); idx++) {
|
||||
if (!parts.isActive(idx) || (ptype && ((*ptype)[idx] & exclude)))
|
||||
continue;
|
||||
Vec3i p = toVec3i(parts.getPos(idx));
|
||||
Vec3i p = toVec3iFloor(parts.getPos(idx));
|
||||
if (flags.isInBounds(p) && flags.isEmpty(p))
|
||||
flags(p) = (flags(p) | FlagGrid::TypeFluid) & ~FlagGrid::TypeEmpty;
|
||||
}
|
||||
@@ -544,7 +544,7 @@ void adjustNumber(BasicParticleSystem &parts,
|
||||
// count particles in cells, and delete excess particles
|
||||
for (IndexInt idx = 0; idx < (int)parts.size(); idx++) {
|
||||
if (parts.isActive(idx)) {
|
||||
Vec3i p = toVec3i(parts.getPos(idx));
|
||||
Vec3i p = toVec3iFloor(parts.getPos(idx));
|
||||
if (!tmp.isInBounds(p)) {
|
||||
parts.kill(idx); // out of domain, remove
|
||||
continue;
|
||||
@@ -711,7 +711,7 @@ void gridParticleIndex(const BasicParticleSystem &parts,
|
||||
for (IndexInt idx = 0; idx < (IndexInt)parts.size(); idx++) {
|
||||
if (parts.isActive(idx)) {
|
||||
// check index for validity...
|
||||
Vec3i p = toVec3i(parts.getPos(idx));
|
||||
Vec3i p = toVec3iFloor(parts.getPos(idx));
|
||||
if (!index.isInBounds(p)) {
|
||||
inactive++;
|
||||
continue;
|
||||
@@ -740,7 +740,7 @@ void gridParticleIndex(const BasicParticleSystem &parts,
|
||||
for (IndexInt idx = 0; idx < (IndexInt)parts.size(); idx++) {
|
||||
if (!parts.isActive(idx))
|
||||
continue;
|
||||
Vec3i p = toVec3i(parts.getPos(idx));
|
||||
Vec3i p = toVec3iFloor(parts.getPos(idx));
|
||||
if (!index.isInBounds(p)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1636,7 +1636,7 @@ struct knPushOutofObs : public KernelBase {
|
||||
{
|
||||
if (!parts.isActive(idx) || (ptype && ((*ptype)[idx] & exclude)))
|
||||
return;
|
||||
Vec3i p = toVec3i(parts.getPos(idx));
|
||||
Vec3i p = toVec3iFloor(parts.getPos(idx));
|
||||
|
||||
if (!flags.isInBounds(p))
|
||||
return;
|
||||
|
@@ -2278,7 +2278,7 @@ T convolveGrid(Grid<T> &originGrid, GaussianKernelCreator &gkSigma, Vec3 pos, in
|
||||
step = Vec3(0.0, 0.0, 1.0);
|
||||
T pxResult(0);
|
||||
for (int i = 0; i < gkSigma.mDim; ++i) {
|
||||
Vec3i curpos = toVec3i(pos - step * (i - gkSigma.mDim / 2));
|
||||
Vec3i curpos = toVec3iFloor(pos - step * (i - gkSigma.mDim / 2));
|
||||
if (originGrid.isInBounds(curpos))
|
||||
pxResult += gkSigma.get1DKernelValue(i) * originGrid.get(curpos);
|
||||
else { // TODO , improve...
|
||||
@@ -2423,7 +2423,7 @@ struct KnBlurMACGridGauss : public KernelBase {
|
||||
|
||||
Vec3 pxResult(0.0f);
|
||||
for (int di = 0; di < gkSigma.mDim; ++di) {
|
||||
Vec3i curpos = toVec3i(pos - step * (di - gkSigma.mDim / 2));
|
||||
Vec3i curpos = toVec3iFloor(pos - step * (di - gkSigma.mDim / 2));
|
||||
if (!originGrid.isInBounds(curpos)) {
|
||||
if (curpos.x < 0)
|
||||
curpos.x = 0;
|
||||
|
@@ -1214,8 +1214,8 @@ struct knFlipUpdateSecondaryParticlesLinear : public KernelBase {
|
||||
|
||||
// anti tunneling for small obstacles
|
||||
for (int ct = 1; ct < antitunneling; ct++) {
|
||||
Vec3i tempPos = toVec3i(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
Vec3i tempPos = toVec3iFloor(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
if (!flags.isInBounds(tempPos) || flags(tempPos) & FlagGrid::TypeObstacle) {
|
||||
pts_sec.kill(idx);
|
||||
return;
|
||||
@@ -1234,8 +1234,8 @@ struct knFlipUpdateSecondaryParticlesLinear : public KernelBase {
|
||||
|
||||
// anti tunneling for small obstacles
|
||||
for (int ct = 1; ct < antitunneling; ct++) {
|
||||
Vec3i tempPos = toVec3i(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
Vec3i tempPos = toVec3iFloor(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
if (!flags.isInBounds(tempPos) || flags(tempPos) & FlagGrid::TypeObstacle) {
|
||||
pts_sec.kill(idx);
|
||||
return;
|
||||
@@ -1252,7 +1252,7 @@ struct knFlipUpdateSecondaryParticlesLinear : public KernelBase {
|
||||
const Vec3 vj = v.getInterpolated(pts_sec[idx].pos);
|
||||
// anti tunneling for small obstacles
|
||||
for (int ct = 1; ct < antitunneling; ct++) {
|
||||
Vec3i tempPos = toVec3i(pts_sec[idx].pos + ct * (1 / Real(antitunneling)) * dt * vj);
|
||||
Vec3i tempPos = toVec3iFloor(pts_sec[idx].pos + ct * (1 / Real(antitunneling)) * dt * vj);
|
||||
if (!flags.isInBounds(tempPos) || flags(tempPos) & FlagGrid::TypeObstacle) {
|
||||
pts_sec.kill(idx);
|
||||
return;
|
||||
@@ -1474,8 +1474,8 @@ struct knFlipUpdateSecondaryParticlesCubic : public KernelBase {
|
||||
|
||||
// anti tunneling for small obstacles
|
||||
for (int ct = 1; ct < antitunneling; ct++) {
|
||||
Vec3i tempPos = toVec3i(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
Vec3i tempPos = toVec3iFloor(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
if (!flags.isInBounds(tempPos) || flags(tempPos) & FlagGrid::TypeObstacle) {
|
||||
pts_sec.kill(idx);
|
||||
return;
|
||||
@@ -1515,8 +1515,8 @@ struct knFlipUpdateSecondaryParticlesCubic : public KernelBase {
|
||||
|
||||
// anti tunneling for small obstacles
|
||||
for (int ct = 1; ct < antitunneling; ct++) {
|
||||
Vec3i tempPos = toVec3i(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
Vec3i tempPos = toVec3iFloor(pts_sec[idx].pos +
|
||||
ct * (1 / Real(antitunneling)) * dt * v_sec[idx]);
|
||||
if (!flags.isInBounds(tempPos) || flags(tempPos) & FlagGrid::TypeObstacle) {
|
||||
pts_sec.kill(idx);
|
||||
return;
|
||||
@@ -1554,8 +1554,8 @@ struct knFlipUpdateSecondaryParticlesCubic : public KernelBase {
|
||||
|
||||
// anti tunneling for small obstacles
|
||||
for (int ct = 1; ct < antitunneling; ct++) {
|
||||
Vec3i tempPos = toVec3i(pts_sec[idx].pos + ct * (1 / Real(antitunneling)) * dt *
|
||||
(sumNumerator / sumDenominator));
|
||||
Vec3i tempPos = toVec3iFloor(pts_sec[idx].pos + ct * (1 / Real(antitunneling)) * dt *
|
||||
(sumNumerator / sumDenominator));
|
||||
if (!flags.isInBounds(tempPos) || flags(tempPos) & FlagGrid::TypeObstacle) {
|
||||
pts_sec.kill(idx);
|
||||
return;
|
||||
@@ -1863,7 +1863,7 @@ struct knFlipDeleteParticlesInObstacle : public KernelBase {
|
||||
return;
|
||||
|
||||
const Vec3 &xi = pts[idx].pos;
|
||||
const Vec3i xidx = toVec3i(xi);
|
||||
const Vec3i xidx = toVec3iFloor(xi);
|
||||
// remove particles that completely left the bounds
|
||||
if (!flags.isInBounds(xidx)) {
|
||||
pts.kill(idx);
|
||||
|
@@ -2145,8 +2145,7 @@ void PbRegister_particleSurfaceTurbulence()
|
||||
void debugCheckParts(const BasicParticleSystem &parts, const FlagGrid &flags)
|
||||
{
|
||||
for (int idx = 0; idx < parts.size(); idx++) {
|
||||
Vec3i p = toVec3i(parts.getPos(idx));
|
||||
if (!flags.isInBounds(p)) {
|
||||
if (!flags.isInBounds(parts.getPos(idx))) {
|
||||
debMsg("bad position??? " << idx << " " << parts.getPos(idx), 1);
|
||||
exit(1);
|
||||
}
|
||||
|
@@ -59,7 +59,6 @@ class CyclesRender(bpy.types.RenderEngine):
|
||||
bl_use_exclude_layers = True
|
||||
bl_use_save_buffers = True
|
||||
bl_use_spherical_stereo = True
|
||||
bl_use_custom_freestyle = True
|
||||
|
||||
def __init__(self):
|
||||
self.session = None
|
||||
|
@@ -67,10 +67,11 @@ static bool ObtainCacheParticleData(
|
||||
Transform tfm = get_transform(b_ob->matrix_world());
|
||||
Transform itfm = transform_quick_inverse(tfm);
|
||||
|
||||
for (BL::Modifier &b_mod : b_ob->modifiers) {
|
||||
if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
|
||||
(background ? b_mod.show_render() : b_mod.show_viewport())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr);
|
||||
BL::Object::modifiers_iterator b_mod;
|
||||
for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
|
||||
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
|
||||
(background ? b_mod->show_render() : b_mod->show_viewport())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
|
||||
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
||||
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
||||
|
||||
@@ -162,10 +163,11 @@ static bool ObtainCacheParticleUV(Hair *hair,
|
||||
|
||||
CData->curve_uv.clear();
|
||||
|
||||
for (BL::Modifier &b_mod : b_ob->modifiers) {
|
||||
if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
|
||||
(background ? b_mod.show_render() : b_mod.show_viewport())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr);
|
||||
BL::Object::modifiers_iterator b_mod;
|
||||
for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
|
||||
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
|
||||
(background ? b_mod->show_render() : b_mod->show_viewport())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
|
||||
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
||||
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
||||
|
||||
@@ -224,10 +226,11 @@ static bool ObtainCacheParticleVcol(Hair *hair,
|
||||
|
||||
CData->curve_vcol.clear();
|
||||
|
||||
for (BL::Modifier &b_mod : b_ob->modifiers) {
|
||||
if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
|
||||
(background ? b_mod.show_render() : b_mod.show_viewport())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr);
|
||||
BL::Object::modifiers_iterator b_mod;
|
||||
for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
|
||||
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
|
||||
(background ? b_mod->show_render() : b_mod->show_viewport())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
|
||||
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
||||
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
||||
|
||||
@@ -507,10 +510,11 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int
|
||||
bool BlenderSync::object_has_particle_hair(BL::Object b_ob)
|
||||
{
|
||||
/* Test if the object has a particle modifier with hair. */
|
||||
for (BL::Modifier &b_mod : b_ob.modifiers) {
|
||||
if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
|
||||
(preview ? b_mod.show_viewport() : b_mod.show_render())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr);
|
||||
BL::Object::modifiers_iterator b_mod;
|
||||
for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
|
||||
if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
|
||||
(preview ? b_mod->show_viewport() : b_mod->show_render())) {
|
||||
BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
|
||||
BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
|
||||
BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
|
||||
|
||||
@@ -674,7 +678,9 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
|
||||
/* Export curves and points. */
|
||||
vector<float> points_length;
|
||||
|
||||
for (BL::HairCurve &b_curve : b_hair.curves) {
|
||||
BL::Hair::curves_iterator b_curve_iter;
|
||||
for (b_hair.curves.begin(b_curve_iter); b_curve_iter != b_hair.curves.end(); ++b_curve_iter) {
|
||||
BL::HairCurve b_curve = *b_curve_iter;
|
||||
const int first_point_index = b_curve.first_point_index();
|
||||
const int num_points = b_curve.num_points();
|
||||
|
||||
@@ -742,7 +748,9 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
|
||||
int num_motion_keys = 0;
|
||||
int curve_index = 0;
|
||||
|
||||
for (BL::HairCurve &b_curve : b_hair.curves) {
|
||||
BL::Hair::curves_iterator b_curve_iter;
|
||||
for (b_hair.curves.begin(b_curve_iter); b_curve_iter != b_hair.curves.end(); ++b_curve_iter) {
|
||||
BL::HairCurve b_curve = *b_curve_iter;
|
||||
const int first_point_index = b_curve.first_point_index();
|
||||
const int num_points = b_curve.num_points();
|
||||
|
||||
@@ -847,7 +855,10 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *ha
|
||||
hair->set_value(socket, new_hair, socket);
|
||||
}
|
||||
|
||||
hair->attributes.update(std::move(new_hair.attributes));
|
||||
hair->attributes.clear();
|
||||
foreach (Attribute &attr, new_hair.attributes.attributes) {
|
||||
hair->attributes.attributes.push_back(std::move(attr));
|
||||
}
|
||||
|
||||
/* tag update */
|
||||
|
||||
|
@@ -47,9 +47,11 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
|
||||
|
||||
/* Find cycles preferences. */
|
||||
PointerRNA cpreferences;
|
||||
for (BL::Addon &b_addon : b_preferences.addons) {
|
||||
if (b_addon.module() == "cycles") {
|
||||
cpreferences = b_addon.preferences().ptr;
|
||||
BL::Preferences::addons_iterator b_addon_iter;
|
||||
for (b_preferences.addons.begin(b_addon_iter); b_addon_iter != b_preferences.addons.end();
|
||||
++b_addon_iter) {
|
||||
if (b_addon_iter->module() == "cycles") {
|
||||
cpreferences = b_addon_iter->preferences().ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -42,34 +42,6 @@ static Geometry::Type determine_geom_type(BL::Object &b_ob, bool use_particle_ha
|
||||
return Geometry::MESH;
|
||||
}
|
||||
|
||||
array<Node *> BlenderSync::find_used_shaders(BL::Object &b_ob)
|
||||
{
|
||||
BL::Material material_override = view_layer.material_override;
|
||||
Shader *default_shader = (b_ob.type() == BL::Object::type_VOLUME) ? scene->default_volume :
|
||||
scene->default_surface;
|
||||
|
||||
array<Node *> used_shaders;
|
||||
|
||||
for (BL::MaterialSlot &b_slot : b_ob.material_slots) {
|
||||
if (material_override) {
|
||||
find_shader(material_override, used_shaders, default_shader);
|
||||
}
|
||||
else {
|
||||
BL::ID b_material(b_slot.material());
|
||||
find_shader(b_material, used_shaders, default_shader);
|
||||
}
|
||||
}
|
||||
|
||||
if (used_shaders.size() == 0) {
|
||||
if (material_override)
|
||||
find_shader(material_override, used_shaders, default_shader);
|
||||
else
|
||||
used_shaders.push_back_slow(default_shader);
|
||||
}
|
||||
|
||||
return used_shaders;
|
||||
}
|
||||
|
||||
Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
|
||||
BL::Object &b_ob,
|
||||
BL::Object &b_ob_instance,
|
||||
@@ -80,11 +52,32 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
|
||||
/* Test if we can instance or if the object is modified. */
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data;
|
||||
BL::Material material_override = view_layer.material_override;
|
||||
Shader *default_shader = (b_ob.type() == BL::Object::type_VOLUME) ? scene->default_volume :
|
||||
scene->default_surface;
|
||||
Geometry::Type geom_type = determine_geom_type(b_ob, use_particle_hair);
|
||||
GeometryKey key(b_key_id.ptr.data, geom_type);
|
||||
|
||||
/* Find shader indices. */
|
||||
array<Node *> used_shaders = find_used_shaders(b_ob);
|
||||
array<Node *> used_shaders;
|
||||
|
||||
BL::Object::material_slots_iterator slot;
|
||||
for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
|
||||
if (material_override) {
|
||||
find_shader(material_override, used_shaders, default_shader);
|
||||
}
|
||||
else {
|
||||
BL::ID b_material(slot->material());
|
||||
find_shader(b_material, used_shaders, default_shader);
|
||||
}
|
||||
}
|
||||
|
||||
if (used_shaders.size() == 0) {
|
||||
if (material_override)
|
||||
find_shader(material_override, used_shaders, default_shader);
|
||||
else
|
||||
used_shaders.push_back_slow(default_shader);
|
||||
}
|
||||
|
||||
/* Ensure we only sync instanced geometry once. */
|
||||
Geometry *geom = geometry_map.find(key);
|
||||
@@ -131,7 +124,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
|
||||
|
||||
foreach (Node *node, geom->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->need_update_geometry()) {
|
||||
if (shader->need_update_geometry) {
|
||||
attribute_recalc = true;
|
||||
}
|
||||
}
|
||||
|
@@ -285,10 +285,12 @@ static void attr_create_sculpt_vertex_color(Scene *scene,
|
||||
BL::Mesh &b_mesh,
|
||||
bool subdivision)
|
||||
{
|
||||
for (BL::MeshVertColorLayer &l : b_mesh.sculpt_vertex_colors) {
|
||||
const bool active_render = l.active_render();
|
||||
BL::Mesh::sculpt_vertex_colors_iterator l;
|
||||
|
||||
for (b_mesh.sculpt_vertex_colors.begin(l); l != b_mesh.sculpt_vertex_colors.end(); ++l) {
|
||||
const bool active_render = l->active_render();
|
||||
AttributeStandard vcol_std = (active_render) ? ATTR_STD_VERTEX_COLOR : ATTR_STD_NONE;
|
||||
ustring vcol_name = ustring(l.name().c_str());
|
||||
ustring vcol_name = ustring(l->name().c_str());
|
||||
|
||||
const bool need_vcol = mesh->need_attribute(scene, vcol_name) ||
|
||||
mesh->need_attribute(scene, vcol_std);
|
||||
@@ -305,7 +307,7 @@ static void attr_create_sculpt_vertex_color(Scene *scene,
|
||||
int numverts = b_mesh.vertices.length();
|
||||
|
||||
for (int i = 0; i < numverts; i++) {
|
||||
*(cdata++) = get_float4(l.data[i].color());
|
||||
*(cdata++) = get_float4(l->data[i].color());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,10 +315,12 @@ static void attr_create_sculpt_vertex_color(Scene *scene,
|
||||
/* Create vertex color attributes. */
|
||||
static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
|
||||
{
|
||||
for (BL::MeshLoopColorLayer &l : b_mesh.vertex_colors) {
|
||||
const bool active_render = l.active_render();
|
||||
BL::Mesh::vertex_colors_iterator l;
|
||||
|
||||
for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
|
||||
const bool active_render = l->active_render();
|
||||
AttributeStandard vcol_std = (active_render) ? ATTR_STD_VERTEX_COLOR : ATTR_STD_NONE;
|
||||
ustring vcol_name = ustring(l.name().c_str());
|
||||
ustring vcol_name = ustring(l->name().c_str());
|
||||
|
||||
const bool need_vcol = mesh->need_attribute(scene, vcol_name) ||
|
||||
mesh->need_attribute(scene, vcol_std);
|
||||
@@ -335,12 +339,13 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
|
||||
vcol_attr = mesh->subd_attributes.add(vcol_name, TypeRGBA, ATTR_ELEMENT_CORNER_BYTE);
|
||||
}
|
||||
|
||||
BL::Mesh::polygons_iterator p;
|
||||
uchar4 *cdata = vcol_attr->data_uchar4();
|
||||
|
||||
for (BL::MeshPolygon &p : b_mesh.polygons) {
|
||||
int n = p.loop_total();
|
||||
for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
|
||||
int n = p->loop_total();
|
||||
for (int i = 0; i < n; i++) {
|
||||
float4 color = get_float4(l.data[p.loop_start() + i].color());
|
||||
float4 color = get_float4(l->data[p->loop_start() + i].color());
|
||||
/* Compress/encode vertex color using the sRGB curve. */
|
||||
*(cdata++) = color_float4_to_uchar4(color);
|
||||
}
|
||||
@@ -354,13 +359,14 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
|
||||
vcol_attr = mesh->attributes.add(vcol_name, TypeRGBA, ATTR_ELEMENT_CORNER_BYTE);
|
||||
}
|
||||
|
||||
BL::Mesh::loop_triangles_iterator t;
|
||||
uchar4 *cdata = vcol_attr->data_uchar4();
|
||||
|
||||
for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
|
||||
int3 li = get_int3(t.loops());
|
||||
float4 c1 = get_float4(l.data[li[0]].color());
|
||||
float4 c2 = get_float4(l.data[li[1]].color());
|
||||
float4 c3 = get_float4(l.data[li[2]].color());
|
||||
for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
|
||||
int3 li = get_int3(t->loops());
|
||||
float4 c1 = get_float4(l->data[li[0]].color());
|
||||
float4 c2 = get_float4(l->data[li[1]].color());
|
||||
float4 c3 = get_float4(l->data[li[2]].color());
|
||||
|
||||
/* Compress/encode vertex color using the sRGB curve. */
|
||||
cdata[0] = color_float4_to_uchar4(c1);
|
||||
@@ -377,12 +383,14 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
|
||||
static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
|
||||
{
|
||||
if (b_mesh.uv_layers.length() != 0) {
|
||||
for (BL::MeshUVLoopLayer &l : b_mesh.uv_layers) {
|
||||
const bool active_render = l.active_render();
|
||||
BL::Mesh::uv_layers_iterator l;
|
||||
|
||||
for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) {
|
||||
const bool active_render = l->active_render();
|
||||
AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
|
||||
ustring uv_name = ustring(l.name().c_str());
|
||||
ustring uv_name = ustring(l->name().c_str());
|
||||
AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE;
|
||||
ustring tangent_name = ustring((string(l.name().c_str()) + ".tangent").c_str());
|
||||
ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str());
|
||||
|
||||
/* Denotes whether UV map was requested directly. */
|
||||
const bool need_uv = mesh->need_attribute(scene, uv_name) ||
|
||||
@@ -404,13 +412,14 @@ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
|
||||
uv_attr = mesh->attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER);
|
||||
}
|
||||
|
||||
BL::Mesh::loop_triangles_iterator t;
|
||||
float2 *fdata = uv_attr->data_float2();
|
||||
|
||||
for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
|
||||
int3 li = get_int3(t.loops());
|
||||
fdata[0] = get_float2(l.data[li[0]].uv());
|
||||
fdata[1] = get_float2(l.data[li[1]].uv());
|
||||
fdata[2] = get_float2(l.data[li[2]].uv());
|
||||
for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
|
||||
int3 li = get_int3(t->loops());
|
||||
fdata[0] = get_float2(l->data[li[0]].uv());
|
||||
fdata[1] = get_float2(l->data[li[1]].uv());
|
||||
fdata[2] = get_float2(l->data[li[2]].uv());
|
||||
fdata += 3;
|
||||
}
|
||||
}
|
||||
@@ -418,10 +427,10 @@ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
|
||||
/* UV tangent */
|
||||
if (need_tangent) {
|
||||
AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE;
|
||||
ustring sign_name = ustring((string(l.name().c_str()) + ".tangent_sign").c_str());
|
||||
ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
|
||||
bool need_sign = (mesh->need_attribute(scene, sign_name) ||
|
||||
mesh->need_attribute(scene, sign_std));
|
||||
mikk_compute_tangents(b_mesh, l.name().c_str(), mesh, need_sign, active_render);
|
||||
mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render);
|
||||
}
|
||||
/* Remove temporarily created UV attribute. */
|
||||
if (!need_uv && uv_attr != NULL) {
|
||||
@@ -471,12 +480,13 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
|
||||
uv_attr->flags |= ATTR_SUBDIVIDED;
|
||||
}
|
||||
|
||||
BL::Mesh::polygons_iterator p;
|
||||
float2 *fdata = uv_attr->data_float2();
|
||||
|
||||
for (BL::MeshPolygon &p : b_mesh.polygons) {
|
||||
int n = p.loop_total();
|
||||
for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
|
||||
int n = p->loop_total();
|
||||
for (int j = 0; j < n; j++) {
|
||||
*(fdata++) = get_float2(l->data[p.loop_start() + j].uv());
|
||||
*(fdata++) = get_float2(l->data[p->loop_start() + j].uv());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -696,8 +706,9 @@ static void attr_create_random_per_island(Scene *scene,
|
||||
|
||||
DisjointSet vertices_sets(number_of_vertices);
|
||||
|
||||
for (BL::MeshEdge &e : b_mesh.edges) {
|
||||
vertices_sets.join(e.vertices()[0], e.vertices()[1]);
|
||||
BL::Mesh::edges_iterator e;
|
||||
for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
|
||||
vertices_sets.join(e->vertices()[0], e->vertices()[1]);
|
||||
}
|
||||
|
||||
AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
|
||||
@@ -705,13 +716,15 @@ static void attr_create_random_per_island(Scene *scene,
|
||||
float *data = attribute->data_float();
|
||||
|
||||
if (!subdivision) {
|
||||
for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
|
||||
data[t.index()] = hash_uint_to_float(vertices_sets.find(t.vertices()[0]));
|
||||
BL::Mesh::loop_triangles_iterator t;
|
||||
for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
|
||||
data[t->index()] = hash_uint_to_float(vertices_sets.find(t->vertices()[0]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (BL::MeshPolygon &p : b_mesh.polygons) {
|
||||
data[p.index()] = hash_uint_to_float(vertices_sets.find(p.vertices()[0]));
|
||||
BL::Mesh::polygons_iterator p;
|
||||
for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
|
||||
data[p->index()] = hash_uint_to_float(vertices_sets.find(p->vertices()[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -743,9 +756,10 @@ static void create_mesh(Scene *scene,
|
||||
numtris = numfaces;
|
||||
}
|
||||
else {
|
||||
for (BL::MeshPolygon &p : b_mesh.polygons) {
|
||||
numngons += (p.loop_total() == 4) ? 0 : 1;
|
||||
numcorners += p.loop_total();
|
||||
BL::Mesh::polygons_iterator p;
|
||||
for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
|
||||
numngons += (p->loop_total() == 4) ? 0 : 1;
|
||||
numcorners += p->loop_total();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -789,15 +803,17 @@ static void create_mesh(Scene *scene,
|
||||
|
||||
/* create faces */
|
||||
if (!subdivision) {
|
||||
for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
|
||||
BL::MeshPolygon p = b_mesh.polygons[t.polygon_index()];
|
||||
int3 vi = get_int3(t.vertices());
|
||||
BL::Mesh::loop_triangles_iterator t;
|
||||
|
||||
for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
|
||||
BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
|
||||
int3 vi = get_int3(t->vertices());
|
||||
|
||||
int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
|
||||
bool smooth = p.use_smooth() || use_loop_normals;
|
||||
|
||||
if (use_loop_normals) {
|
||||
BL::Array<float, 9> loop_normals = t.split_normals();
|
||||
BL::Array<float, 9> loop_normals = t->split_normals();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
N[vi[i]] = make_float3(
|
||||
loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);
|
||||
@@ -812,17 +828,18 @@ static void create_mesh(Scene *scene,
|
||||
}
|
||||
}
|
||||
else {
|
||||
BL::Mesh::polygons_iterator p;
|
||||
vector<int> vi;
|
||||
|
||||
for (BL::MeshPolygon &p : b_mesh.polygons) {
|
||||
int n = p.loop_total();
|
||||
int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
|
||||
bool smooth = p.use_smooth() || use_loop_normals;
|
||||
for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
|
||||
int n = p->loop_total();
|
||||
int shader = clamp(p->material_index(), 0, used_shaders.size() - 1);
|
||||
bool smooth = p->use_smooth() || use_loop_normals;
|
||||
|
||||
vi.resize(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
/* NOTE: Autosmooth is already taken care about. */
|
||||
vi[i] = b_mesh.loops[p.loop_start() + i].vertex_index();
|
||||
vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();
|
||||
}
|
||||
|
||||
/* create subd faces */
|
||||
@@ -874,18 +891,19 @@ static void create_subd_mesh(Scene *scene,
|
||||
|
||||
/* export creases */
|
||||
size_t num_creases = 0;
|
||||
BL::Mesh::edges_iterator e;
|
||||
|
||||
for (BL::MeshEdge &e : b_mesh.edges) {
|
||||
if (e.crease() != 0.0f) {
|
||||
for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
|
||||
if (e->crease() != 0.0f) {
|
||||
num_creases++;
|
||||
}
|
||||
}
|
||||
|
||||
mesh->reserve_subd_creases(num_creases);
|
||||
|
||||
for (BL::MeshEdge &e : b_mesh.edges) {
|
||||
if (e.crease() != 0.0f) {
|
||||
mesh->add_crease(e.vertices()[0], e.vertices()[1], e.crease());
|
||||
for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
|
||||
if (e->crease() != 0.0f) {
|
||||
mesh->add_crease(e->vertices()[0], e->vertices()[1], e->crease());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1057,8 +1075,15 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me
|
||||
mesh->set_value(socket, new_mesh, socket);
|
||||
}
|
||||
|
||||
mesh->attributes.update(std::move(new_mesh.attributes));
|
||||
mesh->subd_attributes.update(std::move(new_mesh.subd_attributes));
|
||||
mesh->attributes.clear();
|
||||
foreach (Attribute &attr, new_mesh.attributes.attributes) {
|
||||
mesh->attributes.attributes.push_back(std::move(attr));
|
||||
}
|
||||
|
||||
mesh->subd_attributes.clear();
|
||||
foreach (Attribute &attr, new_mesh.subd_attributes.attributes) {
|
||||
mesh->subd_attributes.attributes.push_back(std::move(attr));
|
||||
}
|
||||
|
||||
mesh->set_num_subd_faces(new_mesh.get_num_subd_faces());
|
||||
|
||||
|
@@ -51,11 +51,10 @@ bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob)
|
||||
}
|
||||
else {
|
||||
/* object level material links */
|
||||
for (BL::MaterialSlot &b_slot : b_ob.material_slots) {
|
||||
if (b_slot.link() == BL::MaterialSlot::link_OBJECT) {
|
||||
BL::Object::material_slots_iterator slot;
|
||||
for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
|
||||
if (slot->link() == BL::MaterialSlot::link_OBJECT)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -244,6 +243,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
|
||||
/* holdout */
|
||||
object->set_use_holdout(use_holdout);
|
||||
if (object->use_holdout_is_modified()) {
|
||||
scene->object_manager->tag_update(scene);
|
||||
}
|
||||
|
||||
object->set_visibility(visibility);
|
||||
|
||||
|
@@ -57,7 +57,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
|
||||
|
||||
/* no update needed? */
|
||||
if (!need_update && !object->get_geometry()->is_modified() &&
|
||||
!scene->object_manager->need_update())
|
||||
!scene->object_manager->need_update)
|
||||
return true;
|
||||
|
||||
/* first time used in this sync loop? clear and tag update */
|
||||
@@ -85,7 +85,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
|
||||
object->set_particle_index(psys->particles.size() - 1);
|
||||
|
||||
if (object->particle_index_is_modified())
|
||||
scene->object_manager->tag_update(scene, ObjectManager::PARTICLE_MODIFIED);
|
||||
scene->object_manager->tag_update(scene);
|
||||
|
||||
/* return that this object has particle data */
|
||||
return true;
|
||||
|
@@ -597,19 +597,22 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
|
||||
bool removed;
|
||||
|
||||
do {
|
||||
BL::Node::inputs_iterator b_input;
|
||||
BL::Node::outputs_iterator b_output;
|
||||
|
||||
removed = false;
|
||||
|
||||
for (BL::NodeSocket &b_input : b_node.inputs) {
|
||||
if (used_sockets.find(b_input.ptr.data) == used_sockets.end()) {
|
||||
b_node.inputs.remove(b_data, b_input);
|
||||
for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
|
||||
if (used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
|
||||
b_node.inputs.remove(b_data, *b_input);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (BL::NodeSocket &b_output : b_node.outputs) {
|
||||
if (used_sockets.find(b_output.ptr.data) == used_sockets.end()) {
|
||||
b_node.outputs.remove(b_data, b_output);
|
||||
for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
|
||||
if (used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
|
||||
b_node.outputs.remove(b_data, *b_output);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
|
@@ -358,7 +358,11 @@ void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
|
||||
|
||||
if (do_read_only) {
|
||||
/* copy each pass */
|
||||
for (BL::RenderPass &b_pass : b_rlay.passes) {
|
||||
BL::RenderLayer::passes_iterator b_iter;
|
||||
|
||||
for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
|
||||
BL::RenderPass b_pass(*b_iter);
|
||||
|
||||
/* find matching pass type */
|
||||
PassType pass_type = BlenderSync::get_pass_type(b_pass);
|
||||
int components = b_pass.channels();
|
||||
@@ -548,6 +552,7 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
|
||||
int seed = scene->integrator->get_seed();
|
||||
seed += hash_uint2(seed, hash_uint2(view_index * 0xdeadbeef, 0));
|
||||
scene->integrator->set_seed(seed);
|
||||
scene->integrator->tag_update(scene);
|
||||
}
|
||||
|
||||
/* Update number of samples per layer. */
|
||||
@@ -731,7 +736,10 @@ void BlenderSession::do_write_update_render_result(BL::RenderLayer &b_rlay,
|
||||
|
||||
if (!do_update_only) {
|
||||
/* copy each pass */
|
||||
for (BL::RenderPass &b_pass : b_rlay.passes) {
|
||||
BL::RenderLayer::passes_iterator b_iter;
|
||||
|
||||
for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
|
||||
BL::RenderPass b_pass(*b_iter);
|
||||
int components = b_pass.channels();
|
||||
|
||||
/* Copy pixels from regular render passes. */
|
||||
@@ -1108,6 +1116,10 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
|
||||
|
||||
scene->integrator->set_start_sample(rounded_range_start_sample);
|
||||
|
||||
if (scene->integrator->is_modified()) {
|
||||
scene->integrator->tag_update(scene);
|
||||
}
|
||||
|
||||
session->tile_manager.range_start_sample = rounded_range_start_sample;
|
||||
session->tile_manager.range_num_samples = rounded_range_num_samples;
|
||||
}
|
||||
|
@@ -148,13 +148,15 @@ BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_r
|
||||
|
||||
static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name)
|
||||
{
|
||||
for (BL::NodeSocket &b_out : b_node.outputs) {
|
||||
if (b_out.name() == name) {
|
||||
return b_out;
|
||||
}
|
||||
}
|
||||
BL::Node::outputs_iterator b_out;
|
||||
|
||||
for (b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
|
||||
if (b_out->name() == name)
|
||||
return *b_out;
|
||||
|
||||
assert(0);
|
||||
return *b_node.outputs.begin();
|
||||
|
||||
return *b_out;
|
||||
}
|
||||
|
||||
static float3 get_node_output_rgba(BL::Node &b_node, const string &name)
|
||||
@@ -721,8 +723,9 @@ static ShaderNode *add_node(Scene *scene,
|
||||
image->set_alpha_type(get_image_alpha_type(b_image));
|
||||
|
||||
array<int> tiles;
|
||||
for (BL::UDIMTile &b_tile : b_image.tiles) {
|
||||
tiles.push_back_slow(b_tile.number());
|
||||
BL::Image::tiles_iterator b_iter;
|
||||
for (b_image.tiles.begin(b_iter); b_iter != b_image.tiles.end(); ++b_iter) {
|
||||
tiles.push_back_slow(b_iter->number());
|
||||
}
|
||||
image->set_tiles(tiles);
|
||||
|
||||
@@ -882,7 +885,7 @@ static ShaderNode *add_node(Scene *scene,
|
||||
sky->set_sun_intensity(b_sky_node.sun_intensity());
|
||||
sky->set_sun_elevation(b_sky_node.sun_elevation());
|
||||
sky->set_sun_rotation(b_sky_node.sun_rotation());
|
||||
sky->set_altitude(b_sky_node.altitude());
|
||||
sky->set_altitude(1000.0f * b_sky_node.altitude());
|
||||
sky->set_air_density(b_sky_node.air_density());
|
||||
sky->set_dust_density(b_sky_node.dust_density());
|
||||
sky->set_ozone_density(b_sky_node.ozone_density());
|
||||
@@ -1009,18 +1012,18 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node,
|
||||
string name = b_socket.name();
|
||||
|
||||
if (node_use_modified_socket_name(node)) {
|
||||
BL::Node::inputs_iterator b_input;
|
||||
bool found = false;
|
||||
int counter = 0, total = 0;
|
||||
|
||||
for (BL::NodeSocket &b_input : b_node.inputs) {
|
||||
if (b_input.name() == name) {
|
||||
if (!found) {
|
||||
for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
|
||||
if (b_input->name() == name) {
|
||||
if (!found)
|
||||
counter++;
|
||||
}
|
||||
total++;
|
||||
}
|
||||
|
||||
if (b_input.ptr.data == b_socket.ptr.data)
|
||||
if (b_input->ptr.data == b_socket.ptr.data)
|
||||
found = true;
|
||||
}
|
||||
|
||||
@@ -1042,20 +1045,19 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node,
|
||||
string name = b_socket.name();
|
||||
|
||||
if (node_use_modified_socket_name(node)) {
|
||||
BL::Node::outputs_iterator b_output;
|
||||
bool found = false;
|
||||
int counter = 0, total = 0;
|
||||
|
||||
for (BL::NodeSocket &b_output : b_node.outputs) {
|
||||
if (b_output.name() == name) {
|
||||
if (!found) {
|
||||
for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
|
||||
if (b_output->name() == name) {
|
||||
if (!found)
|
||||
counter++;
|
||||
}
|
||||
total++;
|
||||
}
|
||||
|
||||
if (b_output.ptr.data == b_socket.ptr.data) {
|
||||
if (b_output->ptr.data == b_socket.ptr.data)
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* rename if needed */
|
||||
@@ -1080,19 +1082,25 @@ static void add_nodes(Scene *scene,
|
||||
const ProxyMap &proxy_output_map)
|
||||
{
|
||||
/* add nodes */
|
||||
BL::ShaderNodeTree::nodes_iterator b_node;
|
||||
PtrInputMap input_map;
|
||||
PtrOutputMap output_map;
|
||||
|
||||
BL::Node::inputs_iterator b_input;
|
||||
BL::Node::outputs_iterator b_output;
|
||||
|
||||
/* find the node to use for output if there are multiple */
|
||||
BL::ShaderNode output_node = b_ntree.get_output_node(
|
||||
BL::ShaderNodeOutputMaterial::target_CYCLES);
|
||||
|
||||
/* add nodes */
|
||||
for (BL::Node &b_node : b_ntree.nodes) {
|
||||
if (b_node.mute() || b_node.is_a(&RNA_NodeReroute)) {
|
||||
for (b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
|
||||
if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
|
||||
/* replace muted node with internal links */
|
||||
for (BL::NodeLink &b_link : b_node.internal_links) {
|
||||
BL::NodeSocket to_socket(b_link.to_socket());
|
||||
BL::Node::internal_links_iterator b_link;
|
||||
for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end();
|
||||
++b_link) {
|
||||
BL::NodeSocket to_socket(b_link->to_socket());
|
||||
SocketType::Type to_socket_type = convert_socket_type(to_socket);
|
||||
if (to_socket_type == SocketType::UNDEFINED) {
|
||||
continue;
|
||||
@@ -1100,22 +1108,22 @@ static void add_nodes(Scene *scene,
|
||||
|
||||
ConvertNode *proxy = graph->create_node<ConvertNode>(to_socket_type, to_socket_type, true);
|
||||
|
||||
input_map[b_link.from_socket().ptr.data] = proxy->inputs[0];
|
||||
output_map[b_link.to_socket().ptr.data] = proxy->outputs[0];
|
||||
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
|
||||
output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
|
||||
|
||||
graph->add(proxy);
|
||||
}
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeGroup) || b_node.is_a(&RNA_NodeCustomGroup) ||
|
||||
b_node.is_a(&RNA_ShaderNodeCustomGroup)) {
|
||||
else if (b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup) ||
|
||||
b_node->is_a(&RNA_ShaderNodeCustomGroup)) {
|
||||
|
||||
BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL);
|
||||
if (b_node.is_a(&RNA_ShaderNodeGroup))
|
||||
b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(b_node)).node_tree());
|
||||
else if (b_node.is_a(&RNA_NodeCustomGroup))
|
||||
b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(b_node)).node_tree());
|
||||
if (b_node->is_a(&RNA_ShaderNodeGroup))
|
||||
b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree());
|
||||
else if (b_node->is_a(&RNA_NodeCustomGroup))
|
||||
b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree());
|
||||
else
|
||||
b_group_ntree = BL::ShaderNodeTree(((BL::ShaderNodeCustomGroup)(b_node)).node_tree());
|
||||
b_group_ntree = BL::ShaderNodeTree(((BL::ShaderNodeCustomGroup)(*b_node)).node_tree());
|
||||
|
||||
ProxyMap group_proxy_input_map, group_proxy_output_map;
|
||||
|
||||
@@ -1123,8 +1131,8 @@ static void add_nodes(Scene *scene,
|
||||
* Do this even if the node group has no internal tree,
|
||||
* so that links have something to connect to and assert won't fail.
|
||||
*/
|
||||
for (BL::NodeSocket &b_input : b_node.inputs) {
|
||||
SocketType::Type input_type = convert_socket_type(b_input);
|
||||
for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
||||
SocketType::Type input_type = convert_socket_type(*b_input);
|
||||
if (input_type == SocketType::UNDEFINED) {
|
||||
continue;
|
||||
}
|
||||
@@ -1133,14 +1141,14 @@ static void add_nodes(Scene *scene,
|
||||
graph->add(proxy);
|
||||
|
||||
/* register the proxy node for internal binding */
|
||||
group_proxy_input_map[b_input.identifier()] = proxy;
|
||||
group_proxy_input_map[b_input->identifier()] = proxy;
|
||||
|
||||
input_map[b_input.ptr.data] = proxy->inputs[0];
|
||||
input_map[b_input->ptr.data] = proxy->inputs[0];
|
||||
|
||||
set_default_value(proxy->inputs[0], b_input, b_data, b_ntree);
|
||||
set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
|
||||
}
|
||||
for (BL::NodeSocket &b_output : b_node.outputs) {
|
||||
SocketType::Type output_type = convert_socket_type(b_output);
|
||||
for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
||||
SocketType::Type output_type = convert_socket_type(*b_output);
|
||||
if (output_type == SocketType::UNDEFINED) {
|
||||
continue;
|
||||
}
|
||||
@@ -1149,9 +1157,9 @@ static void add_nodes(Scene *scene,
|
||||
graph->add(proxy);
|
||||
|
||||
/* register the proxy node for internal binding */
|
||||
group_proxy_output_map[b_output.identifier()] = proxy;
|
||||
group_proxy_output_map[b_output->identifier()] = proxy;
|
||||
|
||||
output_map[b_output.ptr.data] = proxy->outputs[0];
|
||||
output_map[b_output->ptr.data] = proxy->outputs[0];
|
||||
}
|
||||
|
||||
if (b_group_ntree) {
|
||||
@@ -1166,30 +1174,30 @@ static void add_nodes(Scene *scene,
|
||||
group_proxy_output_map);
|
||||
}
|
||||
}
|
||||
else if (b_node.is_a(&RNA_NodeGroupInput)) {
|
||||
else if (b_node->is_a(&RNA_NodeGroupInput)) {
|
||||
/* map each socket to a proxy node */
|
||||
for (BL::NodeSocket &b_output : b_node.outputs) {
|
||||
ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output.identifier());
|
||||
for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
||||
ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier());
|
||||
if (proxy_it != proxy_input_map.end()) {
|
||||
ConvertNode *proxy = proxy_it->second;
|
||||
|
||||
output_map[b_output.ptr.data] = proxy->outputs[0];
|
||||
output_map[b_output->ptr.data] = proxy->outputs[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (b_node.is_a(&RNA_NodeGroupOutput)) {
|
||||
BL::NodeGroupOutput b_output_node(b_node);
|
||||
else if (b_node->is_a(&RNA_NodeGroupOutput)) {
|
||||
BL::NodeGroupOutput b_output_node(*b_node);
|
||||
/* only the active group output is used */
|
||||
if (b_output_node.is_active_output()) {
|
||||
/* map each socket to a proxy node */
|
||||
for (BL::NodeSocket &b_input : b_node.inputs) {
|
||||
ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input.identifier());
|
||||
for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
||||
ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier());
|
||||
if (proxy_it != proxy_output_map.end()) {
|
||||
ConvertNode *proxy = proxy_it->second;
|
||||
|
||||
input_map[b_input.ptr.data] = proxy->inputs[0];
|
||||
input_map[b_input->ptr.data] = proxy->inputs[0];
|
||||
|
||||
set_default_value(proxy->inputs[0], b_input, b_data, b_ntree);
|
||||
set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1197,49 +1205,52 @@ static void add_nodes(Scene *scene,
|
||||
else {
|
||||
ShaderNode *node = NULL;
|
||||
|
||||
if (b_node.ptr.data == output_node.ptr.data) {
|
||||
if (b_node->ptr.data == output_node.ptr.data) {
|
||||
node = graph->output();
|
||||
}
|
||||
else {
|
||||
BL::ShaderNode b_shader_node(b_node);
|
||||
BL::ShaderNode b_shader_node(*b_node);
|
||||
node = add_node(
|
||||
scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree, b_shader_node);
|
||||
}
|
||||
|
||||
if (node) {
|
||||
/* map node sockets for linking */
|
||||
for (BL::NodeSocket &b_input : b_node.inputs) {
|
||||
ShaderInput *input = node_find_input_by_name(node, b_node, b_input);
|
||||
for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
|
||||
ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
|
||||
if (!input) {
|
||||
/* XXX should not happen, report error? */
|
||||
continue;
|
||||
}
|
||||
input_map[b_input.ptr.data] = input;
|
||||
input_map[b_input->ptr.data] = input;
|
||||
|
||||
set_default_value(input, b_input, b_data, b_ntree);
|
||||
set_default_value(input, *b_input, b_data, b_ntree);
|
||||
}
|
||||
for (BL::NodeSocket &b_output : b_node.outputs) {
|
||||
ShaderOutput *output = node_find_output_by_name(node, b_node, b_output);
|
||||
for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
|
||||
ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output);
|
||||
if (!output) {
|
||||
/* XXX should not happen, report error? */
|
||||
continue;
|
||||
}
|
||||
output_map[b_output.ptr.data] = output;
|
||||
output_map[b_output->ptr.data] = output;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* connect nodes */
|
||||
for (BL::NodeLink &b_link : b_ntree.links) {
|
||||
BL::NodeTree::links_iterator b_link;
|
||||
|
||||
for (b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
|
||||
/* Ignore invalid links to avoid unwanted cycles created in graph.
|
||||
* Also ignore links with unavailable sockets. */
|
||||
if (!(b_link.is_valid() && b_link.from_socket().enabled() && b_link.to_socket().enabled())) {
|
||||
if (!(b_link->is_valid() && b_link->from_socket().enabled() &&
|
||||
b_link->to_socket().enabled())) {
|
||||
continue;
|
||||
}
|
||||
/* get blender link data */
|
||||
BL::NodeSocket b_from_sock = b_link.from_socket();
|
||||
BL::NodeSocket b_to_sock = b_link.to_socket();
|
||||
BL::NodeSocket b_from_sock = b_link->from_socket();
|
||||
BL::NodeSocket b_to_sock = b_link->to_socket();
|
||||
|
||||
ShaderOutput *output = 0;
|
||||
ShaderInput *input = 0;
|
||||
@@ -1287,12 +1298,13 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
TaskPool pool;
|
||||
set<Shader *> updated_shaders;
|
||||
|
||||
for (BL::ID &b_id : b_depsgraph.ids) {
|
||||
if (!b_id.is_a(&RNA_Material)) {
|
||||
BL::Depsgraph::ids_iterator b_id;
|
||||
for (b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
|
||||
if (!b_id->is_a(&RNA_Material)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BL::Material b_mat(b_id);
|
||||
BL::Material b_mat(*b_id);
|
||||
Shader *shader;
|
||||
|
||||
/* test if we need to sync */
|
||||
@@ -1485,6 +1497,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
|
||||
shader->set_graph(graph);
|
||||
shader->tag_update(scene);
|
||||
background->tag_update(scene);
|
||||
}
|
||||
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
@@ -1504,7 +1517,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
viewport_parameters.custom_viewport_parameters());
|
||||
background->set_use_ao(background->get_use_ao() && view_layer.use_background_ao);
|
||||
|
||||
background->tag_update(scene);
|
||||
if (background->is_modified())
|
||||
background->tag_update(scene);
|
||||
}
|
||||
|
||||
/* Sync Lights */
|
||||
@@ -1513,12 +1527,13 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
{
|
||||
shader_map.set_default(scene->default_light);
|
||||
|
||||
for (BL::ID &b_id : b_depsgraph.ids) {
|
||||
if (!b_id.is_a(&RNA_Light)) {
|
||||
BL::Depsgraph::ids_iterator b_id;
|
||||
for (b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
|
||||
if (!b_id->is_a(&RNA_Light)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BL::Light b_light(b_id);
|
||||
BL::Light b_light(*b_id);
|
||||
Shader *shader;
|
||||
|
||||
/* test if we need to sync */
|
||||
|
@@ -24,7 +24,6 @@
|
||||
#include "render/mesh.h"
|
||||
#include "render/nodes.h"
|
||||
#include "render/object.h"
|
||||
#include "render/procedural.h"
|
||||
#include "render/scene.h"
|
||||
#include "render/shader.h"
|
||||
|
||||
@@ -132,8 +131,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
}
|
||||
|
||||
/* Iterate over all IDs in this depsgraph. */
|
||||
for (BL::DepsgraphUpdate &b_update : b_depsgraph.updates) {
|
||||
BL::ID b_id(b_update.id());
|
||||
BL::Depsgraph::updates_iterator b_update;
|
||||
for (b_depsgraph.updates.begin(b_update); b_update != b_depsgraph.updates.end(); ++b_update) {
|
||||
BL::ID b_id(b_update->id());
|
||||
|
||||
/* Material */
|
||||
if (b_id.is_a(&RNA_Material)) {
|
||||
@@ -151,17 +151,17 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
const bool is_geometry = object_is_geometry(b_ob);
|
||||
const bool is_light = !is_geometry && object_is_light(b_ob);
|
||||
|
||||
if (b_ob.is_instancer() && b_update.is_updated_shading()) {
|
||||
if (b_ob.is_instancer() && b_update->is_updated_shading()) {
|
||||
/* Needed for e.g. object color updates on instancer. */
|
||||
object_map.set_recalc(b_ob);
|
||||
}
|
||||
|
||||
if (is_geometry || is_light) {
|
||||
const bool updated_geometry = b_update.is_updated_geometry();
|
||||
const bool updated_geometry = b_update->is_updated_geometry();
|
||||
|
||||
/* Geometry (mesh, hair, volume). */
|
||||
if (is_geometry) {
|
||||
if (b_update.is_updated_transform() || b_update.is_updated_shading()) {
|
||||
if (b_update->is_updated_transform() || b_update->is_updated_shading()) {
|
||||
object_map.set_recalc(b_ob);
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
}
|
||||
/* Light */
|
||||
else if (is_light) {
|
||||
if (b_update.is_updated_transform() || b_update.is_updated_shading()) {
|
||||
if (b_update->is_updated_transform() || b_update->is_updated_shading()) {
|
||||
object_map.set_recalc(b_ob);
|
||||
light_map.set_recalc(b_ob);
|
||||
}
|
||||
@@ -302,6 +302,11 @@ void BlenderSync::sync_integrator()
|
||||
integrator->set_sample_clamp_direct(get_float(cscene, "sample_clamp_direct"));
|
||||
integrator->set_sample_clamp_indirect(get_float(cscene, "sample_clamp_indirect"));
|
||||
if (!preview) {
|
||||
if (integrator->get_motion_blur() != r.use_motion_blur()) {
|
||||
scene->object_manager->tag_update(scene);
|
||||
scene->camera->tag_modified();
|
||||
}
|
||||
|
||||
integrator->set_motion_blur(r.use_motion_blur());
|
||||
}
|
||||
|
||||
@@ -370,8 +375,8 @@ void BlenderSync::sync_integrator()
|
||||
integrator->set_ao_bounces(0);
|
||||
}
|
||||
|
||||
/* UPDATE_NONE as we don't want to tag the integrator as modified, just tag dependent things */
|
||||
integrator->tag_update(scene, Integrator::UPDATE_NONE);
|
||||
if (integrator->is_modified())
|
||||
integrator->tag_update(scene);
|
||||
}
|
||||
|
||||
/* Film */
|
||||
@@ -466,15 +471,16 @@ void BlenderSync::sync_images()
|
||||
return;
|
||||
}
|
||||
/* Free buffers used by images which are not needed for render. */
|
||||
for (BL::Image &b_image : b_data.images) {
|
||||
BL::BlendData::images_iterator b_image;
|
||||
for (b_data.images.begin(b_image); b_image != b_data.images.end(); ++b_image) {
|
||||
/* TODO(sergey): Consider making it an utility function to check
|
||||
* whether image is considered builtin.
|
||||
*/
|
||||
const bool is_builtin = b_image.packed_file() ||
|
||||
b_image.source() == BL::Image::source_GENERATED ||
|
||||
b_image.source() == BL::Image::source_MOVIE || b_engine.is_preview();
|
||||
const bool is_builtin = b_image->packed_file() ||
|
||||
b_image->source() == BL::Image::source_GENERATED ||
|
||||
b_image->source() == BL::Image::source_MOVIE || b_engine.is_preview();
|
||||
if (is_builtin == false) {
|
||||
b_image.buffers_free();
|
||||
b_image->buffers_free();
|
||||
}
|
||||
/* TODO(sergey): Free builtin images not used by any shader. */
|
||||
}
|
||||
@@ -575,7 +581,10 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
|
||||
vector<Pass> passes;
|
||||
|
||||
/* loop over passes */
|
||||
for (BL::RenderPass &b_pass : b_rlay.passes) {
|
||||
BL::RenderLayer::passes_iterator b_pass_iter;
|
||||
|
||||
for (b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
|
||||
BL::RenderPass b_pass(*b_pass_iter);
|
||||
PassType pass_type = get_pass_type(b_pass);
|
||||
|
||||
if (pass_type == PASS_MOTION && scene->integrator->get_motion_blur())
|
||||
@@ -720,7 +729,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay,
|
||||
|
||||
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
|
||||
scene->film->tag_passes_update(scene, passes);
|
||||
scene->integrator->tag_update(scene, Integrator::UPDATE_ALL);
|
||||
scene->integrator->tag_update(scene);
|
||||
|
||||
return passes;
|
||||
}
|
||||
@@ -743,8 +752,9 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
|
||||
/* TODO(sergey): We can actually remove the whole dependency graph,
|
||||
* but that will need some API support first.
|
||||
*/
|
||||
for (BL::Object &b_ob : b_depsgraph.objects) {
|
||||
b_ob.cache_release();
|
||||
BL::Depsgraph::objects_iterator b_ob;
|
||||
for (b_depsgraph.objects.begin(b_ob); b_ob != b_depsgraph.objects.end(); ++b_ob) {
|
||||
b_ob->cache_release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -134,7 +134,6 @@ class BlenderSync {
|
||||
void sync_view();
|
||||
|
||||
/* Shader */
|
||||
array<Node *> find_used_shaders(BL::Object &b_ob);
|
||||
void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
|
||||
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d);
|
||||
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
|
||||
|
@@ -538,9 +538,11 @@ static inline bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_
|
||||
|
||||
static inline BL::FluidDomainSettings object_fluid_liquid_domain_find(BL::Object &b_ob)
|
||||
{
|
||||
for (BL::Modifier &b_mod : b_ob.modifiers) {
|
||||
if (b_mod.is_a(&RNA_FluidModifier)) {
|
||||
BL::FluidModifier b_mmd(b_mod);
|
||||
BL::Object::modifiers_iterator b_mod;
|
||||
|
||||
for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
|
||||
if (b_mod->is_a(&RNA_FluidModifier)) {
|
||||
BL::FluidModifier b_mmd(*b_mod);
|
||||
|
||||
if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN &&
|
||||
b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_LIQUID) {
|
||||
@@ -554,9 +556,11 @@ static inline BL::FluidDomainSettings object_fluid_liquid_domain_find(BL::Object
|
||||
|
||||
static inline BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob)
|
||||
{
|
||||
for (BL::Modifier &b_mod : b_ob.modifiers) {
|
||||
if (b_mod.is_a(&RNA_FluidModifier)) {
|
||||
BL::FluidModifier b_mmd(b_mod);
|
||||
BL::Object::modifiers_iterator b_mod;
|
||||
|
||||
for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
|
||||
if (b_mod->is_a(&RNA_FluidModifier)) {
|
||||
BL::FluidModifier b_mmd(*b_mod);
|
||||
|
||||
if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN &&
|
||||
b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_GAS) {
|
||||
|
@@ -222,7 +222,9 @@ class BlenderVolumeLoader : public VDBImageLoader {
|
||||
b_volume.grids.load(b_data.ptr.data);
|
||||
|
||||
#ifdef WITH_OPENVDB
|
||||
for (BL::VolumeGrid &b_volume_grid : b_volume.grids) {
|
||||
BL::Volume::grids_iterator b_grid_iter;
|
||||
for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) {
|
||||
BL::VolumeGrid b_volume_grid(*b_grid_iter);
|
||||
if (b_volume_grid.name() == grid_name) {
|
||||
const bool unload = !b_volume_grid.is_loaded();
|
||||
|
||||
@@ -258,7 +260,9 @@ static void sync_volume_object(BL::BlendData &b_data,
|
||||
volume->set_object_space((b_render.space() == BL::VolumeRender::space_OBJECT));
|
||||
|
||||
/* Find grid with matching name. */
|
||||
for (BL::VolumeGrid &b_grid : b_volume.grids) {
|
||||
BL::Volume::grids_iterator b_grid_iter;
|
||||
for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) {
|
||||
BL::VolumeGrid b_grid = *b_grid_iter;
|
||||
ustring name = ustring(b_grid.name());
|
||||
AttributeStandard std = ATTR_STD_NONE;
|
||||
|
||||
|
@@ -259,8 +259,6 @@ class device_memory {
|
||||
device_ptr original_device_ptr;
|
||||
size_t original_device_size;
|
||||
Device *original_device;
|
||||
bool need_realloc_;
|
||||
bool modified;
|
||||
};
|
||||
|
||||
/* Device Only Memory
|
||||
@@ -331,8 +329,6 @@ template<typename T> class device_vector : public device_memory {
|
||||
{
|
||||
data_type = device_type_traits<T>::data_type;
|
||||
data_elements = device_type_traits<T>::num_elements;
|
||||
modified = true;
|
||||
need_realloc_ = true;
|
||||
|
||||
assert(data_elements > 0);
|
||||
}
|
||||
@@ -351,7 +347,6 @@ template<typename T> class device_vector : public device_memory {
|
||||
device_free();
|
||||
host_free();
|
||||
host_pointer = host_alloc(sizeof(T) * new_size);
|
||||
modified = true;
|
||||
assert(device_pointer == 0);
|
||||
}
|
||||
|
||||
@@ -405,19 +400,6 @@ template<typename T> class device_vector : public device_memory {
|
||||
assert(device_pointer == 0);
|
||||
}
|
||||
|
||||
void give_data(array<T> &to)
|
||||
{
|
||||
device_free();
|
||||
|
||||
to.set_data((T *)host_pointer, data_size);
|
||||
data_size = 0;
|
||||
data_width = 0;
|
||||
data_height = 0;
|
||||
data_depth = 0;
|
||||
host_pointer = 0;
|
||||
assert(device_pointer == 0);
|
||||
}
|
||||
|
||||
/* Free device and host memory. */
|
||||
void free()
|
||||
{
|
||||
@@ -429,40 +411,10 @@ template<typename T> class device_vector : public device_memory {
|
||||
data_height = 0;
|
||||
data_depth = 0;
|
||||
host_pointer = 0;
|
||||
modified = true;
|
||||
need_realloc_ = true;
|
||||
assert(device_pointer == 0);
|
||||
}
|
||||
|
||||
void free_if_need_realloc(bool force_free)
|
||||
{
|
||||
if (need_realloc_ || force_free) {
|
||||
free();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_modified() const
|
||||
{
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool need_realloc()
|
||||
{
|
||||
return need_realloc_;
|
||||
}
|
||||
|
||||
void tag_modified()
|
||||
{
|
||||
modified = true;
|
||||
}
|
||||
|
||||
void tag_realloc()
|
||||
{
|
||||
need_realloc_ = true;
|
||||
tag_modified();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
size_t size()
|
||||
{
|
||||
return data_size;
|
||||
}
|
||||
@@ -480,24 +432,7 @@ template<typename T> class device_vector : public device_memory {
|
||||
|
||||
void copy_to_device()
|
||||
{
|
||||
if (data_size != 0) {
|
||||
device_copy_to();
|
||||
}
|
||||
}
|
||||
|
||||
void copy_to_device_if_modified()
|
||||
{
|
||||
if (!modified) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy_to_device();
|
||||
}
|
||||
|
||||
void clear_modified()
|
||||
{
|
||||
modified = false;
|
||||
need_realloc_ = false;
|
||||
device_copy_to();
|
||||
}
|
||||
|
||||
void copy_from_device()
|
||||
|
@@ -18,7 +18,7 @@
|
||||
/* Data type to replace `double` used in the NanoVDB headers. Cycles don't need doubles, and is
|
||||
* safer and more portable to never use double datatype on GPU.
|
||||
* Use a special structure, so that the following is true:
|
||||
* - No unnoticed implicit cast or mathematical operations used on scalar 64bit type
|
||||
* - No unnoticed implicit cast or mathermatical operations used on scalar 64bit type
|
||||
* (which rules out trick like using `uint64_t` as a drop-in replacement for double).
|
||||
* - Padding rules are matching exactly `double`
|
||||
* (which rules out array of `uint8_t`). */
|
||||
|
@@ -43,7 +43,7 @@ class ColorSpaceProcessor;
|
||||
*
|
||||
* Data needed by OSL render services, that is global to a rendering session.
|
||||
* This includes all OSL shaders, name to attribute mapping and texture handles.
|
||||
*/
|
||||
* */
|
||||
|
||||
struct OSLGlobals {
|
||||
OSLGlobals()
|
||||
|
@@ -23,7 +23,6 @@ set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
alembic.cpp
|
||||
attribute.cpp
|
||||
background.cpp
|
||||
bake.cpp
|
||||
@@ -49,7 +48,6 @@ set(SRC
|
||||
mesh_displace.cpp
|
||||
mesh_subdivision.cpp
|
||||
nodes.cpp
|
||||
procedural.cpp
|
||||
object.cpp
|
||||
osl.cpp
|
||||
particles.cpp
|
||||
@@ -66,7 +64,6 @@ set(SRC
|
||||
)
|
||||
|
||||
set(SRC_HEADERS
|
||||
alembic.h
|
||||
attribute.h
|
||||
bake.h
|
||||
background.h
|
||||
@@ -93,7 +90,6 @@ set(SRC_HEADERS
|
||||
object.h
|
||||
osl.h
|
||||
particles.h
|
||||
procedural.h
|
||||
curves.h
|
||||
scene.h
|
||||
session.h
|
||||
@@ -148,16 +144,6 @@ if(WITH_OPENVDB)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
add_definitions(-DWITH_ALEMBIC)
|
||||
list(APPEND INC_SYS
|
||||
${ALEMBIC_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND LIB
|
||||
${ALEMBIC_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_NANOVDB)
|
||||
list(APPEND INC_SYS
|
||||
${NANOVDB_INCLUDE_DIRS}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,404 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2018 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "graph/node.h"
|
||||
#include "render/attribute.h"
|
||||
#include "render/procedural.h"
|
||||
#include "util/util_set.h"
|
||||
#include "util/util_transform.h"
|
||||
#include "util/util_vector.h"
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
|
||||
# include <Alembic/AbcCoreFactory/All.h>
|
||||
# include <Alembic/AbcGeom/All.h>
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class AlembicProcedural;
|
||||
class Geometry;
|
||||
class Object;
|
||||
class Progress;
|
||||
class Shader;
|
||||
|
||||
using MatrixSampleMap = std::map<Alembic::Abc::chrono_t, Alembic::Abc::M44d>;
|
||||
|
||||
/* Helpers to detect if some type is a ccl::array. */
|
||||
template<typename> struct is_array : public std::false_type {
|
||||
};
|
||||
|
||||
template<typename T> struct is_array<array<T>> : public std::true_type {
|
||||
};
|
||||
|
||||
/* Store the data set for an animation at every time points, or at the beginning of the animation
|
||||
* for constant data.
|
||||
*
|
||||
* The data is supposed to be stored in chronological order, and is looked up using the current
|
||||
* animation time in seconds using the TimeSampling from the Alembic property. */
|
||||
template<typename T> class DataStore {
|
||||
struct DataTimePair {
|
||||
double time = 0;
|
||||
T data{};
|
||||
};
|
||||
|
||||
vector<DataTimePair> data{};
|
||||
Alembic::AbcCoreAbstract::TimeSampling time_sampling{};
|
||||
|
||||
double last_loaded_time = std::numeric_limits<double>::max();
|
||||
|
||||
public:
|
||||
void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling_)
|
||||
{
|
||||
time_sampling = time_sampling_;
|
||||
}
|
||||
|
||||
Alembic::AbcCoreAbstract::TimeSampling get_time_sampling() const
|
||||
{
|
||||
return time_sampling;
|
||||
}
|
||||
|
||||
/* Get the data for the specified time.
|
||||
* Return nullptr if there is no data or if the data for this time was already loaded. */
|
||||
T *data_for_time(double time)
|
||||
{
|
||||
if (size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<size_t, Alembic::Abc::chrono_t> index_pair;
|
||||
index_pair = time_sampling.getNearIndex(time, data.size());
|
||||
DataTimePair &data_pair = data[index_pair.first];
|
||||
|
||||
if (last_loaded_time == data_pair.time) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
last_loaded_time = data_pair.time;
|
||||
|
||||
return &data_pair.data;
|
||||
}
|
||||
|
||||
/* get the data for the specified time, but do not check if the data was already loaded for this
|
||||
* time return nullptr if there is no data */
|
||||
T *data_for_time_no_check(double time)
|
||||
{
|
||||
if (size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<size_t, Alembic::Abc::chrono_t> index_pair;
|
||||
index_pair = time_sampling.getNearIndex(time, data.size());
|
||||
DataTimePair &data_pair = data[index_pair.first];
|
||||
return &data_pair.data;
|
||||
}
|
||||
|
||||
void add_data(T &data_, double time)
|
||||
{
|
||||
if constexpr (is_array<T>::value) {
|
||||
data.emplace_back();
|
||||
data.back().data.steal_data(data_);
|
||||
data.back().time = time;
|
||||
return;
|
||||
}
|
||||
|
||||
data.push_back({time, data_});
|
||||
}
|
||||
|
||||
bool is_constant() const
|
||||
{
|
||||
return data.size() <= 1;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return data.size();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
invalidate_last_loaded_time();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void invalidate_last_loaded_time()
|
||||
{
|
||||
last_loaded_time = std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
/* Copy the data for the specified time to the node's socket. If there is no
|
||||
* data for this time or it was already loaded, do nothing. */
|
||||
void copy_to_socket(double time, Node *node, const SocketType *socket)
|
||||
{
|
||||
T *data_ = data_for_time(time);
|
||||
|
||||
if (data_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO(kevindietrich): arrays are emptied when passed to the sockets, so for now we copy the
|
||||
* arrays to avoid reloading the data */
|
||||
T value = *data_;
|
||||
node->set(*socket, value);
|
||||
}
|
||||
};
|
||||
|
||||
/* Actual cache for the stored data.
|
||||
* This caches the topological, transformation, and attribute data for a Mesh node or a Hair node
|
||||
* inside of DataStores.
|
||||
*/
|
||||
struct CachedData {
|
||||
DataStore<Transform> transforms{};
|
||||
|
||||
/* mesh data */
|
||||
DataStore<array<float3>> vertices;
|
||||
DataStore<array<int3>> triangles{};
|
||||
/* triangle "loops" are the polygons' vertices indices used for indexing face varying attributes
|
||||
* (like UVs) */
|
||||
DataStore<array<int3>> triangles_loops{};
|
||||
DataStore<array<int>> shader{};
|
||||
|
||||
/* subd data */
|
||||
DataStore<array<int>> subd_start_corner;
|
||||
DataStore<array<int>> subd_num_corners;
|
||||
DataStore<array<bool>> subd_smooth;
|
||||
DataStore<array<int>> subd_ptex_offset;
|
||||
DataStore<array<int>> subd_face_corners;
|
||||
DataStore<int> num_ngons;
|
||||
DataStore<array<int>> subd_creases_edge;
|
||||
DataStore<array<float>> subd_creases_weight;
|
||||
|
||||
/* hair data */
|
||||
DataStore<array<float3>> curve_keys;
|
||||
DataStore<array<float>> curve_radius;
|
||||
DataStore<array<int>> curve_first_key;
|
||||
DataStore<array<int>> curve_shader;
|
||||
|
||||
struct CachedAttribute {
|
||||
AttributeStandard std;
|
||||
AttributeElement element;
|
||||
TypeDesc type_desc;
|
||||
ustring name;
|
||||
DataStore<array<char>> data{};
|
||||
};
|
||||
|
||||
vector<CachedAttribute> attributes{};
|
||||
|
||||
void clear();
|
||||
|
||||
CachedAttribute &add_attribute(const ustring &name,
|
||||
const Alembic::Abc::TimeSampling &time_sampling);
|
||||
|
||||
bool is_constant() const;
|
||||
|
||||
void invalidate_last_loaded_time(bool attributes_only = false);
|
||||
|
||||
void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling);
|
||||
};
|
||||
|
||||
/* Representation of an Alembic object for the AlembicProcedural.
|
||||
*
|
||||
* The AlembicObject holds the path to the Alembic IObject inside of the archive that is desired
|
||||
* for rendering, as well as the list of shaders that it is using.
|
||||
*
|
||||
* The names of the shaders should correspond to the names of the FaceSets inside of the Alembic
|
||||
* archive for per-triangle shader association. If there is no FaceSets, or the names do not
|
||||
* match, the first shader is used for rendering for all triangles.
|
||||
*/
|
||||
class AlembicObject : public Node {
|
||||
public:
|
||||
NODE_DECLARE
|
||||
|
||||
/* Path to the IObject inside of the archive. */
|
||||
NODE_SOCKET_API(ustring, path)
|
||||
|
||||
/* Shaders used for rendering. */
|
||||
NODE_SOCKET_API_ARRAY(array<Node *>, used_shaders)
|
||||
|
||||
/* Maximum number of subdivisions for ISubD objects. */
|
||||
NODE_SOCKET_API(int, subd_max_level)
|
||||
|
||||
/* Finest level of detail (in pixels) for the subdivision. */
|
||||
NODE_SOCKET_API(float, subd_dicing_rate)
|
||||
|
||||
/* Scale the radius of points and curves. */
|
||||
NODE_SOCKET_API(float, radius_scale)
|
||||
|
||||
AlembicObject();
|
||||
~AlembicObject();
|
||||
|
||||
private:
|
||||
friend class AlembicProcedural;
|
||||
|
||||
void set_object(Object *object);
|
||||
Object *get_object();
|
||||
|
||||
void load_all_data(AlembicProcedural *proc,
|
||||
Alembic::AbcGeom::IPolyMeshSchema &schema,
|
||||
float scale,
|
||||
Progress &progress);
|
||||
void load_all_data(AlembicProcedural *proc,
|
||||
Alembic::AbcGeom::ISubDSchema &schema,
|
||||
float scale,
|
||||
Progress &progress);
|
||||
void load_all_data(AlembicProcedural *proc,
|
||||
const Alembic::AbcGeom::ICurvesSchema &schema,
|
||||
float scale,
|
||||
Progress &progress,
|
||||
float default_radius);
|
||||
|
||||
bool has_data_loaded() const;
|
||||
|
||||
bool need_shader_update = true;
|
||||
|
||||
MatrixSampleMap xform_samples;
|
||||
Alembic::AbcGeom::IObject iobject;
|
||||
Transform xform;
|
||||
|
||||
CachedData &get_cached_data()
|
||||
{
|
||||
return cached_data;
|
||||
}
|
||||
|
||||
bool is_constant() const
|
||||
{
|
||||
return cached_data.is_constant();
|
||||
}
|
||||
|
||||
Object *object = nullptr;
|
||||
|
||||
bool data_loaded = false;
|
||||
|
||||
CachedData cached_data;
|
||||
|
||||
void update_shader_attributes(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params,
|
||||
Progress &progress);
|
||||
|
||||
void read_attribute(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params,
|
||||
const ustring &attr_name,
|
||||
Progress &progress);
|
||||
|
||||
template<typename SchemaType>
|
||||
void read_face_sets(SchemaType &schema,
|
||||
array<int> &polygon_to_shader,
|
||||
Alembic::AbcGeom::ISampleSelector sample_sel);
|
||||
|
||||
void setup_transform_cache(float scale);
|
||||
|
||||
AttributeRequestSet get_requested_attributes();
|
||||
};
|
||||
|
||||
/* Procedural to render objects from a single Alembic archive.
|
||||
*
|
||||
* Every object desired to be rendered should be passed as an AlembicObject through the objects
|
||||
* socket.
|
||||
*
|
||||
* This procedural will load the data set for the entire animation in memory on the first frame,
|
||||
* and directly set the data for the new frames on the created Nodes if needed. This allows for
|
||||
* faster updates between frames as it avoids reseeking the data on disk.
|
||||
*/
|
||||
class AlembicProcedural : public Procedural {
|
||||
Alembic::AbcGeom::IArchive archive;
|
||||
bool objects_loaded;
|
||||
Scene *scene_;
|
||||
|
||||
public:
|
||||
NODE_DECLARE
|
||||
|
||||
/* The file path to the Alembic archive */
|
||||
NODE_SOCKET_API(ustring, filepath)
|
||||
|
||||
/* The current frame to render. */
|
||||
NODE_SOCKET_API(float, frame)
|
||||
|
||||
/* The first frame to load data for. */
|
||||
NODE_SOCKET_API(float, start_frame)
|
||||
|
||||
/* The last frame to load data for. */
|
||||
NODE_SOCKET_API(float, end_frame)
|
||||
|
||||
/* Subtracted to the current frame. */
|
||||
NODE_SOCKET_API(float, frame_offset)
|
||||
|
||||
/* The frame rate used for rendering in units of frames per second. */
|
||||
NODE_SOCKET_API(float, frame_rate)
|
||||
|
||||
/* List of AlembicObjects to render. */
|
||||
NODE_SOCKET_API_ARRAY(array<Node *>, objects)
|
||||
|
||||
/* Set the default radius to use for curves when the Alembic Curves Schemas do not have radius
|
||||
* information. */
|
||||
NODE_SOCKET_API(float, default_radius)
|
||||
|
||||
/* Multiplier to account for differences in default units for measuring objects in various
|
||||
* software. */
|
||||
NODE_SOCKET_API(float, scale)
|
||||
|
||||
AlembicProcedural();
|
||||
~AlembicProcedural();
|
||||
|
||||
/* Populates the Cycles scene with Nodes for every contained AlembicObject on the first
|
||||
* invocation, and updates the data on subsequent invocations if the frame changed. */
|
||||
void generate(Scene *scene, Progress &progress);
|
||||
|
||||
/* Add an object to our list of objects, and tag the socket as modified. */
|
||||
void add_object(AlembicObject *object);
|
||||
|
||||
/* Tag for an update only if something was modified. */
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
/* Returns a pointer to an exisiting or a newly created AlembicObject for the given path. */
|
||||
AlembicObject *get_or_create_object(const ustring &path);
|
||||
|
||||
private:
|
||||
/* Load the data for all the objects whose data has not yet been loaded. */
|
||||
void load_objects(Progress &progress);
|
||||
|
||||
/* Traverse the Alembic hierarchy to lookup the IObjects for the AlembicObjects that were
|
||||
* specified in our objects socket, and accumulate all of the transformations samples along the
|
||||
* way for each IObject. */
|
||||
void walk_hierarchy(Alembic::AbcGeom::IObject parent,
|
||||
const Alembic::AbcGeom::ObjectHeader &ohead,
|
||||
MatrixSampleMap *xform_samples,
|
||||
const unordered_map<string, AlembicObject *> &object_map,
|
||||
Progress &progress);
|
||||
|
||||
/* Read the data for an IPolyMesh at the specified frame_time. Creates corresponding Geometry and
|
||||
* Object Nodes in the Cycles scene if none exist yet. */
|
||||
void read_mesh(Scene *scene,
|
||||
AlembicObject *abc_object,
|
||||
Alembic::AbcGeom::Abc::chrono_t frame_time,
|
||||
Progress &progress);
|
||||
|
||||
/* Read the data for an ICurves at the specified frame_time. Creates corresponding Geometry and
|
||||
* Object Nodes in the Cycles scene if none exist yet. */
|
||||
void read_curves(Scene *scene,
|
||||
AlembicObject *abc_object,
|
||||
Alembic::AbcGeom::Abc::chrono_t frame_time,
|
||||
Progress &progress);
|
||||
|
||||
/* Read the data for an ISubD at the specified frame_time. Creates corresponding Geometry and
|
||||
* Object Nodes in the Cycles scene if none exist yet. */
|
||||
void read_subd(Scene *scene,
|
||||
AlembicObject *abc_object,
|
||||
Alembic::AbcGeom::Abc::chrono_t frame_time,
|
||||
Progress &progress);
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif
|
@@ -28,7 +28,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
Attribute::Attribute(
|
||||
ustring name, TypeDesc type, AttributeElement element, Geometry *geom, AttributePrimitive prim)
|
||||
: name(name), std(ATTR_STD_NONE), type(type), element(element), flags(0), modified(true)
|
||||
: name(name), std(ATTR_STD_NONE), type(type), element(element), flags(0)
|
||||
{
|
||||
/* string and matrix not supported! */
|
||||
assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
|
||||
@@ -82,8 +82,6 @@ void Attribute::add(const float &f)
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buffer.push_back(data[i]);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
void Attribute::add(const uchar4 &f)
|
||||
@@ -95,8 +93,6 @@ void Attribute::add(const uchar4 &f)
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buffer.push_back(data[i]);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
void Attribute::add(const float2 &f)
|
||||
@@ -108,8 +104,6 @@ void Attribute::add(const float2 &f)
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buffer.push_back(data[i]);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
void Attribute::add(const float3 &f)
|
||||
@@ -121,8 +115,6 @@ void Attribute::add(const float3 &f)
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buffer.push_back(data[i]);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
void Attribute::add(const Transform &f)
|
||||
@@ -134,8 +126,6 @@ void Attribute::add(const Transform &f)
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buffer.push_back(data[i]);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
void Attribute::add(const char *data)
|
||||
@@ -144,26 +134,6 @@ void Attribute::add(const char *data)
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
buffer.push_back(data[i]);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
void Attribute::set_data_from(Attribute &&other)
|
||||
{
|
||||
assert(other.std == std);
|
||||
assert(other.type == type);
|
||||
assert(other.element == element);
|
||||
|
||||
this->flags = other.flags;
|
||||
|
||||
if (this->buffer.size() != other.buffer.size()) {
|
||||
this->buffer = std::move(other.buffer);
|
||||
modified = true;
|
||||
}
|
||||
else if (memcmp(this->data(), other.data(), other.buffer.size()) != 0) {
|
||||
this->buffer = std::move(other.buffer);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Attribute::data_sizeof() const
|
||||
@@ -657,42 +627,6 @@ void AttributeSet::clear(bool preserve_voxel_data)
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeSet::update(AttributeSet &&new_attributes)
|
||||
{
|
||||
/* add or update old_attributes based on the new_attributes */
|
||||
foreach (Attribute &attr, new_attributes.attributes) {
|
||||
Attribute *nattr = add(attr.name, attr.type, attr.element);
|
||||
nattr->std = attr.std;
|
||||
nattr->set_data_from(std::move(attr));
|
||||
}
|
||||
|
||||
/* remove any attributes not on new_attributes */
|
||||
list<Attribute>::iterator it;
|
||||
for (it = attributes.begin(); it != attributes.end();) {
|
||||
if (it->std != ATTR_STD_NONE) {
|
||||
if (new_attributes.find(it->std) == nullptr) {
|
||||
attributes.erase(it++);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (it->name != "") {
|
||||
if (new_attributes.find(it->name) == nullptr) {
|
||||
attributes.erase(it++);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeSet::clear_modified()
|
||||
{
|
||||
foreach (Attribute &attr, attributes) {
|
||||
attr.modified = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* AttributeRequest */
|
||||
|
||||
AttributeRequest::AttributeRequest(ustring name_)
|
||||
|
@@ -54,8 +54,6 @@ class Attribute {
|
||||
AttributeElement element;
|
||||
uint flags; /* enum AttributeFlag */
|
||||
|
||||
bool modified;
|
||||
|
||||
Attribute(ustring name,
|
||||
TypeDesc type,
|
||||
AttributeElement element,
|
||||
@@ -161,8 +159,6 @@ class Attribute {
|
||||
void add(const Transform &tfm);
|
||||
void add(const char *data);
|
||||
|
||||
void set_data_from(Attribute &&other);
|
||||
|
||||
static bool same_storage(TypeDesc a, TypeDesc b);
|
||||
static const char *standard_name(AttributeStandard std);
|
||||
static AttributeStandard name_standard(const char *name);
|
||||
@@ -198,12 +194,6 @@ class AttributeSet {
|
||||
|
||||
void resize(bool reserve_only = false);
|
||||
void clear(bool preserve_voxel_data = false);
|
||||
|
||||
/* Update the attributes in this AttributeSet with the ones from the new set,
|
||||
* and remove any attribute not found on the new set from this. */
|
||||
void update(AttributeSet &&new_attributes);
|
||||
|
||||
void clear_modified();
|
||||
};
|
||||
|
||||
/* AttributeRequest
|
||||
|
@@ -130,9 +130,8 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
|
||||
|
||||
void Background::tag_update(Scene *scene)
|
||||
{
|
||||
if (ao_factor_is_modified() || use_ao_is_modified()) {
|
||||
scene->integrator->tag_update(scene, Integrator::BACKGROUND_AO_MODIFIED);
|
||||
}
|
||||
scene->integrator->tag_update(scene);
|
||||
tag_modified();
|
||||
}
|
||||
|
||||
Shader *Background::get_shader(const Scene *scene)
|
||||
|
@@ -78,7 +78,7 @@ BakeManager::BakeManager()
|
||||
type = SHADER_EVAL_BAKE;
|
||||
pass_filter = 0;
|
||||
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
BakeManager::~BakeManager()
|
||||
@@ -114,9 +114,9 @@ void BakeManager::set(Scene *scene,
|
||||
|
||||
/* create device and update scene */
|
||||
scene->film->tag_modified();
|
||||
scene->integrator->tag_update(scene, Integrator::UPDATE_ALL);
|
||||
scene->integrator->tag_update(scene);
|
||||
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
void BakeManager::device_update(Device * /*device*/,
|
||||
@@ -124,7 +124,7 @@ void BakeManager::device_update(Device * /*device*/,
|
||||
Scene *scene,
|
||||
Progress & /* progress */)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
@@ -152,21 +152,11 @@ void BakeManager::device_update(Device * /*device*/,
|
||||
object_index++;
|
||||
}
|
||||
|
||||
need_update_ = false;
|
||||
need_update = false;
|
||||
}
|
||||
|
||||
void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
|
||||
{
|
||||
}
|
||||
|
||||
void BakeManager::tag_update()
|
||||
{
|
||||
need_update_ = true;
|
||||
}
|
||||
|
||||
bool BakeManager::need_update() const
|
||||
{
|
||||
return need_update_;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -36,12 +36,9 @@ class BakeManager {
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
void tag_update();
|
||||
|
||||
bool need_update() const;
|
||||
bool need_update;
|
||||
|
||||
private:
|
||||
bool need_update_;
|
||||
ShaderEvalType type;
|
||||
int pass_filter;
|
||||
std::string object_name;
|
||||
|
@@ -688,16 +688,16 @@ void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *sce
|
||||
void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes)
|
||||
{
|
||||
if (Pass::contains(scene->passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
|
||||
scene->geometry_manager->tag_update(scene, GeometryManager::UV_PASS_NEEDED);
|
||||
scene->geometry_manager->tag_update(scene);
|
||||
|
||||
foreach (Shader *shader, scene->shaders)
|
||||
shader->need_update_uvs = true;
|
||||
shader->need_update_geometry = true;
|
||||
}
|
||||
else if (Pass::contains(scene->passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION)) {
|
||||
scene->geometry_manager->tag_update(scene, GeometryManager::MOTION_PASS_NEEDED);
|
||||
scene->geometry_manager->tag_update(scene);
|
||||
}
|
||||
else if (Pass::contains(scene->passes, PASS_AO) != Pass::contains(passes_, PASS_AO)) {
|
||||
scene->integrator->tag_update(scene, Integrator::AO_PASS_MODIFIED);
|
||||
scene->integrator->tag_update(scene);
|
||||
}
|
||||
|
||||
if (update_passes) {
|
||||
|
@@ -240,6 +240,7 @@ void Geometry::compute_bvh(
|
||||
}
|
||||
}
|
||||
|
||||
clear_modified();
|
||||
need_update_rebuild = false;
|
||||
}
|
||||
|
||||
@@ -261,21 +262,22 @@ bool Geometry::has_voxel_attributes() const
|
||||
|
||||
void Geometry::tag_update(Scene *scene, bool rebuild)
|
||||
{
|
||||
tag_modified();
|
||||
|
||||
if (rebuild) {
|
||||
need_update_rebuild = true;
|
||||
scene->light_manager->tag_update(scene, LightManager::MESH_NEED_REBUILD);
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
else {
|
||||
foreach (Node *node, used_shaders) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->has_surface_emission) {
|
||||
scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED);
|
||||
break;
|
||||
}
|
||||
if (shader->has_surface_emission)
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
scene->geometry_manager->tag_update(scene, GeometryManager::GEOMETRY_MODIFIED);
|
||||
scene->geometry_manager->need_update = true;
|
||||
scene->object_manager->need_update = true;
|
||||
}
|
||||
|
||||
void Geometry::tag_bvh_update(bool rebuild)
|
||||
@@ -291,7 +293,7 @@ void Geometry::tag_bvh_update(bool rebuild)
|
||||
|
||||
GeometryManager::GeometryManager()
|
||||
{
|
||||
update_flags = UPDATE_ALL;
|
||||
need_update = true;
|
||||
need_flags_update = true;
|
||||
}
|
||||
|
||||
@@ -492,10 +494,6 @@ void GeometryManager::update_svm_attributes(Device *,
|
||||
if (attr_map_size == 0)
|
||||
return;
|
||||
|
||||
if (!dscene->attributes_map.need_realloc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* create attribute map */
|
||||
uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size);
|
||||
memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint));
|
||||
@@ -604,10 +602,8 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
|
||||
offset = attr_uchar4_offset;
|
||||
|
||||
assert(attr_uchar4.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_uchar4[offset + k] = data[k];
|
||||
}
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_uchar4[offset + k] = data[k];
|
||||
}
|
||||
attr_uchar4_offset += size;
|
||||
}
|
||||
@@ -616,10 +612,8 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
|
||||
offset = attr_float_offset;
|
||||
|
||||
assert(attr_float.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float[offset + k] = data[k];
|
||||
}
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float[offset + k] = data[k];
|
||||
}
|
||||
attr_float_offset += size;
|
||||
}
|
||||
@@ -628,10 +622,8 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
|
||||
offset = attr_float2_offset;
|
||||
|
||||
assert(attr_float2.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float2[offset + k] = data[k];
|
||||
}
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float2[offset + k] = data[k];
|
||||
}
|
||||
attr_float2_offset += size;
|
||||
}
|
||||
@@ -640,10 +632,8 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
|
||||
offset = attr_float3_offset;
|
||||
|
||||
assert(attr_float3.size() >= offset + size * 3);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size * 3; k++) {
|
||||
attr_float3[offset + k] = (&tfm->x)[k];
|
||||
}
|
||||
for (size_t k = 0; k < size * 3; k++) {
|
||||
attr_float3[offset + k] = (&tfm->x)[k];
|
||||
}
|
||||
attr_float3_offset += size * 3;
|
||||
}
|
||||
@@ -652,10 +642,8 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom,
|
||||
offset = attr_float3_offset;
|
||||
|
||||
assert(attr_float3.size() >= offset + size);
|
||||
if (mattr->modified) {
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float3[offset + k] = data[k];
|
||||
}
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
attr_float3[offset + k] = data[k];
|
||||
}
|
||||
attr_float3_offset += size;
|
||||
}
|
||||
@@ -820,11 +808,6 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
dscene->attributes_float3.alloc(attr_float3_size);
|
||||
dscene->attributes_uchar4.alloc(attr_uchar4_size);
|
||||
|
||||
const bool copy_all_data = dscene->attributes_float.need_realloc() ||
|
||||
dscene->attributes_float2.need_realloc() ||
|
||||
dscene->attributes_float3.need_realloc() ||
|
||||
dscene->attributes_uchar4.need_realloc();
|
||||
|
||||
size_t attr_float_offset = 0;
|
||||
size_t attr_float2_offset = 0;
|
||||
size_t attr_float3_offset = 0;
|
||||
@@ -839,12 +822,6 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
* they actually refer to the same mesh attributes, optimize */
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = geom->attributes.find(req);
|
||||
|
||||
if (attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
attr->modified |= copy_all_data;
|
||||
}
|
||||
|
||||
update_attribute_element_offset(geom,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
@@ -863,11 +840,6 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
Attribute *subd_attr = mesh->subd_attributes.find(req);
|
||||
|
||||
if (subd_attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
subd_attr->modified |= copy_all_data;
|
||||
}
|
||||
|
||||
update_attribute_element_offset(mesh,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
@@ -931,10 +903,18 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
/* copy to device */
|
||||
progress.set_status("Updating Mesh", "Copying Attributes to device");
|
||||
|
||||
dscene->attributes_float.copy_to_device();
|
||||
dscene->attributes_float2.copy_to_device();
|
||||
dscene->attributes_float3.copy_to_device();
|
||||
dscene->attributes_uchar4.copy_to_device();
|
||||
if (dscene->attributes_float.size()) {
|
||||
dscene->attributes_float.copy_to_device();
|
||||
}
|
||||
if (dscene->attributes_float2.size()) {
|
||||
dscene->attributes_float2.copy_to_device();
|
||||
}
|
||||
if (dscene->attributes_float3.size()) {
|
||||
dscene->attributes_float3.copy_to_device();
|
||||
}
|
||||
if (dscene->attributes_uchar4.size()) {
|
||||
dscene->attributes_uchar4.copy_to_device();
|
||||
}
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
@@ -1086,34 +1066,17 @@ void GeometryManager::device_update_mesh(
|
||||
uint *tri_patch = dscene->tri_patch.alloc(tri_size);
|
||||
float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
|
||||
|
||||
const bool copy_all_data = dscene->tri_shader.need_realloc() ||
|
||||
dscene->tri_vindex.need_realloc() ||
|
||||
dscene->tri_vnormal.need_realloc() ||
|
||||
dscene->tri_patch.need_realloc() ||
|
||||
dscene->tri_patch_uv.need_realloc();
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
|
||||
if (mesh->shader_is_modified() || mesh->smooth_is_modified() ||
|
||||
mesh->triangles_is_modified() || copy_all_data) {
|
||||
mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]);
|
||||
}
|
||||
|
||||
if (mesh->verts_is_modified() || copy_all_data) {
|
||||
mesh->pack_normals(&vnormal[mesh->vert_offset]);
|
||||
}
|
||||
|
||||
if (mesh->triangles_is_modified() || mesh->vert_patch_uv_is_modified() || copy_all_data) {
|
||||
mesh->pack_verts(tri_prim_index,
|
||||
&tri_vindex[mesh->prim_offset],
|
||||
&tri_patch[mesh->prim_offset],
|
||||
&tri_patch_uv[mesh->vert_offset],
|
||||
mesh->vert_offset,
|
||||
mesh->prim_offset);
|
||||
}
|
||||
|
||||
mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]);
|
||||
mesh->pack_normals(&vnormal[mesh->vert_offset]);
|
||||
mesh->pack_verts(tri_prim_index,
|
||||
&tri_vindex[mesh->prim_offset],
|
||||
&tri_patch[mesh->prim_offset],
|
||||
&tri_patch_uv[mesh->vert_offset],
|
||||
mesh->vert_offset,
|
||||
mesh->prim_offset);
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
@@ -1122,11 +1085,11 @@ void GeometryManager::device_update_mesh(
|
||||
/* vertex coordinates */
|
||||
progress.set_status("Updating Mesh", "Copying Mesh to device");
|
||||
|
||||
dscene->tri_shader.copy_to_device_if_modified();
|
||||
dscene->tri_vnormal.copy_to_device_if_modified();
|
||||
dscene->tri_vindex.copy_to_device_if_modified();
|
||||
dscene->tri_patch.copy_to_device_if_modified();
|
||||
dscene->tri_patch_uv.copy_to_device_if_modified();
|
||||
dscene->tri_shader.copy_to_device();
|
||||
dscene->tri_vnormal.copy_to_device();
|
||||
dscene->tri_vindex.copy_to_device();
|
||||
dscene->tri_patch.copy_to_device();
|
||||
dscene->tri_patch_uv.copy_to_device();
|
||||
}
|
||||
|
||||
if (curve_size != 0) {
|
||||
@@ -1135,21 +1098,9 @@ void GeometryManager::device_update_mesh(
|
||||
float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
|
||||
float4 *curves = dscene->curves.alloc(curve_size);
|
||||
|
||||
const bool copy_all_data = dscene->curve_keys.need_realloc() || dscene->curves.need_realloc();
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
|
||||
bool curve_keys_co_modified = hair->curve_radius_is_modified() ||
|
||||
hair->curve_keys_is_modified();
|
||||
bool curve_data_modified = hair->curve_shader_is_modified() ||
|
||||
hair->curve_first_key_is_modified();
|
||||
|
||||
if (!curve_keys_co_modified && !curve_data_modified && !copy_all_data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hair->pack_curves(scene,
|
||||
&curve_keys[hair->curvekey_offset],
|
||||
&curves[hair->prim_offset],
|
||||
@@ -1159,11 +1110,11 @@ void GeometryManager::device_update_mesh(
|
||||
}
|
||||
}
|
||||
|
||||
dscene->curve_keys.copy_to_device_if_modified();
|
||||
dscene->curves.copy_to_device_if_modified();
|
||||
dscene->curve_keys.copy_to_device();
|
||||
dscene->curves.copy_to_device();
|
||||
}
|
||||
|
||||
if (patch_size != 0 && dscene->patches.need_realloc()) {
|
||||
if (patch_size != 0) {
|
||||
progress.set_status("Updating Mesh", "Copying Patches to device");
|
||||
|
||||
uint *patch_data = dscene->patches.alloc(patch_size);
|
||||
@@ -1229,25 +1180,16 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
|
||||
VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
|
||||
|
||||
const bool can_refit = scene->bvh != nullptr &&
|
||||
(bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX);
|
||||
const bool pack_all = scene->bvh == nullptr;
|
||||
|
||||
BVH *bvh = scene->bvh;
|
||||
if (!scene->bvh) {
|
||||
bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device);
|
||||
}
|
||||
|
||||
device->build_bvh(bvh, progress, can_refit);
|
||||
delete scene->bvh;
|
||||
BVH *bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device);
|
||||
device->build_bvh(bvh, progress, false);
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool has_bvh2_layout = (bparams.bvh_layout == BVH_LAYOUT_BVH2);
|
||||
|
||||
PackedBVH pack;
|
||||
if (has_bvh2_layout) {
|
||||
if (bparams.bvh_layout == BVH_LAYOUT_BVH2) {
|
||||
pack = std::move(static_cast<BVH2 *>(bvh)->pack);
|
||||
}
|
||||
else {
|
||||
@@ -1268,22 +1210,12 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
}
|
||||
|
||||
pack.root_index = -1;
|
||||
|
||||
if (!pack_all) {
|
||||
/* if we do not need to recreate the BVH, then only the vertices are updated, so we can
|
||||
* safely retake the memory */
|
||||
dscene->prim_tri_verts.give_data(pack.prim_tri_verts);
|
||||
}
|
||||
else {
|
||||
/* It is not strictly necessary to skip those resizes we if do not have to repack, as the OS
|
||||
* will not allocate pages if we do not touch them, however it does help catching bugs. */
|
||||
pack.prim_tri_index.resize(num_prims);
|
||||
pack.prim_tri_verts.resize(num_tri_verts);
|
||||
pack.prim_type.resize(num_prims);
|
||||
pack.prim_index.resize(num_prims);
|
||||
pack.prim_object.resize(num_prims);
|
||||
pack.prim_visibility.resize(num_prims);
|
||||
}
|
||||
pack.prim_tri_index.reserve(num_prims);
|
||||
pack.prim_tri_verts.reserve(num_tri_verts);
|
||||
pack.prim_type.reserve(num_prims);
|
||||
pack.prim_index.reserve(num_prims);
|
||||
pack.prim_object.reserve(num_prims);
|
||||
pack.prim_visibility.reserve(num_prims);
|
||||
|
||||
// Merge visibility flags of all objects and find object index for non-instanced geometry
|
||||
unordered_map<const Geometry *, pair<int, uint>> geometry_to_object_info;
|
||||
@@ -1297,27 +1229,17 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
}
|
||||
}
|
||||
|
||||
TaskPool pool;
|
||||
// Iterate over scene mesh list instead of objects, since 'optix_prim_offset' was calculated
|
||||
// based on that list, which may be ordered differently from the object list.
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (!pack_all && !geom->is_modified()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const pair<int, uint> &info = geometry_to_object_info[geom];
|
||||
pool.push(function_bind(
|
||||
&Geometry::pack_primitives, geom, &pack, info.first, info.second, pack_all));
|
||||
geom->pack_primitives(pack, info.first, info.second);
|
||||
}
|
||||
pool.wait_work();
|
||||
}
|
||||
|
||||
/* copy to device */
|
||||
progress.set_status("Updating Scene BVH", "Copying BVH to device");
|
||||
|
||||
/* When using BVH2, we always have to copy/update the data as its layout is dependent on the
|
||||
* BVH's leaf nodes which may be different when the objects or vertices move. */
|
||||
|
||||
if (pack.nodes.size()) {
|
||||
dscene->bvh_nodes.steal_data(pack.nodes);
|
||||
dscene->bvh_nodes.copy_to_device();
|
||||
@@ -1330,7 +1252,7 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
dscene->object_node.steal_data(pack.object_node);
|
||||
dscene->object_node.copy_to_device();
|
||||
}
|
||||
if (pack.prim_tri_index.size() && (dscene->prim_tri_index.need_realloc() || has_bvh2_layout)) {
|
||||
if (pack.prim_tri_index.size()) {
|
||||
dscene->prim_tri_index.steal_data(pack.prim_tri_index);
|
||||
dscene->prim_tri_index.copy_to_device();
|
||||
}
|
||||
@@ -1338,23 +1260,23 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
dscene->prim_tri_verts.steal_data(pack.prim_tri_verts);
|
||||
dscene->prim_tri_verts.copy_to_device();
|
||||
}
|
||||
if (pack.prim_type.size() && (dscene->prim_type.need_realloc() || has_bvh2_layout)) {
|
||||
if (pack.prim_type.size()) {
|
||||
dscene->prim_type.steal_data(pack.prim_type);
|
||||
dscene->prim_type.copy_to_device();
|
||||
}
|
||||
if (pack.prim_visibility.size() && (dscene->prim_visibility.need_realloc() || has_bvh2_layout)) {
|
||||
if (pack.prim_visibility.size()) {
|
||||
dscene->prim_visibility.steal_data(pack.prim_visibility);
|
||||
dscene->prim_visibility.copy_to_device();
|
||||
}
|
||||
if (pack.prim_index.size() && (dscene->prim_index.need_realloc() || has_bvh2_layout)) {
|
||||
if (pack.prim_index.size()) {
|
||||
dscene->prim_index.steal_data(pack.prim_index);
|
||||
dscene->prim_index.copy_to_device();
|
||||
}
|
||||
if (pack.prim_object.size() && (dscene->prim_object.need_realloc() || has_bvh2_layout)) {
|
||||
if (pack.prim_object.size()) {
|
||||
dscene->prim_object.steal_data(pack.prim_object);
|
||||
dscene->prim_object.copy_to_device();
|
||||
}
|
||||
if (pack.prim_time.size() && (dscene->prim_time.need_realloc() || has_bvh2_layout)) {
|
||||
if (pack.prim_time.size()) {
|
||||
dscene->prim_time.steal_data(pack.prim_time);
|
||||
dscene->prim_time.copy_to_device();
|
||||
}
|
||||
@@ -1367,65 +1289,12 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
dscene->data.bvh.scene = NULL;
|
||||
}
|
||||
|
||||
/* Set of flags used to help determining what data has been modified or needs reallocation, so we
|
||||
* can decide which device data to free or update. */
|
||||
enum {
|
||||
DEVICE_CURVE_DATA_MODIFIED = (1 << 0),
|
||||
DEVICE_MESH_DATA_MODIFIED = (1 << 1),
|
||||
|
||||
ATTR_FLOAT_MODIFIED = (1 << 2),
|
||||
ATTR_FLOAT2_MODIFIED = (1 << 3),
|
||||
ATTR_FLOAT3_MODIFIED = (1 << 4),
|
||||
ATTR_UCHAR4_MODIFIED = (1 << 5),
|
||||
|
||||
CURVE_DATA_NEED_REALLOC = (1 << 6),
|
||||
MESH_DATA_NEED_REALLOC = (1 << 7),
|
||||
|
||||
ATTR_FLOAT_NEEDS_REALLOC = (1 << 8),
|
||||
ATTR_FLOAT2_NEEDS_REALLOC = (1 << 9),
|
||||
ATTR_FLOAT3_NEEDS_REALLOC = (1 << 10),
|
||||
ATTR_UCHAR4_NEEDS_REALLOC = (1 << 11),
|
||||
|
||||
ATTRS_NEED_REALLOC = (ATTR_FLOAT_NEEDS_REALLOC | ATTR_FLOAT2_NEEDS_REALLOC |
|
||||
ATTR_FLOAT3_NEEDS_REALLOC | ATTR_UCHAR4_NEEDS_REALLOC),
|
||||
DEVICE_MESH_DATA_NEEDS_REALLOC = (CURVE_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
DEVICE_CURVE_DATA_NEEDS_REALLOC = (MESH_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC),
|
||||
};
|
||||
|
||||
static void update_device_flags_attribute(uint32_t &device_update_flags,
|
||||
const AttributeSet &attributes)
|
||||
{
|
||||
foreach (const Attribute &attr, attributes.attributes) {
|
||||
if (!attr.modified) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attr.element == ATTR_ELEMENT_CORNER) {
|
||||
device_update_flags |= ATTR_UCHAR4_MODIFIED;
|
||||
}
|
||||
else if (attr.type == TypeDesc::TypeFloat) {
|
||||
device_update_flags |= ATTR_FLOAT_MODIFIED;
|
||||
}
|
||||
else if (attr.type == TypeFloat2) {
|
||||
device_update_flags |= ATTR_FLOAT2_MODIFIED;
|
||||
}
|
||||
else if (attr.type == TypeDesc::TypeMatrix) {
|
||||
device_update_flags |= ATTR_FLOAT3_MODIFIED;
|
||||
}
|
||||
else if (attr.element != ATTR_ELEMENT_VOXEL) {
|
||||
device_update_flags |= ATTR_FLOAT3_MODIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress)
|
||||
{
|
||||
if (!need_update() && !need_flags_update) {
|
||||
if (!need_update && !need_flags_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t device_update_flags = 0;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
if (scene->update_stats) {
|
||||
scene->update_stats->geometry.times.add_entry({"device_update_preprocess", time});
|
||||
@@ -1445,54 +1314,9 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
|
||||
if (shader->has_volume) {
|
||||
geom->has_volume = true;
|
||||
}
|
||||
|
||||
if (shader->has_surface_bssrdf) {
|
||||
geom->has_surface_bssrdf = true;
|
||||
}
|
||||
|
||||
if (shader->need_update_uvs) {
|
||||
device_update_flags |= ATTR_FLOAT2_NEEDS_REALLOC;
|
||||
|
||||
/* Attributes might need to be tesselated if added. */
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
if (mesh->need_tesselation()) {
|
||||
mesh->tag_modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shader->need_update_attribute) {
|
||||
device_update_flags |= ATTRS_NEED_REALLOC;
|
||||
|
||||
/* Attributes might need to be tesselated if added. */
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
if (mesh->need_tesselation()) {
|
||||
mesh->tag_modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shader->need_update_displacement) {
|
||||
/* tag displacement related sockets as modified */
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
mesh->tag_verts_modified();
|
||||
mesh->tag_subd_dicing_rate_modified();
|
||||
mesh->tag_subd_max_level_modified();
|
||||
mesh->tag_subd_objecttoworld_modified();
|
||||
|
||||
device_update_flags |= ATTRS_NEED_REALLOC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* only check for modified attributes if we do not need to reallocate them already */
|
||||
if ((device_update_flags & ATTRS_NEED_REALLOC) == 0) {
|
||||
update_device_flags_attribute(device_update_flags, geom->attributes);
|
||||
/* don't check for subd_attributes, as if they were modified, we would need to reallocate
|
||||
* anyway */
|
||||
}
|
||||
|
||||
/* Re-create volume mesh if we will rebuild or refit the BVH. Note we
|
||||
@@ -1508,119 +1332,13 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
|
||||
|
||||
Volume *volume = static_cast<Volume *>(geom);
|
||||
create_volume_mesh(volume, progress);
|
||||
|
||||
/* always reallocate when we have a volume, as we need to rebuild the BVH */
|
||||
device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC;
|
||||
}
|
||||
|
||||
if (geom->is_hair()) {
|
||||
/* Set curve shape, still a global scene setting for now. */
|
||||
Hair *hair = static_cast<Hair *>(geom);
|
||||
hair->curve_shape = scene->params.hair_shape;
|
||||
|
||||
if (hair->need_update_rebuild) {
|
||||
device_update_flags |= DEVICE_CURVE_DATA_NEEDS_REALLOC;
|
||||
}
|
||||
else if (hair->is_modified()) {
|
||||
device_update_flags |= DEVICE_CURVE_DATA_MODIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
|
||||
if (mesh->need_update_rebuild) {
|
||||
device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC;
|
||||
}
|
||||
else if (mesh->is_modified()) {
|
||||
device_update_flags |= DEVICE_MESH_DATA_MODIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (update_flags & (MESH_ADDED | MESH_REMOVED)) {
|
||||
device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC;
|
||||
}
|
||||
|
||||
if (update_flags & (HAIR_ADDED | HAIR_REMOVED)) {
|
||||
device_update_flags |= DEVICE_CURVE_DATA_NEEDS_REALLOC;
|
||||
}
|
||||
|
||||
/* tag the device arrays for reallocation or modification */
|
||||
DeviceScene *dscene = &scene->dscene;
|
||||
|
||||
if (device_update_flags & (DEVICE_MESH_DATA_NEEDS_REALLOC | DEVICE_CURVE_DATA_NEEDS_REALLOC)) {
|
||||
delete scene->bvh;
|
||||
scene->bvh = nullptr;
|
||||
|
||||
dscene->bvh_nodes.tag_realloc();
|
||||
dscene->bvh_leaf_nodes.tag_realloc();
|
||||
dscene->object_node.tag_realloc();
|
||||
dscene->prim_tri_verts.tag_realloc();
|
||||
dscene->prim_tri_index.tag_realloc();
|
||||
dscene->prim_type.tag_realloc();
|
||||
dscene->prim_visibility.tag_realloc();
|
||||
dscene->prim_index.tag_realloc();
|
||||
dscene->prim_object.tag_realloc();
|
||||
dscene->prim_time.tag_realloc();
|
||||
|
||||
if (device_update_flags & DEVICE_MESH_DATA_NEEDS_REALLOC) {
|
||||
dscene->tri_vnormal.tag_realloc();
|
||||
dscene->tri_vindex.tag_realloc();
|
||||
dscene->tri_patch.tag_realloc();
|
||||
dscene->tri_vnormal.tag_realloc();
|
||||
dscene->tri_patch_uv.tag_realloc();
|
||||
dscene->patches.tag_realloc();
|
||||
}
|
||||
|
||||
if (device_update_flags & DEVICE_CURVE_DATA_NEEDS_REALLOC) {
|
||||
dscene->curves.tag_realloc();
|
||||
dscene->curve_keys.tag_realloc();
|
||||
}
|
||||
}
|
||||
|
||||
if (device_update_flags & ATTR_FLOAT_NEEDS_REALLOC) {
|
||||
dscene->attributes_map.tag_realloc();
|
||||
dscene->attributes_float.tag_realloc();
|
||||
}
|
||||
else if (device_update_flags & ATTR_FLOAT_MODIFIED) {
|
||||
dscene->attributes_float.tag_modified();
|
||||
}
|
||||
|
||||
if (device_update_flags & ATTR_FLOAT2_NEEDS_REALLOC) {
|
||||
dscene->attributes_map.tag_realloc();
|
||||
dscene->attributes_float2.tag_realloc();
|
||||
}
|
||||
else if (device_update_flags & ATTR_FLOAT_MODIFIED) {
|
||||
dscene->attributes_float.tag_modified();
|
||||
}
|
||||
|
||||
if (device_update_flags & ATTR_FLOAT3_NEEDS_REALLOC) {
|
||||
dscene->attributes_map.tag_realloc();
|
||||
dscene->attributes_float3.tag_realloc();
|
||||
}
|
||||
else if (device_update_flags & ATTR_FLOAT_MODIFIED) {
|
||||
dscene->attributes_float.tag_modified();
|
||||
}
|
||||
|
||||
if (device_update_flags & ATTR_UCHAR4_NEEDS_REALLOC) {
|
||||
dscene->attributes_map.tag_realloc();
|
||||
dscene->attributes_uchar4.tag_realloc();
|
||||
}
|
||||
else if (device_update_flags & ATTR_UCHAR4_MODIFIED) {
|
||||
dscene->attributes_uchar4.tag_modified();
|
||||
}
|
||||
|
||||
if (device_update_flags & DEVICE_MESH_DATA_MODIFIED) {
|
||||
/* if anything else than vertices or shaders are modified, we would need to reallocate, so
|
||||
* these are the only arrays that can be updated */
|
||||
dscene->tri_vnormal.tag_modified();
|
||||
dscene->tri_shader.tag_modified();
|
||||
}
|
||||
|
||||
if (device_update_flags & DEVICE_CURVE_DATA_MODIFIED) {
|
||||
dscene->curve_keys.tag_modified();
|
||||
dscene->curves.tag_modified();
|
||||
}
|
||||
|
||||
need_flags_update = false;
|
||||
@@ -1705,7 +1423,7 @@ void GeometryManager::device_update(Device *device,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
VLOG(1) << "Total " << scene->geometry.size() << " meshes.";
|
||||
@@ -1721,6 +1439,12 @@ void GeometryManager::device_update(Device *device,
|
||||
});
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
foreach (Node *node, geom->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->need_update_geometry)
|
||||
geom->tag_modified();
|
||||
}
|
||||
|
||||
if (geom->is_modified() &&
|
||||
(geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
@@ -1817,7 +1541,7 @@ void GeometryManager::device_update(Device *device,
|
||||
}
|
||||
|
||||
/* Device update. */
|
||||
device_free(device, dscene, false);
|
||||
device_free(device, dscene);
|
||||
|
||||
const BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
|
||||
device->get_bvh_layout_mask());
|
||||
@@ -1890,7 +1614,7 @@ void GeometryManager::device_update(Device *device,
|
||||
{"device_update (displacement: attributes)", time});
|
||||
}
|
||||
});
|
||||
device_free(device, dscene, false);
|
||||
device_free(device, dscene);
|
||||
|
||||
device_update_attributes(device, dscene, scene, progress);
|
||||
if (progress.get_cancel()) {
|
||||
@@ -1898,9 +1622,6 @@ void GeometryManager::device_update(Device *device,
|
||||
}
|
||||
}
|
||||
|
||||
/* update the bvh even when there is no geometry so the kernel bvh data is still valid,
|
||||
* especially when removing all of the objects during interactive renders */
|
||||
bool need_update_scene_bvh = (scene->bvh == nullptr);
|
||||
{
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
if (scene->update_stats) {
|
||||
@@ -1912,7 +1633,6 @@ void GeometryManager::device_update(Device *device,
|
||||
size_t i = 0;
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
if (geom->is_modified()) {
|
||||
need_update_scene_bvh = true;
|
||||
pool.push(function_bind(
|
||||
&Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh));
|
||||
if (geom->need_build_bvh(bvh_layout)) {
|
||||
@@ -1927,9 +1647,7 @@ void GeometryManager::device_update(Device *device,
|
||||
}
|
||||
|
||||
foreach (Shader *shader, scene->shaders) {
|
||||
shader->need_update_uvs = false;
|
||||
shader->need_update_attribute = false;
|
||||
shader->need_update_displacement = false;
|
||||
shader->need_update_geometry = false;
|
||||
}
|
||||
|
||||
Scene::MotionType need_motion = scene->need_motion();
|
||||
@@ -1952,7 +1670,7 @@ void GeometryManager::device_update(Device *device,
|
||||
return;
|
||||
}
|
||||
|
||||
if (need_update_scene_bvh) {
|
||||
{
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
if (scene->update_stats) {
|
||||
scene->update_stats->geometry.times.add_entry({"device_update (build scene BVH)", time});
|
||||
@@ -1977,6 +1695,8 @@ void GeometryManager::device_update(Device *device,
|
||||
}
|
||||
}
|
||||
|
||||
need_update = false;
|
||||
|
||||
if (true_displacement_used) {
|
||||
/* Re-tag flags for update, so they're re-evaluated
|
||||
* for meshes with correct bounding boxes.
|
||||
@@ -1986,71 +1706,33 @@ void GeometryManager::device_update(Device *device,
|
||||
*/
|
||||
scene->object_manager->need_flags_update = old_need_object_flags_update;
|
||||
}
|
||||
|
||||
/* unset flags */
|
||||
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
geom->clear_modified();
|
||||
geom->attributes.clear_modified();
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
mesh->subd_attributes.clear_modified();
|
||||
}
|
||||
}
|
||||
|
||||
update_flags = UPDATE_NONE;
|
||||
|
||||
dscene->bvh_nodes.clear_modified();
|
||||
dscene->bvh_leaf_nodes.clear_modified();
|
||||
dscene->object_node.clear_modified();
|
||||
dscene->prim_tri_verts.clear_modified();
|
||||
dscene->prim_tri_index.clear_modified();
|
||||
dscene->prim_type.clear_modified();
|
||||
dscene->prim_visibility.clear_modified();
|
||||
dscene->prim_index.clear_modified();
|
||||
dscene->prim_object.clear_modified();
|
||||
dscene->prim_time.clear_modified();
|
||||
dscene->tri_shader.clear_modified();
|
||||
dscene->tri_vindex.clear_modified();
|
||||
dscene->tri_patch.clear_modified();
|
||||
dscene->tri_vnormal.clear_modified();
|
||||
dscene->tri_patch_uv.clear_modified();
|
||||
dscene->curves.clear_modified();
|
||||
dscene->curve_keys.clear_modified();
|
||||
dscene->patches.clear_modified();
|
||||
dscene->attributes_map.clear_modified();
|
||||
dscene->attributes_float.clear_modified();
|
||||
dscene->attributes_float2.clear_modified();
|
||||
dscene->attributes_float3.clear_modified();
|
||||
dscene->attributes_uchar4.clear_modified();
|
||||
}
|
||||
|
||||
void GeometryManager::device_free(Device *device, DeviceScene *dscene, bool force_free)
|
||||
void GeometryManager::device_free(Device *device, DeviceScene *dscene)
|
||||
{
|
||||
dscene->bvh_nodes.free_if_need_realloc(force_free);
|
||||
dscene->bvh_leaf_nodes.free_if_need_realloc(force_free);
|
||||
dscene->object_node.free_if_need_realloc(force_free);
|
||||
dscene->prim_tri_verts.free_if_need_realloc(force_free);
|
||||
dscene->prim_tri_index.free_if_need_realloc(force_free);
|
||||
dscene->prim_type.free_if_need_realloc(force_free);
|
||||
dscene->prim_visibility.free_if_need_realloc(force_free);
|
||||
dscene->prim_index.free_if_need_realloc(force_free);
|
||||
dscene->prim_object.free_if_need_realloc(force_free);
|
||||
dscene->prim_time.free_if_need_realloc(force_free);
|
||||
dscene->tri_shader.free_if_need_realloc(force_free);
|
||||
dscene->tri_vnormal.free_if_need_realloc(force_free);
|
||||
dscene->tri_vindex.free_if_need_realloc(force_free);
|
||||
dscene->tri_patch.free_if_need_realloc(force_free);
|
||||
dscene->tri_patch_uv.free_if_need_realloc(force_free);
|
||||
dscene->curves.free_if_need_realloc(force_free);
|
||||
dscene->curve_keys.free_if_need_realloc(force_free);
|
||||
dscene->patches.free_if_need_realloc(force_free);
|
||||
dscene->attributes_map.free_if_need_realloc(force_free);
|
||||
dscene->attributes_float.free_if_need_realloc(force_free);
|
||||
dscene->attributes_float2.free_if_need_realloc(force_free);
|
||||
dscene->attributes_float3.free_if_need_realloc(force_free);
|
||||
dscene->attributes_uchar4.free_if_need_realloc(force_free);
|
||||
dscene->bvh_nodes.free();
|
||||
dscene->bvh_leaf_nodes.free();
|
||||
dscene->object_node.free();
|
||||
dscene->prim_tri_verts.free();
|
||||
dscene->prim_tri_index.free();
|
||||
dscene->prim_type.free();
|
||||
dscene->prim_visibility.free();
|
||||
dscene->prim_index.free();
|
||||
dscene->prim_object.free();
|
||||
dscene->prim_time.free();
|
||||
dscene->tri_shader.free();
|
||||
dscene->tri_vnormal.free();
|
||||
dscene->tri_vindex.free();
|
||||
dscene->tri_patch.free();
|
||||
dscene->tri_patch_uv.free();
|
||||
dscene->curves.free();
|
||||
dscene->curve_keys.free();
|
||||
dscene->patches.free();
|
||||
dscene->attributes_map.free();
|
||||
dscene->attributes_float.free();
|
||||
dscene->attributes_float2.free();
|
||||
dscene->attributes_float3.free();
|
||||
dscene->attributes_uchar4.free();
|
||||
|
||||
/* Signal for shaders like displacement not to do ray tracing. */
|
||||
dscene->data.bvh.bvh_layout = BVH_LAYOUT_NONE;
|
||||
@@ -2068,19 +1750,10 @@ void GeometryManager::device_free(Device *device, DeviceScene *dscene, bool forc
|
||||
#endif
|
||||
}
|
||||
|
||||
void GeometryManager::tag_update(Scene *scene, uint32_t flag)
|
||||
void GeometryManager::tag_update(Scene *scene)
|
||||
{
|
||||
update_flags |= flag;
|
||||
|
||||
/* do not tag the object manager for an update if it is the one who tagged us */
|
||||
if ((flag & OBJECT_MANAGER) == 0) {
|
||||
scene->object_manager->tag_update(scene, ObjectManager::GEOMETRY_MANAGER);
|
||||
}
|
||||
}
|
||||
|
||||
bool GeometryManager::need_update() const
|
||||
{
|
||||
return update_flags != UPDATE_NONE;
|
||||
need_update = true;
|
||||
scene->object_manager->need_update = true;
|
||||
}
|
||||
|
||||
void GeometryManager::collect_statistics(const Scene *scene, RenderStats *stats)
|
||||
|
@@ -125,7 +125,7 @@ class Geometry : public Node {
|
||||
int n,
|
||||
int total);
|
||||
|
||||
virtual void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) = 0;
|
||||
virtual void pack_primitives(PackedBVH &pack, int object, uint visibility) = 0;
|
||||
|
||||
/* Check whether the geometry should have own BVH built separately. Briefly,
|
||||
* own BVH is needed for geometry, if:
|
||||
@@ -155,11 +155,6 @@ class Geometry : public Node {
|
||||
return geometry_type == HAIR;
|
||||
}
|
||||
|
||||
bool is_volume() const
|
||||
{
|
||||
return geometry_type == VOLUME;
|
||||
}
|
||||
|
||||
/* Updates */
|
||||
void tag_update(Scene *scene, bool rebuild);
|
||||
|
||||
@@ -169,32 +164,9 @@ class Geometry : public Node {
|
||||
/* Geometry Manager */
|
||||
|
||||
class GeometryManager {
|
||||
uint32_t update_flags;
|
||||
|
||||
public:
|
||||
enum : uint32_t {
|
||||
UV_PASS_NEEDED = (1 << 0),
|
||||
MOTION_PASS_NEEDED = (1 << 1),
|
||||
GEOMETRY_MODIFIED = (1 << 2),
|
||||
OBJECT_MANAGER = (1 << 3),
|
||||
MESH_ADDED = (1 << 4),
|
||||
MESH_REMOVED = (1 << 5),
|
||||
HAIR_ADDED = (1 << 6),
|
||||
HAIR_REMOVED = (1 << 7),
|
||||
|
||||
SHADER_ATTRIBUTE_MODIFIED = (1 << 8),
|
||||
SHADER_DISPLACEMENT_MODIFIED = (1 << 9),
|
||||
|
||||
GEOMETRY_ADDED = MESH_ADDED | HAIR_ADDED,
|
||||
GEOMETRY_REMOVED = MESH_REMOVED | HAIR_REMOVED,
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
||||
UPDATE_NONE = 0u,
|
||||
};
|
||||
|
||||
/* Update Flags */
|
||||
bool need_update;
|
||||
bool need_flags_update;
|
||||
|
||||
/* Constructor/Destructor */
|
||||
@@ -204,12 +176,10 @@ class GeometryManager {
|
||||
/* Device Updates */
|
||||
void device_update_preprocess(Device *device, Scene *scene, Progress &progress);
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
void device_free(Device *device, DeviceScene *dscene, bool force_free);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
/* Updates */
|
||||
void tag_update(Scene *scene, uint32_t flag);
|
||||
|
||||
bool need_update() const;
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
/* Statistics */
|
||||
void collect_statistics(const Scene *scene, RenderStats *stats);
|
||||
|
@@ -494,38 +494,33 @@ void Hair::pack_curves(Scene *scene,
|
||||
}
|
||||
}
|
||||
|
||||
void Hair::pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all)
|
||||
void Hair::pack_primitives(PackedBVH &pack, int object, uint visibility)
|
||||
{
|
||||
if (curve_first_key.empty())
|
||||
return;
|
||||
|
||||
/* If the BVH does not have to be recreated, we can bail out. */
|
||||
if (!pack_all) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset];
|
||||
int *prim_type = &pack->prim_type[optix_prim_offset];
|
||||
unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset];
|
||||
int *prim_index = &pack->prim_index[optix_prim_offset];
|
||||
int *prim_object = &pack->prim_object[optix_prim_offset];
|
||||
// 'pack->prim_time' is unused by Embree and OptiX
|
||||
const size_t num_prims = num_segments();
|
||||
pack.prim_tri_index.reserve(pack.prim_tri_index.size() + num_prims);
|
||||
pack.prim_type.reserve(pack.prim_type.size() + num_prims);
|
||||
pack.prim_visibility.reserve(pack.prim_visibility.size() + num_prims);
|
||||
pack.prim_index.reserve(pack.prim_index.size() + num_prims);
|
||||
pack.prim_object.reserve(pack.prim_object.size() + num_prims);
|
||||
// 'pack.prim_time' is unused by Embree and OptiX
|
||||
|
||||
uint type = has_motion_blur() ?
|
||||
((curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
|
||||
PRIMITIVE_MOTION_CURVE_THICK) :
|
||||
((curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK);
|
||||
|
||||
size_t index = 0;
|
||||
for (size_t j = 0; j < num_curves(); ++j) {
|
||||
Curve curve = get_curve(j);
|
||||
for (size_t k = 0; k < curve.num_segments(); ++k, ++index) {
|
||||
prim_tri_index[index] = -1;
|
||||
prim_type[index] = PRIMITIVE_PACK_SEGMENT(type, k);
|
||||
prim_visibility[index] = visibility;
|
||||
for (size_t k = 0; k < curve.num_segments(); ++k) {
|
||||
pack.prim_tri_index.push_back_reserved(-1);
|
||||
pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(type, k));
|
||||
pack.prim_visibility.push_back_reserved(visibility);
|
||||
// Each curve segment points back to its curve index
|
||||
prim_index[index] = j + prim_offset;
|
||||
prim_object[index] = object;
|
||||
pack.prim_index.push_back_reserved(j + prim_offset);
|
||||
pack.prim_object.push_back_reserved(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -146,7 +146,7 @@ class Hair : public Geometry {
|
||||
/* BVH */
|
||||
void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
|
||||
|
||||
void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) override;
|
||||
void pack_primitives(PackedBVH &pack, int object, uint visibility) override;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -298,7 +298,7 @@ bool ImageLoader::is_vdb_loader() const
|
||||
|
||||
ImageManager::ImageManager(const DeviceInfo &info)
|
||||
{
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
osl_texture_system = NULL;
|
||||
animation_frame = 0;
|
||||
|
||||
@@ -451,7 +451,7 @@ int ImageManager::add_image_slot(ImageLoader *loader,
|
||||
|
||||
images[slot] = img;
|
||||
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
|
||||
return slot;
|
||||
}
|
||||
@@ -478,7 +478,7 @@ void ImageManager::remove_image_user(int slot)
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if (image->users == 0)
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
static bool image_associate_alpha(ImageManager::Image *img)
|
||||
@@ -810,7 +810,7 @@ void ImageManager::device_free_image(Device *, int slot)
|
||||
|
||||
void ImageManager::device_update(Device *device, Scene *scene, Progress &progress)
|
||||
{
|
||||
if (!need_update()) {
|
||||
if (!need_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -834,7 +834,7 @@ void ImageManager::device_update(Device *device, Scene *scene, Progress &progres
|
||||
|
||||
pool.wait_work();
|
||||
|
||||
need_update_ = false;
|
||||
need_update = false;
|
||||
}
|
||||
|
||||
void ImageManager::device_update_slot(Device *device, Scene *scene, int slot, Progress *progress)
|
||||
@@ -854,7 +854,7 @@ void ImageManager::device_load_builtin(Device *device, Scene *scene, Progress &p
|
||||
{
|
||||
/* Load only builtin images, Blender needs this to load evaluated
|
||||
* scene data from depsgraph before it is freed. */
|
||||
if (!need_update()) {
|
||||
if (!need_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -896,14 +896,4 @@ void ImageManager::collect_statistics(RenderStats *stats)
|
||||
}
|
||||
}
|
||||
|
||||
void ImageManager::tag_update()
|
||||
{
|
||||
need_update_ = true;
|
||||
}
|
||||
|
||||
bool ImageManager::need_update() const
|
||||
{
|
||||
return need_update_;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -189,9 +189,7 @@ class ImageManager {
|
||||
|
||||
void collect_statistics(RenderStats *stats);
|
||||
|
||||
void tag_update();
|
||||
|
||||
bool need_update() const;
|
||||
bool need_update;
|
||||
|
||||
struct Image {
|
||||
ImageParams params;
|
||||
@@ -211,7 +209,6 @@ class ImageManager {
|
||||
};
|
||||
|
||||
private:
|
||||
bool need_update_;
|
||||
bool has_half_images;
|
||||
|
||||
thread_mutex device_mutex;
|
||||
|
@@ -17,11 +17,9 @@
|
||||
#include "render/integrator.h"
|
||||
#include "device/device.h"
|
||||
#include "render/background.h"
|
||||
#include "render/camera.h"
|
||||
#include "render/film.h"
|
||||
#include "render/jitter.h"
|
||||
#include "render/light.h"
|
||||
#include "render/object.h"
|
||||
#include "render/scene.h"
|
||||
#include "render/shader.h"
|
||||
#include "render/sobol.h"
|
||||
@@ -115,18 +113,6 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
|
||||
}
|
||||
});
|
||||
|
||||
const bool need_update_lut = ao_samples_is_modified() || diffuse_samples_is_modified() ||
|
||||
glossy_samples_is_modified() || max_bounce_is_modified() ||
|
||||
max_transmission_bounce_is_modified() ||
|
||||
mesh_light_samples_is_modified() || method_is_modified() ||
|
||||
sampling_pattern_is_modified() ||
|
||||
subsurface_samples_is_modified() ||
|
||||
transmission_samples_is_modified() || volume_samples_is_modified();
|
||||
|
||||
if (need_update_lut) {
|
||||
dscene->sample_pattern_lut.tag_realloc();
|
||||
}
|
||||
|
||||
device_free(device, dscene);
|
||||
|
||||
KernelIntegrator *kintegrator = &dscene->data.integrator;
|
||||
@@ -256,69 +242,45 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
|
||||
int dimensions = PRNG_BASE_NUM + max_samples * PRNG_BOUNCE_NUM;
|
||||
dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
|
||||
|
||||
if (need_update_lut) {
|
||||
if (sampling_pattern == SAMPLING_PATTERN_SOBOL) {
|
||||
uint *directions = dscene->sample_pattern_lut.alloc(SOBOL_BITS * dimensions);
|
||||
if (sampling_pattern == SAMPLING_PATTERN_SOBOL) {
|
||||
uint *directions = dscene->sample_pattern_lut.alloc(SOBOL_BITS * dimensions);
|
||||
|
||||
sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
|
||||
sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
|
||||
|
||||
dscene->sample_pattern_lut.copy_to_device();
|
||||
}
|
||||
else {
|
||||
constexpr int sequence_size = NUM_PMJ_SAMPLES;
|
||||
constexpr int num_sequences = NUM_PMJ_PATTERNS;
|
||||
float2 *directions = (float2 *)dscene->sample_pattern_lut.alloc(sequence_size *
|
||||
num_sequences * 2);
|
||||
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));
|
||||
}
|
||||
pool.wait_work();
|
||||
dscene->sample_pattern_lut.copy_to_device();
|
||||
dscene->sample_pattern_lut.copy_to_device();
|
||||
}
|
||||
else {
|
||||
constexpr int sequence_size = NUM_PMJ_SAMPLES;
|
||||
constexpr int num_sequences = NUM_PMJ_PATTERNS;
|
||||
float2 *directions = (float2 *)dscene->sample_pattern_lut.alloc(sequence_size * num_sequences *
|
||||
2);
|
||||
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));
|
||||
}
|
||||
pool.wait_work();
|
||||
dscene->sample_pattern_lut.copy_to_device();
|
||||
}
|
||||
|
||||
dscene->sample_pattern_lut.clear_modified();
|
||||
clear_modified();
|
||||
}
|
||||
|
||||
void Integrator::device_free(Device *, DeviceScene *dscene, bool force_free)
|
||||
void Integrator::device_free(Device *, DeviceScene *dscene)
|
||||
{
|
||||
dscene->sample_pattern_lut.free_if_need_realloc(force_free);
|
||||
dscene->sample_pattern_lut.free();
|
||||
}
|
||||
|
||||
void Integrator::tag_update(Scene *scene, uint32_t flag)
|
||||
void Integrator::tag_update(Scene *scene)
|
||||
{
|
||||
if (flag & UPDATE_ALL) {
|
||||
tag_modified();
|
||||
}
|
||||
|
||||
if (flag & (AO_PASS_MODIFIED | BACKGROUND_AO_MODIFIED)) {
|
||||
/* tag only the ao_bounces socket as modified so we avoid updating sample_pattern_lut
|
||||
* unnecessarily */
|
||||
tag_ao_bounces_modified();
|
||||
}
|
||||
|
||||
if ((flag & LIGHT_SAMPLES_MODIFIED) && (method == BRANCHED_PATH)) {
|
||||
/* the number of light samples may affect the size of the sample_pattern_lut */
|
||||
tag_sampling_pattern_modified();
|
||||
}
|
||||
|
||||
if (filter_glossy_is_modified()) {
|
||||
foreach (Shader *shader, scene->shaders) {
|
||||
if (shader->has_integrator_dependency) {
|
||||
scene->shader_manager->tag_update(scene, ShaderManager::INTEGRATOR_MODIFIED);
|
||||
break;
|
||||
}
|
||||
foreach (Shader *shader, scene->shaders) {
|
||||
if (shader->has_integrator_dependency) {
|
||||
scene->shader_manager->need_update = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (motion_blur_is_modified()) {
|
||||
scene->object_manager->tag_update(scene, ObjectManager::MOTION_BLUR_MODIFIED);
|
||||
scene->camera->tag_modified();
|
||||
}
|
||||
tag_modified();
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -89,24 +89,13 @@ class Integrator : public Node {
|
||||
|
||||
NODE_SOCKET_API(SamplingPattern, sampling_pattern)
|
||||
|
||||
enum : uint32_t {
|
||||
AO_PASS_MODIFIED = (1 << 0),
|
||||
BACKGROUND_AO_MODIFIED = (1 << 1),
|
||||
LIGHT_SAMPLES_MODIFIED = (1 << 2),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
||||
UPDATE_NONE = 0u,
|
||||
};
|
||||
|
||||
Integrator();
|
||||
~Integrator();
|
||||
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
|
||||
void device_free(Device *device, DeviceScene *dscene, bool force_free = false);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
void tag_update(Scene *scene, uint32_t flag);
|
||||
void tag_update(Scene *scene);
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -162,13 +162,7 @@ Light::Light() : Node(node_type)
|
||||
|
||||
void Light::tag_update(Scene *scene)
|
||||
{
|
||||
if (is_modified()) {
|
||||
scene->light_manager->tag_update(scene, LightManager::LIGHT_MODIFIED);
|
||||
|
||||
if (samples_is_modified()) {
|
||||
scene->integrator->tag_update(scene, Integrator::LIGHT_SAMPLES_MODIFIED);
|
||||
}
|
||||
}
|
||||
scene->light_manager->need_update = is_modified();
|
||||
}
|
||||
|
||||
bool Light::has_contribution(Scene *scene)
|
||||
@@ -189,7 +183,7 @@ bool Light::has_contribution(Scene *scene)
|
||||
|
||||
LightManager::LightManager()
|
||||
{
|
||||
update_flags = UPDATE_ALL;
|
||||
need_update = true;
|
||||
need_update_background = true;
|
||||
use_light_visibility = false;
|
||||
last_background_enabled = false;
|
||||
@@ -968,7 +962,7 @@ void LightManager::device_update(Device *device,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
@@ -1006,7 +1000,7 @@ void LightManager::device_update(Device *device,
|
||||
|
||||
scene->film->set_use_light_visibility(use_light_visibility);
|
||||
|
||||
update_flags = UPDATE_NONE;
|
||||
need_update = false;
|
||||
need_update_background = false;
|
||||
}
|
||||
|
||||
@@ -1021,14 +1015,9 @@ void LightManager::device_free(Device *, DeviceScene *dscene, const bool free_ba
|
||||
dscene->ies_lights.free();
|
||||
}
|
||||
|
||||
void LightManager::tag_update(Scene * /*scene*/, uint32_t flag)
|
||||
void LightManager::tag_update(Scene * /*scene*/)
|
||||
{
|
||||
update_flags |= flag;
|
||||
}
|
||||
|
||||
bool LightManager::need_update() const
|
||||
{
|
||||
return update_flags != UPDATE_NONE;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
int LightManager::add_ies_from_file(const string &filename)
|
||||
@@ -1074,7 +1063,7 @@ int LightManager::add_ies(const string &content)
|
||||
ies_slots[slot]->users = 1;
|
||||
ies_slots[slot]->hash = hash;
|
||||
|
||||
update_flags = UPDATE_ALL;
|
||||
need_update = true;
|
||||
need_update_background = true;
|
||||
|
||||
return slot;
|
||||
@@ -1093,10 +1082,8 @@ void LightManager::remove_ies(int slot)
|
||||
ies_slots[slot]->users--;
|
||||
|
||||
/* If the slot has no more users, update the device to remove it. */
|
||||
if (ies_slots[slot]->users == 0) {
|
||||
update_flags |= UPDATE_ALL;
|
||||
need_update_background = true;
|
||||
}
|
||||
need_update |= (ies_slots[slot]->users == 0);
|
||||
need_update_background |= need_update;
|
||||
}
|
||||
|
||||
void LightManager::device_update_ies(DeviceScene *dscene)
|
||||
|
@@ -91,23 +91,8 @@ class Light : public Node {
|
||||
|
||||
class LightManager {
|
||||
public:
|
||||
enum : uint32_t {
|
||||
MESH_NEED_REBUILD = (1 << 0),
|
||||
EMISSIVE_MESH_MODIFIED = (1 << 1),
|
||||
LIGHT_MODIFIED = (1 << 2),
|
||||
LIGHT_ADDED = (1 << 3),
|
||||
LIGHT_REMOVED = (1 << 4),
|
||||
OBJECT_MANAGER = (1 << 5),
|
||||
SHADER_COMPILED = (1 << 6),
|
||||
SHADER_MODIFIED = (1 << 7),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
||||
UPDATE_NONE = 0u,
|
||||
};
|
||||
|
||||
bool use_light_visibility;
|
||||
bool need_update;
|
||||
|
||||
/* Need to update background (including multiple importance map) */
|
||||
bool need_update_background;
|
||||
@@ -123,9 +108,7 @@ class LightManager {
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
void device_free(Device *device, DeviceScene *dscene, const bool free_background = true);
|
||||
|
||||
void tag_update(Scene *scene, uint32_t flag);
|
||||
|
||||
bool need_update() const;
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
/* Check whether there is a background light. */
|
||||
bool has_background_light(Scene *scene);
|
||||
@@ -162,8 +145,6 @@ class LightManager {
|
||||
|
||||
bool last_background_enabled;
|
||||
int last_background_resolution;
|
||||
|
||||
uint32_t update_flags;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -805,42 +805,34 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::pack_primitives(ccl::PackedBVH *pack, int object, uint visibility, bool pack_all)
|
||||
void Mesh::pack_primitives(PackedBVH &pack, int object, uint visibility)
|
||||
{
|
||||
if (triangles.empty())
|
||||
return;
|
||||
|
||||
const size_t num_prims = num_triangles();
|
||||
|
||||
/* Use prim_offset for indexing as it is computed per geometry type, and prim_tri_verts does not
|
||||
* contain data for Hair geometries. */
|
||||
float4 *prim_tri_verts = &pack->prim_tri_verts[prim_offset * 3];
|
||||
// 'pack->prim_time' is unused by Embree and OptiX
|
||||
pack.prim_tri_index.reserve(pack.prim_tri_index.size() + num_prims);
|
||||
pack.prim_tri_verts.reserve(pack.prim_tri_verts.size() + num_prims * 3);
|
||||
pack.prim_type.reserve(pack.prim_type.size() + num_prims);
|
||||
pack.prim_visibility.reserve(pack.prim_visibility.size() + num_prims);
|
||||
pack.prim_index.reserve(pack.prim_index.size() + num_prims);
|
||||
pack.prim_object.reserve(pack.prim_object.size() + num_prims);
|
||||
// 'pack.prim_time' is unused by Embree and OptiX
|
||||
|
||||
uint type = has_motion_blur() ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE;
|
||||
|
||||
if (pack_all) {
|
||||
/* Use optix_prim_offset for indexing as those arrays also contain data for Hair geometries. */
|
||||
unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset];
|
||||
int *prim_type = &pack->prim_type[optix_prim_offset];
|
||||
unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset];
|
||||
int *prim_index = &pack->prim_index[optix_prim_offset];
|
||||
int *prim_object = &pack->prim_object[optix_prim_offset];
|
||||
|
||||
for (size_t k = 0; k < num_prims; ++k) {
|
||||
prim_tri_index[k] = (prim_offset + k) * 3;
|
||||
prim_type[k] = type;
|
||||
prim_index[k] = prim_offset + k;
|
||||
prim_object[k] = object;
|
||||
prim_visibility[k] = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < num_prims; ++k) {
|
||||
pack.prim_tri_index.push_back_reserved(pack.prim_tri_verts.size());
|
||||
|
||||
const Mesh::Triangle t = get_triangle(k);
|
||||
prim_tri_verts[k * 3] = float3_to_float4(verts[t.v[0]]);
|
||||
prim_tri_verts[k * 3 + 1] = float3_to_float4(verts[t.v[1]]);
|
||||
prim_tri_verts[k * 3 + 2] = float3_to_float4(verts[t.v[2]]);
|
||||
pack.prim_tri_verts.push_back_reserved(float3_to_float4(verts[t.v[0]]));
|
||||
pack.prim_tri_verts.push_back_reserved(float3_to_float4(verts[t.v[1]]));
|
||||
pack.prim_tri_verts.push_back_reserved(float3_to_float4(verts[t.v[2]]));
|
||||
|
||||
pack.prim_type.push_back_reserved(type);
|
||||
pack.prim_visibility.push_back_reserved(visibility);
|
||||
pack.prim_index.push_back_reserved(k + prim_offset);
|
||||
pack.prim_object.push_back_reserved(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -232,7 +232,7 @@ class Mesh : public Geometry {
|
||||
size_t tri_offset);
|
||||
void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
|
||||
|
||||
void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) override;
|
||||
void pack_primitives(PackedBVH &pack, int object, uint visibility) override;
|
||||
|
||||
void tessellate(DiagSplit *split);
|
||||
|
||||
|
@@ -153,10 +153,6 @@ void Object::update_motion()
|
||||
|
||||
void Object::compute_bounds(bool motion_blur)
|
||||
{
|
||||
if (!is_modified() && !geometry->is_modified()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BoundBox mbounds = geometry->bounds;
|
||||
|
||||
if (motion_blur && use_motion()) {
|
||||
@@ -209,39 +205,20 @@ void Object::apply_transform(bool apply_to_motion)
|
||||
|
||||
void Object::tag_update(Scene *scene)
|
||||
{
|
||||
uint32_t flag = ObjectManager::UPDATE_NONE;
|
||||
|
||||
if (is_modified()) {
|
||||
flag |= ObjectManager::OBJECT_MODIFIED;
|
||||
|
||||
if (use_holdout_is_modified()) {
|
||||
flag |= ObjectManager::HOLDOUT_MODIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
if (geometry) {
|
||||
if (tfm_is_modified()) {
|
||||
/* tag the geometry as modified so the BVH is updated, but do not tag everything as modified
|
||||
*/
|
||||
if (geometry->is_mesh() || geometry->is_volume()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geometry);
|
||||
mesh->tag_verts_modified();
|
||||
}
|
||||
else if (geometry->is_hair()) {
|
||||
Hair *hair = static_cast<Hair *>(geometry);
|
||||
hair->tag_curve_keys_modified();
|
||||
}
|
||||
}
|
||||
if (geometry->transform_applied)
|
||||
geometry->tag_modified();
|
||||
|
||||
foreach (Node *node, geometry->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->get_use_mis() && shader->has_surface_emission)
|
||||
scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED);
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
scene->camera->need_flags_update = true;
|
||||
scene->object_manager->tag_update(scene, flag);
|
||||
scene->geometry_manager->need_update = true;
|
||||
scene->object_manager->need_update = true;
|
||||
}
|
||||
|
||||
bool Object::use_motion() const
|
||||
@@ -384,7 +361,7 @@ int Object::get_device_index() const
|
||||
|
||||
ObjectManager::ObjectManager()
|
||||
{
|
||||
update_flags = UPDATE_ALL;
|
||||
need_update = true;
|
||||
need_flags_update = true;
|
||||
}
|
||||
|
||||
@@ -405,9 +382,7 @@ static float object_volume_density(const Transform &tfm, Geometry *geom)
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state,
|
||||
Object *ob,
|
||||
bool update_all)
|
||||
void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob)
|
||||
{
|
||||
KernelObject &kobject = state->objects[ob->index];
|
||||
Transform *object_motion_pass = state->object_motion_pass;
|
||||
@@ -481,11 +456,8 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
|
||||
kobject.motion_offset = state->motion_offset[ob->index];
|
||||
|
||||
/* Decompose transforms for interpolation. */
|
||||
if (ob->tfm_is_modified() || update_all) {
|
||||
DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
|
||||
transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
|
||||
}
|
||||
|
||||
DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
|
||||
transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
|
||||
flag |= SD_OBJECT_MOTION;
|
||||
state->have_motion = true;
|
||||
}
|
||||
@@ -508,14 +480,10 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
|
||||
0;
|
||||
kobject.patch_map_offset = 0;
|
||||
kobject.attribute_map_offset = 0;
|
||||
|
||||
if (ob->asset_name_is_modified() || update_all) {
|
||||
uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
|
||||
uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
|
||||
kobject.cryptomatte_object = util_hash_to_float(hash_name);
|
||||
kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
|
||||
}
|
||||
|
||||
uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
|
||||
uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
|
||||
kobject.cryptomatte_object = util_hash_to_float(hash_name);
|
||||
kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
|
||||
kobject.shadow_terminator_offset = 1.0f / (1.0f - 0.5f * ob->shadow_terminator_offset);
|
||||
|
||||
/* Object flag. */
|
||||
@@ -576,9 +544,6 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene,
|
||||
numparticles += psys->particles.size();
|
||||
}
|
||||
|
||||
/* as all the arrays are the same size, checking only dscene.objects is sufficient */
|
||||
const bool update_all = dscene->objects.need_realloc();
|
||||
|
||||
/* Parallel object update, with grain size to avoid too much threading overhead
|
||||
* for individual objects. */
|
||||
static const int OBJECTS_PER_TASK = 32;
|
||||
@@ -586,7 +551,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene,
|
||||
[&](const blocked_range<size_t> &r) {
|
||||
for (size_t i = r.begin(); i != r.end(); i++) {
|
||||
Object *ob = state.scene->objects[i];
|
||||
device_update_object_transform(&state, ob, update_all);
|
||||
device_update_object_transform(&state, ob);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -594,7 +559,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene,
|
||||
return;
|
||||
}
|
||||
|
||||
dscene->objects.copy_to_device_if_modified();
|
||||
dscene->objects.copy_to_device();
|
||||
if (state.need_motion == Scene::MOTION_PASS) {
|
||||
dscene->object_motion_pass.copy_to_device();
|
||||
}
|
||||
@@ -604,10 +569,6 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene,
|
||||
|
||||
dscene->data.bvh.have_motion = state.have_motion;
|
||||
dscene->data.bvh.have_curves = state.have_curves;
|
||||
|
||||
dscene->objects.clear_modified();
|
||||
dscene->object_motion_pass.clear_modified();
|
||||
dscene->object_motion.clear_modified();
|
||||
}
|
||||
|
||||
void ObjectManager::device_update(Device *device,
|
||||
@@ -615,28 +576,12 @@ void ObjectManager::device_update(Device *device,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
if (update_flags & (OBJECT_ADDED | OBJECT_REMOVED)) {
|
||||
dscene->objects.tag_realloc();
|
||||
dscene->object_motion_pass.tag_realloc();
|
||||
dscene->object_motion.tag_realloc();
|
||||
dscene->object_flag.tag_realloc();
|
||||
dscene->object_volume_step.tag_realloc();
|
||||
}
|
||||
|
||||
if (update_flags & HOLDOUT_MODIFIED) {
|
||||
dscene->object_flag.tag_modified();
|
||||
}
|
||||
|
||||
if (update_flags & PARTICLE_MODIFIED) {
|
||||
dscene->objects.tag_modified();
|
||||
}
|
||||
|
||||
VLOG(1) << "Total " << scene->objects.size() << " objects.";
|
||||
|
||||
device_free(device, dscene, false);
|
||||
device_free(device, dscene);
|
||||
|
||||
if (scene->objects.size() == 0)
|
||||
return;
|
||||
@@ -652,16 +597,6 @@ void ObjectManager::device_update(Device *device,
|
||||
int index = 0;
|
||||
foreach (Object *object, scene->objects) {
|
||||
object->index = index++;
|
||||
|
||||
/* this is a bit too broad, however a bigger refactor might be needed to properly separate
|
||||
* update each type of data (transform, flags, etc.) */
|
||||
if (object->is_modified()) {
|
||||
dscene->objects.tag_modified();
|
||||
dscene->object_motion_pass.tag_modified();
|
||||
dscene->object_motion.tag_modified();
|
||||
dscene->object_flag.tag_modified();
|
||||
dscene->object_volume_step.tag_modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,7 +638,7 @@ void ObjectManager::device_update(Device *device,
|
||||
void ObjectManager::device_update_flags(
|
||||
Device *, DeviceScene *dscene, Scene *scene, Progress & /*progress*/, bool bounds_valid)
|
||||
{
|
||||
if (!need_update() && !need_flags_update)
|
||||
if (!need_update && !need_flags_update)
|
||||
return;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
@@ -712,7 +647,7 @@ void ObjectManager::device_update_flags(
|
||||
}
|
||||
});
|
||||
|
||||
update_flags = UPDATE_NONE;
|
||||
need_update = false;
|
||||
need_flags_update = false;
|
||||
|
||||
if (scene->objects.size() == 0)
|
||||
@@ -782,9 +717,6 @@ void ObjectManager::device_update_flags(
|
||||
/* Copy object flag. */
|
||||
dscene->object_flag.copy_to_device();
|
||||
dscene->object_volume_step.copy_to_device();
|
||||
|
||||
dscene->object_flag.clear_modified();
|
||||
dscene->object_volume_step.clear_modified();
|
||||
}
|
||||
|
||||
void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Scene *scene)
|
||||
@@ -832,13 +764,13 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectManager::device_free(Device *, DeviceScene *dscene, bool force_free)
|
||||
void ObjectManager::device_free(Device *, DeviceScene *dscene)
|
||||
{
|
||||
dscene->objects.free_if_need_realloc(force_free);
|
||||
dscene->object_motion_pass.free_if_need_realloc(force_free);
|
||||
dscene->object_motion.free_if_need_realloc(force_free);
|
||||
dscene->object_flag.free_if_need_realloc(force_free);
|
||||
dscene->object_volume_step.free_if_need_realloc(force_free);
|
||||
dscene->objects.free();
|
||||
dscene->object_motion_pass.free();
|
||||
dscene->object_motion.free();
|
||||
dscene->object_flag.free();
|
||||
dscene->object_volume_step.free();
|
||||
}
|
||||
|
||||
void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
|
||||
@@ -909,21 +841,11 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectManager::tag_update(Scene *scene, uint32_t flag)
|
||||
void ObjectManager::tag_update(Scene *scene)
|
||||
{
|
||||
update_flags |= flag;
|
||||
|
||||
/* avoid infinite loops if the geometry manager tagged us for an update */
|
||||
if ((flag & GEOMETRY_MANAGER) == 0) {
|
||||
scene->geometry_manager->tag_update(scene, GeometryManager::OBJECT_MANAGER);
|
||||
}
|
||||
|
||||
scene->light_manager->tag_update(scene, LightManager::OBJECT_MANAGER);
|
||||
}
|
||||
|
||||
bool ObjectManager::need_update() const
|
||||
{
|
||||
return update_flags != UPDATE_NONE;
|
||||
need_update = true;
|
||||
scene->geometry_manager->need_update = true;
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
|
||||
string ObjectManager::get_cryptomatte_objects(Scene *scene)
|
||||
|
@@ -122,24 +122,8 @@ class Object : public Node {
|
||||
/* Object Manager */
|
||||
|
||||
class ObjectManager {
|
||||
uint32_t update_flags;
|
||||
|
||||
public:
|
||||
enum : uint32_t {
|
||||
PARTICLE_MODIFIED = (1 << 0),
|
||||
GEOMETRY_MANAGER = (1 << 1),
|
||||
MOTION_BLUR_MODIFIED = (1 << 2),
|
||||
OBJECT_ADDED = (1 << 3),
|
||||
OBJECT_REMOVED = (1 << 4),
|
||||
OBJECT_MODIFIED = (1 << 5),
|
||||
HOLDOUT_MODIFIED = (1 << 6),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
||||
UPDATE_NONE = 0u,
|
||||
};
|
||||
|
||||
bool need_update;
|
||||
bool need_flags_update;
|
||||
|
||||
ObjectManager();
|
||||
@@ -155,11 +139,9 @@ class ObjectManager {
|
||||
bool bounds_valid = true);
|
||||
void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene);
|
||||
|
||||
void device_free(Device *device, DeviceScene *dscene, bool force_free);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
void tag_update(Scene *scene, uint32_t flag);
|
||||
|
||||
bool need_update() const;
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
|
||||
@@ -167,9 +149,7 @@ class ObjectManager {
|
||||
string get_cryptomatte_assets(Scene *scene);
|
||||
|
||||
protected:
|
||||
void device_update_object_transform(UpdateObjectTransformState *state,
|
||||
Object *ob,
|
||||
bool update_all);
|
||||
void device_update_object_transform(UpdateObjectTransformState *state, Object *ob);
|
||||
void device_update_object_transform_task(UpdateObjectTransformState *state);
|
||||
bool device_update_object_transform_pop_work(UpdateObjectTransformState *state,
|
||||
int *start_index,
|
||||
|
@@ -96,7 +96,7 @@ void OSLShaderManager::device_update(Device *device,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
@@ -132,7 +132,7 @@ void OSLShaderManager::device_update(Device *device,
|
||||
compiler.compile(og, shader);
|
||||
|
||||
if (shader->get_use_mis() && shader->has_surface_emission)
|
||||
scene->light_manager->tag_update(scene, LightManager::SHADER_COMPILED);
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
|
||||
/* setup shader engine */
|
||||
@@ -147,7 +147,7 @@ void OSLShaderManager::device_update(Device *device,
|
||||
foreach (Shader *shader, scene->shaders)
|
||||
shader->clear_modified();
|
||||
|
||||
update_flags = UPDATE_NONE;
|
||||
need_update = false;
|
||||
|
||||
/* add special builtin texture types */
|
||||
services->textures.insert(ustring("@ao"), new OSLTextureHandle(OSLTextureHandle::AO));
|
||||
|
@@ -46,14 +46,14 @@ ParticleSystem::~ParticleSystem()
|
||||
|
||||
void ParticleSystem::tag_update(Scene *scene)
|
||||
{
|
||||
scene->particle_system_manager->tag_update(scene);
|
||||
scene->particle_system_manager->need_update = true;
|
||||
}
|
||||
|
||||
/* Particle System Manager */
|
||||
|
||||
ParticleSystemManager::ParticleSystemManager()
|
||||
{
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
ParticleSystemManager::~ParticleSystemManager()
|
||||
@@ -109,7 +109,7 @@ void ParticleSystemManager::device_update(Device *device,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
@@ -128,7 +128,7 @@ void ParticleSystemManager::device_update(Device *device,
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
need_update_ = false;
|
||||
need_update = false;
|
||||
}
|
||||
|
||||
void ParticleSystemManager::device_free(Device *, DeviceScene *dscene)
|
||||
@@ -138,12 +138,7 @@ void ParticleSystemManager::device_free(Device *, DeviceScene *dscene)
|
||||
|
||||
void ParticleSystemManager::tag_update(Scene * /*scene*/)
|
||||
{
|
||||
need_update_ = true;
|
||||
}
|
||||
|
||||
bool ParticleSystemManager::need_update() const
|
||||
{
|
||||
return need_update_;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -57,9 +57,9 @@ class ParticleSystem : public Node {
|
||||
/* ParticleSystem Manager */
|
||||
|
||||
class ParticleSystemManager {
|
||||
bool need_update_;
|
||||
|
||||
public:
|
||||
bool need_update;
|
||||
|
||||
ParticleSystemManager();
|
||||
~ParticleSystemManager();
|
||||
|
||||
@@ -71,8 +71,6 @@ class ParticleSystemManager {
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
bool need_update() const;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2018 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "procedural.h"
|
||||
|
||||
#include "render/scene.h"
|
||||
#include "render/stats.h"
|
||||
|
||||
#include "util/util_foreach.h"
|
||||
#include "util/util_progress.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
NODE_ABSTRACT_DEFINE(Procedural)
|
||||
{
|
||||
NodeType *type = NodeType::add("procedural_base", NULL);
|
||||
return type;
|
||||
}
|
||||
|
||||
Procedural::Procedural(const NodeType *type) : Node(type)
|
||||
{
|
||||
}
|
||||
|
||||
Procedural::~Procedural()
|
||||
{
|
||||
}
|
||||
|
||||
ProceduralManager::ProceduralManager()
|
||||
{
|
||||
need_update_ = true;
|
||||
}
|
||||
|
||||
ProceduralManager::~ProceduralManager()
|
||||
{
|
||||
}
|
||||
|
||||
void ProceduralManager::update(Scene *scene, Progress &progress)
|
||||
{
|
||||
if (!need_update()) {
|
||||
return;
|
||||
}
|
||||
|
||||
progress.set_status("Updating Procedurals");
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
if (scene->update_stats) {
|
||||
scene->update_stats->procedurals.times.add_entry({"update", time});
|
||||
}
|
||||
});
|
||||
|
||||
foreach (Procedural *procedural, scene->procedurals) {
|
||||
if (progress.get_cancel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
procedural->generate(scene, progress);
|
||||
}
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
need_update_ = false;
|
||||
}
|
||||
|
||||
void ProceduralManager::tag_update()
|
||||
{
|
||||
need_update_ = true;
|
||||
}
|
||||
|
||||
bool ProceduralManager::need_update() const
|
||||
{
|
||||
return need_update_;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2018 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "graph/node.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Progress;
|
||||
class Scene;
|
||||
|
||||
/* A Procedural is a Node which can create other Nodes before rendering starts.
|
||||
*
|
||||
* The Procedural is supposed to be the owner of any nodes that it creates. It can also create
|
||||
* Nodes directly in the Scene (through Scene.create_node), it should still be set as the owner of
|
||||
* those Nodes.
|
||||
*/
|
||||
class Procedural : public Node, public NodeOwner {
|
||||
public:
|
||||
NODE_ABSTRACT_DECLARE
|
||||
|
||||
explicit Procedural(const NodeType *type);
|
||||
virtual ~Procedural();
|
||||
|
||||
/* Called each time the ProceduralManager is tagged for an update, this function is the entry
|
||||
* point for the data generated by this Procedural. */
|
||||
virtual void generate(Scene *scene, Progress &progress) = 0;
|
||||
|
||||
/* Create a node and set this Procedural as the owner. */
|
||||
template<typename T> T *create_node()
|
||||
{
|
||||
T *node = new T();
|
||||
node->set_owner(this);
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Delete a Node created and owned by this Procedural. */
|
||||
template<typename T> void delete_node(T *node)
|
||||
{
|
||||
assert(node->get_owner() == this);
|
||||
delete node;
|
||||
}
|
||||
};
|
||||
|
||||
class ProceduralManager {
|
||||
bool need_update_;
|
||||
|
||||
public:
|
||||
ProceduralManager();
|
||||
~ProceduralManager();
|
||||
|
||||
void update(Scene *scene, Progress &progress);
|
||||
|
||||
void tag_update();
|
||||
|
||||
bool need_update() const;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
@@ -18,7 +18,6 @@
|
||||
|
||||
#include "bvh/bvh.h"
|
||||
#include "device/device.h"
|
||||
#include "render/alembic.h"
|
||||
#include "render/background.h"
|
||||
#include "render/bake.h"
|
||||
#include "render/camera.h"
|
||||
@@ -30,7 +29,6 @@
|
||||
#include "render/object.h"
|
||||
#include "render/osl.h"
|
||||
#include "render/particles.h"
|
||||
#include "render/procedural.h"
|
||||
#include "render/scene.h"
|
||||
#include "render/session.h"
|
||||
#include "render/shader.h"
|
||||
@@ -116,7 +114,6 @@ Scene::Scene(const SceneParams ¶ms_, Device *device)
|
||||
image_manager = new ImageManager(device->info);
|
||||
particle_system_manager = new ParticleSystemManager();
|
||||
bake_manager = new BakeManager();
|
||||
procedural_manager = new ProceduralManager();
|
||||
kernels_loaded = false;
|
||||
|
||||
/* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
|
||||
@@ -145,9 +142,6 @@ void Scene::free_memory(bool final)
|
||||
|
||||
foreach (Shader *s, shaders)
|
||||
delete s;
|
||||
/* delete procedurals before other types as they may hold pointers to those types */
|
||||
foreach (Procedural *p, procedurals)
|
||||
delete p;
|
||||
foreach (Geometry *g, geometry)
|
||||
delete g;
|
||||
foreach (Object *o, objects)
|
||||
@@ -162,16 +156,15 @@ void Scene::free_memory(bool final)
|
||||
objects.clear();
|
||||
lights.clear();
|
||||
particle_systems.clear();
|
||||
procedurals.clear();
|
||||
|
||||
if (device) {
|
||||
camera->device_free(device, &dscene, this);
|
||||
film->device_free(device, &dscene, this);
|
||||
background->device_free(device, &dscene);
|
||||
integrator->device_free(device, &dscene, true);
|
||||
integrator->device_free(device, &dscene);
|
||||
|
||||
object_manager->device_free(device, &dscene, true);
|
||||
geometry_manager->device_free(device, &dscene, true);
|
||||
object_manager->device_free(device, &dscene);
|
||||
geometry_manager->device_free(device, &dscene);
|
||||
shader_manager->device_free(device, &dscene, this);
|
||||
light_manager->device_free(device, &dscene);
|
||||
|
||||
@@ -202,7 +195,6 @@ void Scene::free_memory(bool final)
|
||||
delete image_manager;
|
||||
delete bake_manager;
|
||||
delete update_stats;
|
||||
delete procedural_manager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,11 +236,6 @@ void Scene::device_update(Device *device_, Progress &progress)
|
||||
if (progress.get_cancel() || device->have_error())
|
||||
return;
|
||||
|
||||
procedural_manager->update(this, progress);
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
progress.set_status("Updating Background");
|
||||
background->device_update(device, &dscene, this);
|
||||
|
||||
@@ -399,12 +386,11 @@ bool Scene::need_update()
|
||||
|
||||
bool Scene::need_data_update()
|
||||
{
|
||||
return (background->is_modified() || image_manager->need_update() ||
|
||||
object_manager->need_update() || geometry_manager->need_update() ||
|
||||
light_manager->need_update() || lookup_tables->need_update() ||
|
||||
integrator->is_modified() || shader_manager->need_update() ||
|
||||
particle_system_manager->need_update() || bake_manager->need_update() ||
|
||||
film->is_modified() || procedural_manager->need_update());
|
||||
return (background->is_modified() || image_manager->need_update || object_manager->need_update ||
|
||||
geometry_manager->need_update || light_manager->need_update ||
|
||||
lookup_tables->need_update || integrator->is_modified() || shader_manager->need_update ||
|
||||
particle_system_manager->need_update || bake_manager->need_update ||
|
||||
film->is_modified());
|
||||
}
|
||||
|
||||
bool Scene::need_reset()
|
||||
@@ -421,15 +407,12 @@ void Scene::reset()
|
||||
camera->tag_modified();
|
||||
dicing_camera->tag_modified();
|
||||
film->tag_modified();
|
||||
background->tag_modified();
|
||||
|
||||
background->tag_update(this);
|
||||
integrator->tag_update(this, Integrator::UPDATE_ALL);
|
||||
object_manager->tag_update(this, ObjectManager::UPDATE_ALL);
|
||||
geometry_manager->tag_update(this, GeometryManager::UPDATE_ALL);
|
||||
light_manager->tag_update(this, LightManager::UPDATE_ALL);
|
||||
integrator->tag_update(this);
|
||||
object_manager->tag_update(this);
|
||||
geometry_manager->tag_update(this);
|
||||
light_manager->tag_update(this);
|
||||
particle_system_manager->tag_update(this);
|
||||
procedural_manager->tag_update();
|
||||
}
|
||||
|
||||
void Scene::device_free()
|
||||
@@ -613,7 +596,7 @@ template<> Light *Scene::create_node<Light>()
|
||||
Light *node = new Light();
|
||||
node->set_owner(this);
|
||||
lights.push_back(node);
|
||||
light_manager->tag_update(this, LightManager::LIGHT_ADDED);
|
||||
light_manager->tag_update(this);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -622,7 +605,7 @@ template<> Mesh *Scene::create_node<Mesh>()
|
||||
Mesh *node = new Mesh();
|
||||
node->set_owner(this);
|
||||
geometry.push_back(node);
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_ADDED);
|
||||
geometry_manager->tag_update(this);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -631,7 +614,7 @@ template<> Hair *Scene::create_node<Hair>()
|
||||
Hair *node = new Hair();
|
||||
node->set_owner(this);
|
||||
geometry.push_back(node);
|
||||
geometry_manager->tag_update(this, GeometryManager::HAIR_ADDED);
|
||||
geometry_manager->tag_update(this);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -640,7 +623,7 @@ template<> Volume *Scene::create_node<Volume>()
|
||||
Volume *node = new Volume();
|
||||
node->set_owner(this);
|
||||
geometry.push_back(node);
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_ADDED);
|
||||
geometry_manager->tag_update(this);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -649,7 +632,7 @@ template<> Object *Scene::create_node<Object>()
|
||||
Object *node = new Object();
|
||||
node->set_owner(this);
|
||||
objects.push_back(node);
|
||||
object_manager->tag_update(this, ObjectManager::OBJECT_ADDED);
|
||||
object_manager->tag_update(this);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -667,23 +650,10 @@ template<> Shader *Scene::create_node<Shader>()
|
||||
Shader *node = new Shader();
|
||||
node->set_owner(this);
|
||||
shaders.push_back(node);
|
||||
shader_manager->tag_update(this, ShaderManager::SHADER_ADDED);
|
||||
shader_manager->need_update = true;
|
||||
return node;
|
||||
}
|
||||
|
||||
template<> AlembicProcedural *Scene::create_node<AlembicProcedural>()
|
||||
{
|
||||
#ifdef WITH_ALEMBIC
|
||||
AlembicProcedural *node = new AlembicProcedural();
|
||||
node->set_owner(this);
|
||||
procedurals.push_back(node);
|
||||
procedural_manager->tag_update();
|
||||
return node;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T> void delete_node_from_array(vector<T> &nodes, T node)
|
||||
{
|
||||
for (size_t i = 0; i < nodes.size(); ++i) {
|
||||
@@ -694,52 +664,43 @@ template<typename T> void delete_node_from_array(vector<T> &nodes, T node)
|
||||
}
|
||||
|
||||
nodes.resize(nodes.size() - 1);
|
||||
|
||||
delete node;
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Light *node)
|
||||
{
|
||||
delete_node_from_array(lights, node);
|
||||
light_manager->tag_update(this, LightManager::LIGHT_REMOVED);
|
||||
light_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Mesh *node)
|
||||
{
|
||||
delete_node_from_array(geometry, static_cast<Geometry *>(node));
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED);
|
||||
geometry_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Hair *node)
|
||||
{
|
||||
delete_node_from_array(geometry, static_cast<Geometry *>(node));
|
||||
geometry_manager->tag_update(this, GeometryManager::HAIR_REMOVED);
|
||||
geometry_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Volume *node)
|
||||
{
|
||||
delete_node_from_array(geometry, static_cast<Geometry *>(node));
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED);
|
||||
geometry_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Geometry *node)
|
||||
{
|
||||
uint flag;
|
||||
if (node->is_hair()) {
|
||||
flag = GeometryManager::HAIR_REMOVED;
|
||||
}
|
||||
else {
|
||||
flag = GeometryManager::MESH_REMOVED;
|
||||
}
|
||||
|
||||
delete_node_from_array(geometry, node);
|
||||
geometry_manager->tag_update(this, flag);
|
||||
geometry_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Object *node)
|
||||
{
|
||||
delete_node_from_array(objects, node);
|
||||
object_manager->tag_update(this, ObjectManager::OBJECT_REMOVED);
|
||||
object_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(ParticleSystem *node)
|
||||
@@ -753,21 +714,6 @@ template<> void Scene::delete_node_impl(Shader * /*node*/)
|
||||
/* don't delete unused shaders, not supported */
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Procedural *node)
|
||||
{
|
||||
delete_node_from_array(procedurals, node);
|
||||
procedural_manager->tag_update();
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(AlembicProcedural *node)
|
||||
{
|
||||
#ifdef WITH_ALEMBIC
|
||||
delete_node_impl(static_cast<Procedural *>(node));
|
||||
#else
|
||||
(void)node;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void remove_nodes_in_set(const set<T *> &nodes_set,
|
||||
vector<T *> &nodes_array,
|
||||
@@ -796,19 +742,19 @@ static void remove_nodes_in_set(const set<T *> &nodes_set,
|
||||
template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, lights, owner);
|
||||
light_manager->tag_update(this, LightManager::LIGHT_REMOVED);
|
||||
light_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, geometry, owner);
|
||||
geometry_manager->tag_update(this, GeometryManager::GEOMETRY_REMOVED);
|
||||
geometry_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Object *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, objects, owner);
|
||||
object_manager->tag_update(this, ObjectManager::OBJECT_REMOVED);
|
||||
object_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const NodeOwner *owner)
|
||||
@@ -822,10 +768,4 @@ template<> void Scene::delete_nodes(const set<Shader *> & /*nodes*/, const NodeO
|
||||
/* don't delete unused shaders, not supported */
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, procedurals, owner);
|
||||
procedural_manager->tag_update();
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -36,7 +36,6 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class AlembicProcedural;
|
||||
class AttributeRequestSet;
|
||||
class Background;
|
||||
class BVH;
|
||||
@@ -54,8 +53,6 @@ class Object;
|
||||
class ObjectManager;
|
||||
class ParticleSystemManager;
|
||||
class ParticleSystem;
|
||||
class Procedural;
|
||||
class ProceduralManager;
|
||||
class CurveSystemManager;
|
||||
class Shader;
|
||||
class ShaderManager;
|
||||
@@ -239,7 +236,6 @@ class Scene : public NodeOwner {
|
||||
vector<Light *> lights;
|
||||
vector<ParticleSystem *> particle_systems;
|
||||
vector<Pass> passes;
|
||||
vector<Procedural *> procedurals;
|
||||
|
||||
/* data managers */
|
||||
ImageManager *image_manager;
|
||||
@@ -249,7 +245,6 @@ class Scene : public NodeOwner {
|
||||
ObjectManager *object_manager;
|
||||
ParticleSystemManager *particle_system_manager;
|
||||
BakeManager *bake_manager;
|
||||
ProceduralManager *procedural_manager;
|
||||
|
||||
/* default shaders */
|
||||
Shader *default_surface;
|
||||
@@ -384,8 +379,6 @@ template<> ParticleSystem *Scene::create_node<ParticleSystem>();
|
||||
|
||||
template<> Shader *Scene::create_node<Shader>();
|
||||
|
||||
template<> AlembicProcedural *Scene::create_node<AlembicProcedural>();
|
||||
|
||||
template<> void Scene::delete_node_impl(Light *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Mesh *node);
|
||||
@@ -402,10 +395,6 @@ template<> void Scene::delete_node_impl(ParticleSystem *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Shader *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Procedural *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(AlembicProcedural *node);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner);
|
||||
@@ -416,8 +405,6 @@ template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const No
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner);
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __SCENE_H__ */
|
||||
|
@@ -1040,7 +1040,13 @@ bool Session::update_scene()
|
||||
BakeManager *bake_manager = scene->bake_manager;
|
||||
|
||||
if (integrator->get_sampling_pattern() != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) {
|
||||
integrator->set_aa_samples(tile_manager.num_samples);
|
||||
int aa_samples = tile_manager.num_samples;
|
||||
|
||||
integrator->set_aa_samples(aa_samples);
|
||||
|
||||
if (integrator->is_modified()) {
|
||||
integrator->tag_update(scene);
|
||||
}
|
||||
}
|
||||
|
||||
bool kernel_switch_needed = false;
|
||||
|
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "render/alembic.h"
|
||||
#include "render/background.h"
|
||||
#include "render/camera.h"
|
||||
#include "render/colorspace.h"
|
||||
@@ -219,9 +218,7 @@ Shader::Shader() : Node(node_type)
|
||||
id = -1;
|
||||
used = false;
|
||||
|
||||
need_update_uvs = true;
|
||||
need_update_attribute = true;
|
||||
need_update_displacement = true;
|
||||
need_update_geometry = true;
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
@@ -294,7 +291,7 @@ void Shader::set_graph(ShaderGraph *graph_)
|
||||
const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
|
||||
|
||||
if (strcmp(old_hash, new_hash) != 0) {
|
||||
need_update_displacement = true;
|
||||
need_update_geometry = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,14 +308,13 @@ void Shader::tag_update(Scene *scene)
|
||||
{
|
||||
/* update tag */
|
||||
tag_modified();
|
||||
|
||||
scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED);
|
||||
scene->shader_manager->need_update = true;
|
||||
|
||||
/* if the shader previously was emissive, update light distribution,
|
||||
* if the new shader is emissive, a light manager update tag will be
|
||||
* done in the shader manager device update. */
|
||||
if (use_mis && has_surface_emission)
|
||||
scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED);
|
||||
scene->light_manager->need_update = true;
|
||||
|
||||
/* Special handle of background MIS light for now: for some reason it
|
||||
* has use_mis set to false. We are quite close to release now, so
|
||||
@@ -327,7 +323,7 @@ void Shader::tag_update(Scene *scene)
|
||||
if (this == scene->background->get_shader(scene)) {
|
||||
scene->light_manager->need_update_background = true;
|
||||
if (scene->light_manager->has_background_light(scene)) {
|
||||
scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED);
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,18 +352,17 @@ void Shader::tag_update(Scene *scene)
|
||||
attributes.add(ATTR_STD_POSITION_UNDISPLACED);
|
||||
}
|
||||
if (displacement_method_is_modified()) {
|
||||
need_update_displacement = true;
|
||||
scene->geometry_manager->tag_update(scene, GeometryManager::SHADER_DISPLACEMENT_MODIFIED);
|
||||
need_update_geometry = true;
|
||||
scene->geometry_manager->need_update = true;
|
||||
scene->object_manager->need_flags_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* compare if the attributes changed, mesh manager will check
|
||||
* need_update_attribute, update the relevant meshes and clear it. */
|
||||
* need_update_geometry, update the relevant meshes and clear it. */
|
||||
if (attributes.modified(prev_attributes)) {
|
||||
need_update_attribute = true;
|
||||
scene->geometry_manager->tag_update(scene, GeometryManager::SHADER_ATTRIBUTE_MODIFIED);
|
||||
scene->procedural_manager->tag_update();
|
||||
need_update_geometry = true;
|
||||
scene->geometry_manager->need_update = true;
|
||||
}
|
||||
|
||||
if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) {
|
||||
@@ -383,20 +378,15 @@ void Shader::tag_used(Scene *scene)
|
||||
* recompiled because it was skipped for compilation before */
|
||||
if (!used) {
|
||||
tag_modified();
|
||||
scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED);
|
||||
scene->shader_manager->need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Shader::need_update_geometry() const
|
||||
{
|
||||
return need_update_uvs || need_update_attribute || need_update_displacement;
|
||||
}
|
||||
|
||||
/* Shader Manager */
|
||||
|
||||
ShaderManager::ShaderManager()
|
||||
{
|
||||
update_flags = UPDATE_ALL;
|
||||
need_update = true;
|
||||
beckmann_table_offset = TABLE_OFFSET_INVALID;
|
||||
|
||||
xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
|
||||
@@ -494,7 +484,7 @@ int ShaderManager::get_shader_id(Shader *shader, bool smooth)
|
||||
|
||||
void ShaderManager::update_shaders_used(Scene *scene)
|
||||
{
|
||||
if (!need_update()) {
|
||||
if (!need_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -514,21 +504,6 @@ void ShaderManager::update_shaders_used(Scene *scene)
|
||||
if (scene->background->get_shader())
|
||||
scene->background->get_shader()->used = true;
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
foreach (Procedural *procedural, scene->procedurals) {
|
||||
AlembicProcedural *abc_proc = static_cast<AlembicProcedural *>(procedural);
|
||||
|
||||
foreach (Node *abc_node, abc_proc->get_objects()) {
|
||||
AlembicObject *abc_object = static_cast<AlembicObject *>(abc_node);
|
||||
|
||||
foreach (Node *node, abc_object->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
shader->used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach (Geometry *geom, scene->geometry)
|
||||
foreach (Node *node, geom->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
@@ -818,15 +793,4 @@ string ShaderManager::get_cryptomatte_materials(Scene *scene)
|
||||
return manifest;
|
||||
}
|
||||
|
||||
void ShaderManager::tag_update(Scene * /*scene*/, uint32_t /*flag*/)
|
||||
{
|
||||
/* update everything for now */
|
||||
update_flags = ShaderManager::UPDATE_ALL;
|
||||
}
|
||||
|
||||
bool ShaderManager::need_update() const
|
||||
{
|
||||
return update_flags != UPDATE_NONE;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -100,9 +100,7 @@ class Shader : public Node {
|
||||
float prev_volume_step_rate;
|
||||
|
||||
/* synchronization */
|
||||
bool need_update_uvs;
|
||||
bool need_update_attribute;
|
||||
bool need_update_displacement;
|
||||
bool need_update_geometry;
|
||||
|
||||
/* If the shader has only volume components, the surface is assumed to
|
||||
* be transparent.
|
||||
@@ -154,8 +152,6 @@ class Shader : public Node {
|
||||
void set_graph(ShaderGraph *graph);
|
||||
void tag_update(Scene *scene);
|
||||
void tag_used(Scene *scene);
|
||||
|
||||
bool need_update_geometry() const;
|
||||
};
|
||||
|
||||
/* Shader Manager virtual base class
|
||||
@@ -165,16 +161,7 @@ class Shader : public Node {
|
||||
|
||||
class ShaderManager {
|
||||
public:
|
||||
enum : uint32_t {
|
||||
SHADER_ADDED = (1 << 0),
|
||||
SHADER_MODIFIED = (1 << 2),
|
||||
INTEGRATOR_MODIFIED = (1 << 3),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
||||
UPDATE_NONE = 0u,
|
||||
};
|
||||
bool need_update;
|
||||
|
||||
static ShaderManager *create(int shadingsystem);
|
||||
virtual ~ShaderManager();
|
||||
@@ -217,15 +204,9 @@ class ShaderManager {
|
||||
|
||||
string get_cryptomatte_materials(Scene *scene);
|
||||
|
||||
void tag_update(Scene *scene, uint32_t flag);
|
||||
|
||||
bool need_update() const;
|
||||
|
||||
protected:
|
||||
ShaderManager();
|
||||
|
||||
uint32_t update_flags;
|
||||
|
||||
typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
|
||||
AttributeIDMap unique_attribute_id;
|
||||
|
||||
|
@@ -375,7 +375,6 @@ string SceneUpdateStats::full_report()
|
||||
result += "Particles:\n" + particles.full_report(1);
|
||||
result += "SVM:\n" + svm.full_report(1);
|
||||
result += "Tables:\n" + tables.full_report(1);
|
||||
result += "Procedurals:\n" + procedurals.full_report(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -395,7 +394,6 @@ void SceneUpdateStats::clear()
|
||||
scene.times.clear();
|
||||
svm.times.clear();
|
||||
tables.times.clear();
|
||||
procedurals.times.clear();
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -219,7 +219,6 @@ class SceneUpdateStats {
|
||||
UpdateTimeStats scene;
|
||||
UpdateTimeStats svm;
|
||||
UpdateTimeStats tables;
|
||||
UpdateTimeStats procedurals;
|
||||
|
||||
string full_report();
|
||||
|
||||
|
@@ -74,7 +74,7 @@ void SVMShaderManager::device_update(Device *device,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
@@ -125,7 +125,7 @@ void SVMShaderManager::device_update(Device *device,
|
||||
|
||||
shader->clear_modified();
|
||||
if (shader->get_use_mis() && shader->has_surface_emission) {
|
||||
scene->light_manager->tag_update(scene, LightManager::SHADER_COMPILED);
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
|
||||
/* Update the global jump table.
|
||||
@@ -159,7 +159,7 @@ void SVMShaderManager::device_update(Device *device,
|
||||
|
||||
device_update_common(device, dscene, scene, progress);
|
||||
|
||||
update_flags = UPDATE_NONE;
|
||||
need_update = false;
|
||||
|
||||
VLOG(1) << "Shader manager updated " << num_shaders << " shaders in " << time_dt() - start_time
|
||||
<< " seconds.";
|
||||
|
@@ -28,7 +28,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
LookupTables::LookupTables()
|
||||
{
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
LookupTables::~LookupTables()
|
||||
@@ -38,7 +38,7 @@ LookupTables::~LookupTables()
|
||||
|
||||
void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene)
|
||||
{
|
||||
if (!need_update())
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
@@ -52,7 +52,7 @@ void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene)
|
||||
if (lookup_tables.size() > 0)
|
||||
dscene->lookup_table.copy_to_device();
|
||||
|
||||
need_update_ = false;
|
||||
need_update = false;
|
||||
}
|
||||
|
||||
void LookupTables::device_free(Device *, DeviceScene *dscene)
|
||||
@@ -60,11 +60,6 @@ void LookupTables::device_free(Device *, DeviceScene *dscene)
|
||||
dscene->lookup_table.free();
|
||||
}
|
||||
|
||||
bool LookupTables::need_update() const
|
||||
{
|
||||
return need_update_;
|
||||
}
|
||||
|
||||
static size_t round_up_to_multiple(size_t size, size_t chunk)
|
||||
{
|
||||
return ((size + chunk - 1) / chunk) * chunk;
|
||||
@@ -74,7 +69,7 @@ size_t LookupTables::add_table(DeviceScene *dscene, vector<float> &data)
|
||||
{
|
||||
assert(data.size() > 0);
|
||||
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
|
||||
Table new_table;
|
||||
new_table.offset = 0;
|
||||
@@ -112,7 +107,7 @@ void LookupTables::remove_table(size_t *offset)
|
||||
return;
|
||||
}
|
||||
|
||||
need_update_ = true;
|
||||
need_update = true;
|
||||
|
||||
list<Table>::iterator table;
|
||||
|
||||
|
@@ -30,14 +30,13 @@ enum { TABLE_CHUNK_SIZE = 256 };
|
||||
enum { TABLE_OFFSET_INVALID = -1 };
|
||||
|
||||
class LookupTables {
|
||||
bool need_update_;
|
||||
|
||||
public:
|
||||
struct Table {
|
||||
size_t offset;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
bool need_update;
|
||||
list<Table> lookup_tables;
|
||||
|
||||
LookupTables();
|
||||
@@ -46,8 +45,6 @@ class LookupTables {
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
bool need_update() const;
|
||||
|
||||
size_t add_table(DeviceScene *dscene, vector<float> &data);
|
||||
void remove_table(size_t *offset);
|
||||
};
|
||||
|
@@ -131,14 +131,6 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
|
||||
}
|
||||
}
|
||||
|
||||
void set_data(T *ptr_, size_t datasize)
|
||||
{
|
||||
clear();
|
||||
data_ = ptr_;
|
||||
datasize_ = datasize;
|
||||
capacity_ = datasize;
|
||||
}
|
||||
|
||||
T *steal_pointer()
|
||||
{
|
||||
T *ptr = data_;
|
||||
|
@@ -109,7 +109,7 @@ class GHOST_DropTargetX11 {
|
||||
/* class holding internal stiff of xdnd library */
|
||||
static DndClass m_dndClass;
|
||||
|
||||
/* list of supported types to be dragged into */
|
||||
/* list of supported types to eb draggeg into */
|
||||
static Atom *m_dndTypes;
|
||||
|
||||
/* list of supported dran'n'drop actions */
|
||||
|
@@ -49,6 +49,12 @@ set(LIB
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
list(APPEND SRC
|
||||
intern/mmap_win.c
|
||||
|
||||
mmap_win.h
|
||||
)
|
||||
|
||||
list(APPEND INC_SYS
|
||||
${PTHREADS_INC}
|
||||
)
|
||||
|
@@ -122,7 +122,7 @@ extern void *(*MEM_calloc_arrayN)(size_t len,
|
||||
/**
|
||||
* Allocate a block of memory of size len, with tag name str. The
|
||||
* name must be a static, because only a pointer to it is stored !
|
||||
*/
|
||||
* */
|
||||
extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
|
||||
|
||||
@@ -130,7 +130,7 @@ extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_
|
||||
* Allocate a block of memory of size (len * size), with tag name str,
|
||||
* aborting in case of integer overflow to prevent vulnerabilities. The
|
||||
* name must be a static, because only a pointer to it is stored !
|
||||
*/
|
||||
* */
|
||||
extern void *(*MEM_malloc_arrayN)(size_t len,
|
||||
size_t size,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
@@ -139,7 +139,7 @@ extern void *(*MEM_malloc_arrayN)(size_t len,
|
||||
/**
|
||||
* Allocate an aligned block of memory of size len, with tag name str. The
|
||||
* name must be a static, because only a pointer to it is stored !
|
||||
*/
|
||||
* */
|
||||
extern void *(*MEM_mallocN_aligned)(size_t len,
|
||||
size_t alignment,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
|
294
intern/guardedalloc/intern/mmap_win.c
Normal file
294
intern/guardedalloc/intern/mmap_win.c
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
# include <errno.h>
|
||||
# include <io.h>
|
||||
# include <stdio.h>
|
||||
# include <sys/types.h>
|
||||
# include <windows.h>
|
||||
|
||||
# include "mmap_win.h"
|
||||
|
||||
# ifndef FILE_MAP_EXECUTE
|
||||
// not defined in earlier versions of the Platform SDK (before February 2003)
|
||||
# define FILE_MAP_EXECUTE 0x0020
|
||||
# endif
|
||||
|
||||
/* copied from BLI_utildefines.h, ugh */
|
||||
# ifdef __GNUC__
|
||||
# define UNUSED(x) UNUSED_##x __attribute__((__unused__))
|
||||
# else
|
||||
# define UNUSED(x) x
|
||||
# endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local storage definitions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* all memory mapped chunks are put in linked lists */
|
||||
typedef struct mmapLink {
|
||||
struct mmapLink *next, *prev;
|
||||
} mmapLink;
|
||||
|
||||
typedef struct mmapListBase {
|
||||
void *first, *last;
|
||||
} mmapListBase;
|
||||
|
||||
typedef struct MemMap {
|
||||
struct MemMap *next, *prev;
|
||||
void *mmap;
|
||||
HANDLE fhandle;
|
||||
HANDLE maphandle;
|
||||
} MemMap;
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void mmap_addtail(volatile mmapListBase *listbase, void *vlink);
|
||||
static void mmap_remlink(volatile mmapListBase *listbase, void *vlink);
|
||||
static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr);
|
||||
|
||||
static int mmap_get_prot_flags(int flags);
|
||||
static int mmap_get_access_flags(int flags);
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* vars */
|
||||
/* --------------------------------------------------------------------- */
|
||||
volatile static struct mmapListBase _mmapbase;
|
||||
volatile static struct mmapListBase *mmapbase = &_mmapbase;
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* implementation */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* mmap for windows */
|
||||
void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
HANDLE fhandle = INVALID_HANDLE_VALUE;
|
||||
HANDLE maphandle;
|
||||
int prot_flags = mmap_get_prot_flags(prot);
|
||||
int access_flags = mmap_get_access_flags(prot);
|
||||
MemMap *mm = NULL;
|
||||
void *ptr = NULL;
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
# if 0
|
||||
if (fd == -1) {
|
||||
_set_errno(EBADF);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (fd != -1) {
|
||||
fhandle = (HANDLE)_get_osfhandle(fd);
|
||||
}
|
||||
if (fhandle == INVALID_HANDLE_VALUE) {
|
||||
if (!(flags & MAP_ANONYMOUS)) {
|
||||
errno = EBADF;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!DuplicateHandle(GetCurrentProcess(),
|
||||
fhandle,
|
||||
GetCurrentProcess(),
|
||||
&fhandle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS)) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Split 64 bit size into low and high bits. */
|
||||
DWORD len_bits_high = len >> 32;
|
||||
DWORD len_bits_low = len & 0xFFFFFFFF;
|
||||
|
||||
maphandle = CreateFileMapping(fhandle, NULL, prot_flags, len_bits_high, len_bits_low, NULL);
|
||||
if (maphandle == 0) {
|
||||
errno = EBADF;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0);
|
||||
if (ptr == NULL) {
|
||||
DWORD dwLastErr = GetLastError();
|
||||
if (dwLastErr == ERROR_MAPPED_ALIGNMENT) {
|
||||
errno = EINVAL;
|
||||
}
|
||||
else {
|
||||
errno = EACCES;
|
||||
}
|
||||
CloseHandle(maphandle);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
mm = (MemMap *)malloc(sizeof(MemMap));
|
||||
if (!mm) {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
mm->fhandle = fhandle;
|
||||
mm->maphandle = maphandle;
|
||||
mm->mmap = ptr;
|
||||
mmap_addtail(mmapbase, mm);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* munmap for windows */
|
||||
intptr_t munmap(void *ptr, size_t UNUSED(size))
|
||||
{
|
||||
MemMap *mm = mmap_findlink(mmapbase, ptr);
|
||||
if (!mm) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
UnmapViewOfFile(mm->mmap);
|
||||
CloseHandle(mm->maphandle);
|
||||
CloseHandle(mm->fhandle);
|
||||
mmap_remlink(mmapbase, mm);
|
||||
free(mm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
|
||||
{
|
||||
struct mmapLink *link = vlink;
|
||||
|
||||
if (link == NULL) {
|
||||
return;
|
||||
}
|
||||
if (listbase == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
link->next = 0;
|
||||
link->prev = listbase->last;
|
||||
|
||||
if (listbase->last) {
|
||||
((struct mmapLink *)listbase->last)->next = link;
|
||||
}
|
||||
if (listbase->first == NULL) {
|
||||
listbase->first = link;
|
||||
}
|
||||
listbase->last = link;
|
||||
}
|
||||
|
||||
static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
|
||||
{
|
||||
struct mmapLink *link = vlink;
|
||||
|
||||
if (link == NULL) {
|
||||
return;
|
||||
}
|
||||
if (listbase == NULL) {
|
||||
return;
|
||||
}
|
||||
if (link->next) {
|
||||
link->next->prev = link->prev;
|
||||
}
|
||||
if (link->prev) {
|
||||
link->prev->next = link->next;
|
||||
}
|
||||
|
||||
if (listbase->last == link) {
|
||||
listbase->last = link->prev;
|
||||
}
|
||||
if (listbase->first == link) {
|
||||
listbase->first = link->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
|
||||
{
|
||||
MemMap *mm;
|
||||
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (listbase == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mm = (MemMap *)listbase->first;
|
||||
while (mm) {
|
||||
if (mm->mmap == ptr) {
|
||||
return mm;
|
||||
}
|
||||
mm = mm->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mmap_get_prot_flags(int flags)
|
||||
{
|
||||
int prot = PAGE_NOACCESS;
|
||||
|
||||
if ((flags & PROT_READ) == PROT_READ) {
|
||||
if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||
}
|
||||
else {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY;
|
||||
}
|
||||
}
|
||||
else if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY;
|
||||
}
|
||||
else if ((flags & PROT_EXEC) == PROT_EXEC) {
|
||||
prot = PAGE_EXECUTE_READ;
|
||||
}
|
||||
return prot;
|
||||
}
|
||||
|
||||
static int mmap_get_access_flags(int flags)
|
||||
{
|
||||
int access = 0;
|
||||
|
||||
if ((flags & PROT_READ) == PROT_READ) {
|
||||
if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
access = FILE_MAP_WRITE;
|
||||
}
|
||||
else {
|
||||
access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ;
|
||||
}
|
||||
}
|
||||
else if ((flags & PROT_WRITE) == PROT_WRITE) {
|
||||
access = FILE_MAP_COPY;
|
||||
}
|
||||
else if ((flags & PROT_EXEC) == PROT_EXEC) {
|
||||
access = FILE_MAP_EXECUTE;
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
#endif // WIN32
|
50
intern/guardedalloc/mmap_win.h
Normal file
50
intern/guardedalloc/mmap_win.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
#ifndef __MMAP_WIN_H__
|
||||
#define __MMAP_WIN_H__
|
||||
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
|
||||
#define MAP_FILE 0
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_TYPE 0xF
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */
|
||||
#include "../../source/blender/blenlib/BLI_sys_types.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);
|
||||
intptr_t munmap(void *ptr, size_t size);
|
||||
|
||||
#endif
|
Submodule release/datafiles/locale updated: 877a343fed...6c693b5b0b
Binary file not shown.
Before Width: | Height: | Size: 721 KiB After Width: | Height: | Size: 867 KiB |
@@ -119,7 +119,6 @@ const UserDef U_default = {
|
||||
|
||||
.gizmo_flag = USER_GIZMO_DRAW,
|
||||
.gizmo_size = 75,
|
||||
.gizmo_size_navigate_v3d = 80,
|
||||
.edit_studio_light = 0,
|
||||
.lookdev_sphere_size = 150,
|
||||
.vbotimeout = 120,
|
||||
|
Submodule release/scripts/addons updated: a3fa40ec0b...dfeb905d62
@@ -74,6 +74,8 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True):
|
||||
if tap_reset_tool not in items_all_id:
|
||||
use_tap_reset = False
|
||||
|
||||
from bl_operators.wm import use_toolbar_release_hack
|
||||
|
||||
# Pie-menu style release to activate.
|
||||
use_release_confirm = use_reset
|
||||
|
||||
@@ -435,7 +437,7 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True):
|
||||
|
||||
kmi = keymap.keymap_items.new(
|
||||
"wm.tool_set_by_id",
|
||||
value='DOUBLE_CLICK',
|
||||
value='PRESS' if use_toolbar_release_hack else 'DOUBLE_CLICK',
|
||||
**kmi_toolbar_args_available,
|
||||
)
|
||||
kmi.properties.name = tap_reset_tool
|
||||
@@ -449,6 +451,15 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True):
|
||||
)
|
||||
kmi.properties.skip_depressed = True
|
||||
|
||||
if use_toolbar_release_hack:
|
||||
# ... or pass through to let the toolbar know we're released.
|
||||
# Let the operator know we're released.
|
||||
kmi = keymap.keymap_items.new(
|
||||
"wm.tool_set_by_id",
|
||||
type=kmi_toolbar_type,
|
||||
value='RELEASE',
|
||||
any=True,
|
||||
)
|
||||
|
||||
wm.keyconfigs.update()
|
||||
return keymap
|
||||
|
@@ -49,6 +49,7 @@ def keyconfig_data_oskey_from_ctrl_for_macos(keyconfig_data_src):
|
||||
'W',
|
||||
'ACCENT_GRAVE',
|
||||
'PERIOD',
|
||||
'TAB',
|
||||
}):
|
||||
if (not item_event.get("alt")) and (not item_event.get("shift")):
|
||||
return False
|
||||
|
@@ -1,28 +1,3 @@
|
||||
#
|
||||
# Notes on this key-map:
|
||||
#
|
||||
# This uses Blender's key-map, running with `legacy=True`.
|
||||
#
|
||||
# The intention of this key-map is to match Blender 2.7x which had many more key-map items available.
|
||||
#
|
||||
# There are some differences with the original Blender 2.7x key-map.
|
||||
# There is no intention to change these are they are not considered significant
|
||||
# enough to make a 1:1 match with the previous Blender version.
|
||||
#
|
||||
# These include:
|
||||
#
|
||||
# 3D View
|
||||
# =======
|
||||
#
|
||||
# - Border Render (`Shift-B` -> `Ctrl-B`)
|
||||
# Both `Shift-B` and `Ctrl-B` were used.
|
||||
#
|
||||
# Time Line/Animation Views
|
||||
# =========================
|
||||
#
|
||||
# - Start Frame/End Frame (`S/E` -> `Ctrl-Home/Ctrl-End`)
|
||||
#
|
||||
|
||||
import os
|
||||
import bpy
|
||||
from bpy.props import (
|
||||
|
@@ -33,6 +33,11 @@ from bpy.props import (
|
||||
)
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
# FIXME, we need a way to detect key repeat events.
|
||||
# unfortunately checking event previous values isn't reliable.
|
||||
use_toolbar_release_hack = True
|
||||
|
||||
|
||||
rna_path_prop = StringProperty(
|
||||
name="Context Attributes",
|
||||
description="RNA context string",
|
||||
@@ -1693,6 +1698,18 @@ class WM_OT_tool_set_by_id(Operator):
|
||||
|
||||
space_type: rna_space_type_prop
|
||||
|
||||
if use_toolbar_release_hack:
|
||||
def invoke(self, context, event):
|
||||
# Hack :S
|
||||
if not self.properties.is_property_set("name"):
|
||||
WM_OT_toolbar._key_held = False
|
||||
return {'PASS_THROUGH'}
|
||||
elif (WM_OT_toolbar._key_held == event.type) and (event.value != 'RELEASE'):
|
||||
return {'PASS_THROUGH'}
|
||||
WM_OT_toolbar._key_held = None
|
||||
|
||||
return self.execute(context)
|
||||
|
||||
def execute(self, context):
|
||||
from bl_ui.space_toolsystem_common import (
|
||||
activate_by_id,
|
||||
@@ -1784,6 +1801,13 @@ class WM_OT_toolbar(Operator):
|
||||
def poll(cls, context):
|
||||
return context.space_data is not None
|
||||
|
||||
if use_toolbar_release_hack:
|
||||
_key_held = None
|
||||
|
||||
def invoke(self, context, event):
|
||||
WM_OT_toolbar._key_held = event.type
|
||||
return self.execute(context)
|
||||
|
||||
@staticmethod
|
||||
def keymap_from_toolbar(context, space_type, use_fallback_keys=True, use_reset=True):
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
|
@@ -23,7 +23,6 @@ from rna_prop_ui import PropertyPanel
|
||||
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilLayerMasksPanel,
|
||||
GreasePencilLayerTransformPanel,
|
||||
GreasePencilLayerAdjustmentsPanel,
|
||||
GreasePencilLayerRelationsPanel,
|
||||
GreasePencilLayerDisplayPanel,
|
||||
@@ -91,10 +90,8 @@ class GPENCIL_MT_layer_context_menu(Menu):
|
||||
layout = self.layout
|
||||
ob = context.object
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
|
||||
layout.operator("gpencil.layer_duplicate", text="Duplicate", icon='DUPLICATE').mode='ALL'
|
||||
layout.operator("gpencil.layer_duplicate", text="Duplicate Empty Keyframes").mode='EMPTY'
|
||||
layout.operator("gpencil.layer_duplicate", icon='DUPLICATE')
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -106,7 +103,6 @@ class GPENCIL_MT_layer_context_menu(Menu):
|
||||
layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All")
|
||||
layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="Unlock All")
|
||||
layout.prop(gpd, "use_autolock_layers", text="Autolock Inactive Layers")
|
||||
layout.prop(gpl, "lock_material")
|
||||
|
||||
layout.separator()
|
||||
|
||||
@@ -192,12 +188,6 @@ class DATA_PT_gpencil_layer_masks(LayerDataButtonsPanel, GreasePencilLayerMasksP
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_transform(LayerDataButtonsPanel, GreasePencilLayerTransformPanel, Panel):
|
||||
bl_label = "Transform"
|
||||
bl_parent_id = 'DATA_PT_gpencil_layers'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_adjustments(LayerDataButtonsPanel, GreasePencilLayerAdjustmentsPanel, Panel):
|
||||
bl_label = "Adjustments"
|
||||
bl_parent_id = 'DATA_PT_gpencil_layers'
|
||||
@@ -434,7 +424,6 @@ classes = (
|
||||
DATA_PT_gpencil_onion_skinning_custom_colors,
|
||||
DATA_PT_gpencil_onion_skinning_display,
|
||||
DATA_PT_gpencil_layer_masks,
|
||||
DATA_PT_gpencil_layer_transform,
|
||||
DATA_PT_gpencil_layer_adjustments,
|
||||
DATA_PT_gpencil_layer_relations,
|
||||
DATA_PT_gpencil_layer_display,
|
||||
|
@@ -63,7 +63,7 @@ class DATA_PT_volume_file(DataButtonsPanel, Panel):
|
||||
|
||||
layout.prop(volume, "filepath", text="")
|
||||
|
||||
if volume.filepath:
|
||||
if len(volume.filepath):
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
@@ -76,7 +76,7 @@ class DATA_PT_volume_file(DataButtonsPanel, Panel):
|
||||
col.prop(volume, "sequence_mode", text="Mode")
|
||||
|
||||
error_msg = volume.grids.error_message
|
||||
if error_msg:
|
||||
if len(error_msg):
|
||||
layout.separator()
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Failed to load volume:")
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user