Compare commits

..

19 Commits

Author SHA1 Message Date
Sam Miller
bb0b250cbd Fix T85368: map range node clamps incorrectly in geometry nodes
When clamp is enabled, it should clamp between the output min and max
and not between 0 and 1.

Differential Revision: https://developer.blender.org/D10324
2021-02-08 13:33:23 +01:00
4402f43b71 Fix T85426: Speed effect stretch to input not working
`seq_effect_speed_get_strip_content_length()` checked only for number
of inputs of target strip, even if it's not an effect.

Only effects are treated in different way, so check for type as well.
Broken by 93c10797dc

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D10356
2021-02-08 11:30:26 +01:00
eccc57aa5c Fix T85378: Shrink/Fatten display number units
Currently the displayed distance when using the shrink/fatten transform
operator does not respect the scene units (they would always be in
blender units).

This changes makes sure the number is displayed in the correct unit.

Reviewed By: mano-wii

Maniphest Tasks: T85378

Differential Revision: https://developer.blender.org/D10325
2021-02-06 09:07:50 +01:00
a563775649 Fluid: Updated Mantaflow source files
This updates fixes the following issues (critical for 2.92):

- Issue that prevented dense 'int' grids from being exported (incorrect clip value)
- Issue with particles outside out of domain bounds (position between -1 and 0) not being deleted
2021-02-05 16:23:02 +01:00
4212ea7b7d Fix T85260: Viewport render does not draw background
Regression introduced by {rBed809866b172} where overlays weren't drawn
when overlays are turned off. The background in wireframe, solid
(always) and material preview and render preview (when not using scene
world) are also part of the overlays.
2021-02-05 13:05:58 +01:00
0a546beb1f Fix T85396: Display Texture Paint UV only working in editmode
Caused by rBf83aa830cd00.

Since above commit, only meshes in editmode were considered for drawing
(because
BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs was
used), but the option needs to work for texture paint mode as well, so
use BKE_view_layer_array_from_objects_in_mode_unique_data instead on
pass the draw_ctx->object_mode.

note: there is no good filter_fn to check if we have UVs if mesh is not
in editmode, this shouldnt cause much of a performance hit though.

Maniphest Tasks: T85396

Differential Revision: https://developer.blender.org/D10319
2021-02-05 12:43:00 +01:00
7fb540b4cf Fix T85357: Setting collection color restricted to View Layer mode
Allow setting collection color in Scenes and Blender File outliner
display modes in addition to View Layer mode.
2021-02-04 10:38:44 -07:00
760a16b88b Fix for 3D view transform: flipped rotation direction for numeric input
The rotation direction was flipped recently.

This meant that rotation on a single axis gave negative results compared
with previous Blender releases.

This partially reverts a9b53daf23.

Differential Revision: https://developer.blender.org/D10299
2021-02-04 10:43:57 -03:00
Johannes Jakob
bec08621d6 Fix T85363: Cmd + Tab shortcut overridden on macOS
Adds an exception so that the key-binding `control + Tab` does not get
duplicated as `command + Tab` on macOS because this is a global system
shortcut for the app switcher.

The key-binding `command + Tab` was shown for the operators “Toggle
Graph Editor“ and “Toggle Dope Sheet” in Dope Sheet and Graph Editor,
but only `control + Tab` actually worked.

Differential Revision: https://developer.blender.org/D10304
2021-02-04 14:27:44 +01:00
3f90c11621 Fix T85318: Driver variable don't resolve collection indices
The driver variable `splines[0]` (on a curve)
behaved as if the path was `splines`.

Resolve pointers was well as properties as it's supported by the caller.

Error in original commit that added property support
82b0a9e369.
2021-02-04 11:19:09 +11:00
ebd2aa789e Fix T85230: Face Set Boundary automasking not working with dyntopo
Dyntopo does not have Face Sets implemented yet, so the entire mesh is
considered a single Face Set. In that case, the check unique face set
function should always return true.

Reviewed By: JacquesLucke

Maniphest Tasks: T85230

Differential Revision: https://developer.blender.org/D10259
2021-02-03 21:05:48 +01:00
0f238c5bcb Fix T85136: Sculpt geometry extract not using updated mesh
This ensured that the sculpt mode deformation is flushed to the mesh
datablock after leaving sculpt mode, so it can be duplicated and
extracted correctly.

Reviewed By: JacquesLucke

Maniphest Tasks: T85136

Differential Revision: https://developer.blender.org/D10254
2021-02-03 21:00:28 +01:00
1081eee4c5 Fix T84370: Project tool not working with shape keys
A missing flush of the deformed PBVH coordinates to the shape key.

Reviewed By: JacquesLucke

Maniphest Tasks: T84370

Differential Revision: https://developer.blender.org/D10174
2021-02-03 20:58:42 +01:00
Pablo Dobarro
7bde2844ae Fix memory leak in boundary brush preview data
The edge preview data of the boundary needs to be freed with the
boundary data created for the brush. Also, all data for the
ScultpSession preview that is used to render the cursor needs to be
freed with the ##SculptSession##.

Found by Jacques Lucke

Reviewed By: JacquesLucke

Differential Revision: https://developer.blender.org/D10173
2021-02-03 20:55:17 +01:00
5eb5a7f4b7 Fix unreported: Rotation Gizmo "C" influenced by custom orientation
The white rotation Gizmo should always use the View orientation.

Before, if you set an orientation for the gizmo other than the default,
that gizmo would behave like the contraint Z Gizmo.
2021-02-03 14:54:58 -03:00
bbd74e9fd4 Fix T85340: Gizmo rotation inverted (in some perspective angles)
This is an old bug (strange not to have been reported before).

To define the direction of rotation, the View Vector is used.

However, only the projection matrix was being considered, but in
perspective mode, the position of the pivot also matters.
2021-02-03 14:48:17 -03:00
9042532085 Cleanup: Move and rename 'getViewVector' utility
This function is only being used by the constraint code.
2021-02-03 14:48:17 -03:00
8c7b78672e Fix 'getViewVector' returning inverted vector
Despite the wrong value, this change is harmless since the direction of
the vector is not really required.
2021-02-03 14:48:17 -03:00
Yevgeny Makarov
e54f88f092 macOS: trackpad scroll direction reversed in list views
The 'ui_pan_to_scroll' uses 'WM_event_absolute_delta_y'. For scrolling the List View
we need to invert the direction to respect "natural scroll direction" system preferences.

Differential Revision: https://developer.blender.org/D10291
2021-02-03 17:13:27 +01:00
537 changed files with 7180 additions and 16148 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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()

View File

@@ -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*")

View File

@@ -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)

View File

@@ -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"

View File

@@ -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;

View File

@@ -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

View File

@@ -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)

View File

@@ -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")

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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()

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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 \

View File

@@ -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)
{

View File

@@ -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;
}

View File

@@ -1,3 +1,3 @@
#define MANTA_GIT_VERSION "commit 1c86d86496e7f7473c36248d12ef07bf4d9d2840"
#define MANTA_GIT_VERSION "commit 39b7a415721ecbf6643612a24e8eadd221aeb934"

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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());

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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()

View File

@@ -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`). */

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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_)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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,

View File

@@ -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));

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 &params_, 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

View File

@@ -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__ */

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -219,7 +219,6 @@ class SceneUpdateStats {
UpdateTimeStats scene;
UpdateTimeStats svm;
UpdateTimeStats tables;
UpdateTimeStats procedurals;
string full_report();

View File

@@ -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.";

View File

@@ -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;

View File

@@ -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);
};

View File

@@ -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_;

View File

@@ -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 */

View File

@@ -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}
)

View File

@@ -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

View 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

View 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 KiB

After

Width:  |  Height:  |  Size: 867 KiB

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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 (

View File

@@ -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

View File

@@ -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,

View File

@@ -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