Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile6
-rw-r--r--build_files/build_environment/cmake/usd.cmake4
-rw-r--r--build_files/build_environment/cmake/versions.cmake4
-rwxr-xr-xbuild_files/build_environment/install_deps.sh2
-rw-r--r--build_files/build_environment/patches/usd.diff42
-rw-r--r--build_files/buildbot/buildbot_utils.py2
-rw-r--r--extern/audaspace/plugins/sdl/SDLDevice.cpp40
-rw-r--r--intern/cycles/device/cuda/device_cuda.h6
-rw-r--r--intern/cycles/device/cuda/device_cuda_impl.cpp122
-rw-r--r--intern/cycles/device/device_optix.cpp18
-rw-r--r--intern/cycles/render/session.cpp4
-rw-r--r--intern/ghost/intern/GHOST_XrContext.cpp1
-rw-r--r--intern/ghost/intern/GHOST_XrContext.h1
-rw-r--r--intern/ghost/intern/GHOST_XrSession.cpp3
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py2
-rw-r--r--release/scripts/startup/bl_ui/space_text.py2
-rw-r--r--source/blender/blenkernel/BKE_anim_path.h14
-rw-r--r--source/blender/blenkernel/BKE_armature.h42
-rw-r--r--source/blender/blenkernel/BKE_cloth.h7
-rw-r--r--source/blender/blenkernel/BKE_curve.h46
-rw-r--r--source/blender/blenkernel/BKE_deform.h12
-rw-r--r--source/blender/blenkernel/BKE_lattice.h80
-rw-r--r--source/blender/blenkernel/BKE_mesh_wrapper.h2
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt3
-rw-r--r--source/blender/blenkernel/intern/anim_path.c96
-rw-r--r--source/blender/blenkernel/intern/armature.c640
-rw-r--r--source/blender/blenkernel/intern/armature_deform.c688
-rw-r--r--source/blender/blenkernel/intern/cloth.c1
-rw-r--r--source/blender/blenkernel/intern/collection.c37
-rw-r--r--source/blender/blenkernel/intern/curve.c3
-rw-r--r--source/blender/blenkernel/intern/curve_deform.c504
-rw-r--r--source/blender/blenkernel/intern/deform.c10
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c8
-rw-r--r--source/blender/blenkernel/intern/lattice.c648
-rw-r--r--source/blender/blenkernel/intern/lattice_deform.c470
-rw-r--r--source/blender/blenkernel/intern/lib_id.c2
-rw-r--r--source/blender/blenkernel/intern/lib_override.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_wrapper.c4
-rw-r--r--source/blender/blenkernel/intern/modifier.c5
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c2
-rw-r--r--source/blender/blenkernel/intern/particle.c21
-rw-r--r--source/blender/blenkernel/intern/particle_system.c6
-rw-r--r--source/blender/blenkernel/intern/pointcache.c62
-rw-r--r--source/blender/blenlib/BLI_array.hh2
-rw-r--r--source/blender/blenlib/BLI_hash.hh12
-rw-r--r--source/blender/blenlib/BLI_linear_allocator.hh2
-rw-r--r--source/blender/blenlib/BLI_map.hh6
-rw-r--r--source/blender/blenlib/BLI_map_slots.hh26
-rw-r--r--source/blender/blenlib/BLI_memory_utils.hh15
-rw-r--r--source/blender/blenlib/BLI_optional.hh8
-rw-r--r--source/blender/blenlib/BLI_set.hh4
-rw-r--r--source/blender/blenlib/BLI_set_slots.hh16
-rw-r--r--source/blender/blenlib/BLI_stack.hh2
-rw-r--r--source/blender/blenlib/BLI_string_ref.hh6
-rw-r--r--source/blender/blenlib/BLI_vector.hh6
-rw-r--r--source/blender/blenlib/BLI_vector_set.hh2
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc3
-rw-r--r--source/blender/draw/intern/draw_cache_impl_lattice.c2
-rw-r--r--source/blender/draw/intern/draw_manager.c4
-rw-r--r--source/blender/editors/mesh/editmesh_select_similar.c54
-rw-r--r--source/blender/editors/object/object_constraint.c2
-rw-r--r--source/blender/editors/object/object_relations.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c34
-rw-r--r--source/blender/editors/space_graph/graph_utils.c2
-rw-r--r--source/blender/editors/space_text/text_ops.c4
-rw-r--r--source/blender/editors/transform/transform_convert_gpencil.c56
-rw-r--r--source/blender/editors/transform/transform_convert_particle.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c15
-rw-r--r--source/blender/functions/FN_cpp_type.hh12
-rw-r--r--source/blender/functions/FN_cpp_types.hh2
-rw-r--r--source/blender/functions/intern/cpp_types.cc2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c33
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c7
-rw-r--r--source/blender/gpu/intern/gpu_draw.c5
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c9
-rw-r--r--source/blender/io/alembic/intern/abc_writer_points.cc2
-rw-r--r--source/blender/io/usd/intern/usd_writer_mesh.cc9
-rw-r--r--source/blender/makesdna/DNA_ID.h11
-rw-r--r--source/blender/makesdna/DNA_cloth_types.h5
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h12
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h6
-rw-r--r--source/blender/makesdna/DNA_pointcache_types.h1
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_ID.c9
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c32
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c36
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c16
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c111
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c61
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c2
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c33
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.c8
-rw-r--r--source/blender/modifiers/intern/MOD_util.h4
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp220
-rw-r--r--source/blender/physics/intern/implicit.h7
-rw-r--r--source/blender/physics/intern/implicit_blender.c52
-rw-r--r--source/blender/render/intern/source/pointdensity.c4
-rw-r--r--tests/gtests/blenlib/BLI_map_test.cc9
-rw-r--r--tests/gtests/blenlib/BLI_set_test.cc6
-rw-r--r--tests/gtests/functions/FN_cpp_type_test.cc6
105 files changed, 2884 insertions, 1832 deletions
diff --git a/GNUmakefile b/GNUmakefile
index e3bb3eaff7a..93e2164dee8 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -32,6 +32,7 @@ Convenience Targets
* debug: Build a debug binary.
* full: Enable all supported dependencies & options.
* lite: Disable non essential features for a smaller binary and faster build.
+ * release Complete build with all options enabled including CUDA and Optix, matching the releases on blender.org
* headless: Build without an interface (renderfarm or server automation).
* cycles: Build Cycles standalone only, without Blender.
* bpy: Build as a python module which can be loaded from python directly.
@@ -207,6 +208,10 @@ ifneq "$(findstring lite, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_lite
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_lite.cmake" $(CMAKE_CONFIG_ARGS)
endif
+ifneq "$(findstring release, $(MAKECMDGOALS))" ""
+ BUILD_DIR:=$(BUILD_DIR)_release
+ CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_release.cmake" $(CMAKE_CONFIG_ARGS)
+endif
ifneq "$(findstring cycles, $(MAKECMDGOALS))" ""
BUILD_DIR:=$(BUILD_DIR)_cycles
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/cycles_standalone.cmake" $(CMAKE_CONFIG_ARGS)
@@ -317,6 +322,7 @@ all: .FORCE
debug: all
full: all
lite: all
+release: all
cycles: all
headless: all
bpy: all
diff --git a/build_files/build_environment/cmake/usd.cmake b/build_files/build_environment/cmake/usd.cmake
index 3e4535a6f92..c98a9cae959 100644
--- a/build_files/build_environment/cmake/usd.cmake
+++ b/build_files/build_environment/cmake/usd.cmake
@@ -78,14 +78,14 @@ if(WIN32)
if(BUILD_MODE STREQUAL Release)
ExternalProject_Add_Step(external_usd after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/ ${HARVEST_TARGET}/usd
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/libusd_m.lib ${HARVEST_TARGET}/usd/lib/libusd_m.lib
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/usd_m.lib ${HARVEST_TARGET}/usd/lib/libusd_m.lib
DEPENDEES install
)
endif()
if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_usd after_install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/lib ${HARVEST_TARGET}/usd/lib
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/libusd_m_d.lib ${HARVEST_TARGET}/usd/lib/libusd_m_d.lib
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/usd_m_d.lib ${HARVEST_TARGET}/usd/lib/libusd_m_d.lib
DEPENDEES install
)
endif()
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index c1dcf98318c..a140a26b023 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -297,9 +297,9 @@ set(EMBREE_VERSION 3.10.0)
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
set(EMBREE_HASH 4bbe29e7eaa46417efc75fc5f1e8eb87)
-set(USD_VERSION 19.11)
+set(USD_VERSION 20.02)
set(USD_URI https://github.com/PixarAnimationStudios/USD/archive/v${USD_VERSION}.tar.gz)
-set(USD_HASH 79ff176167b3fe85f4953abd6cc5e0cc)
+set(USD_HASH 8901815f01469a7f4496bd60315a9d10)
set(OIDN_VERSION 1.0.0)
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.zip)
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 511ea341bb1..06d9cc4aa06 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -459,7 +459,7 @@ ALEMBIC_FORCE_BUILD=false
ALEMBIC_FORCE_REBUILD=false
ALEMBIC_SKIP=false
-USD_VERSION="19.11"
+USD_VERSION="20.02"
USD_FORCE_BUILD=false
USD_FORCE_REBUILD=false
USD_SKIP=false
diff --git a/build_files/build_environment/patches/usd.diff b/build_files/build_environment/patches/usd.diff
index 6302f13796b..adee3d2e458 100644
--- a/build_files/build_environment/patches/usd.diff
+++ b/build_files/build_environment/patches/usd.diff
@@ -1,14 +1,3 @@
-diff -x .git -ur usd.orig/cmake/defaults/Options.cmake external_usd/cmake/defaults/Options.cmake
---- usd.orig/cmake/defaults/Options.cmake 2019-10-24 22:39:53.000000000 +0200
-+++ external_usd/cmake/defaults/Options.cmake 2019-11-28 13:00:33.197957712 +0100
-@@ -25,6 +25,7 @@
- option(PXR_VALIDATE_GENERATED_CODE "Validate script generated code" OFF)
- option(PXR_HEADLESS_TEST_MODE "Disallow GUI based tests, useful for running under headless CI systems." OFF)
- option(PXR_BUILD_TESTS "Build tests" ON)
-+option(PXR_BUILD_USD_TOOLS "Build commandline tools" ON)
- option(PXR_BUILD_IMAGING "Build imaging components" ON)
- option(PXR_BUILD_EMBREE_PLUGIN "Build embree imaging plugin" OFF)
- option(PXR_BUILD_OPENIMAGEIO_PLUGIN "Build OpenImageIO plugin" OFF)
diff -x .git -ur usd.orig/cmake/defaults/Packages.cmake external_usd/cmake/defaults/Packages.cmake
--- usd.orig/cmake/defaults/Packages.cmake 2019-10-24 22:39:53.000000000 +0200
+++ external_usd/cmake/defaults/Packages.cmake 2019-11-28 13:00:33.185957483 +0100
@@ -21,9 +10,9 @@ diff -x .git -ur usd.orig/cmake/defaults/Packages.cmake external_usd/cmake/defau
add_definitions(${TBB_DEFINITIONS})
# --math
-diff -x .git -ur usd.orig/pxr/base/lib/plug/initConfig.cpp external_usd/pxr/base/lib/plug/initConfig.cpp
---- usd.orig/pxr/base/lib/plug/initConfig.cpp 2019-10-24 22:39:53.000000000 +0200
-+++ external_usd/pxr/base/lib/plug/initConfig.cpp 2019-12-11 11:00:37.643323127 +0100
+diff -x .git -ur usd.orig/pxr/base/plug/initConfig.cpp external_usd/pxr/base/plug/initConfig.cpp
+--- usd.orig/pxr/base/plug/initConfig.cpp 2019-10-24 22:39:53.000000000 +0200
++++ external_usd/pxr/base/plug/initConfig.cpp 2019-12-11 11:00:37.643323127 +0100
@@ -69,8 +69,38 @@
ARCH_CONSTRUCTOR(Plug_InitConfig, 2, void)
@@ -90,28 +79,9 @@ diff -x .git -ur usd.orig/pxr/base/lib/plug/initConfig.cpp external_usd/pxr/base
+ PXR_NS::usd_initialise_plugin_path(datafiles_usd_path);
+}
+}
-diff -x .git -ur usd.orig/pxr/usd/CMakeLists.txt external_usd/pxr/usd/CMakeLists.txt
---- usd.orig/pxr/usd/CMakeLists.txt 2019-10-24 22:39:53.000000000 +0200
-+++ external_usd/pxr/usd/CMakeLists.txt 2019-11-28 13:00:33.197957712 +0100
-@@ -1,6 +1,5 @@
- set(DIRS
- lib
-- bin
- plugin
- )
-
-@@ -8,3 +7,8 @@
- add_subdirectory(${d})
- endforeach()
-
-+if (PXR_BUILD_USD_TOOLS)
-+ add_subdirectory(bin)
-+else()
-+ message(STATUS "Skipping commandline tools because PXR_BUILD_USD_TOOLS=OFF")
-+endif()
-diff -Naur external_usd_orig/pxr/base/lib/tf/preprocessorUtils.h external_usd/pxr/base/lib/tf/preprocessorUtils.h
---- external_usd_orig/pxr/base/lib/tf/preprocessorUtils.h 2019-10-24 14:39:53 -0600
-+++ external_usd/pxr/base/lib/tf/preprocessorUtils.h 2020-01-14 09:30:18 -0700
+diff -Naur external_usd_orig/pxr/base/tf/preprocessorUtils.h external_usd/pxr/base/tf/preprocessorUtils.h
+--- external_usd_orig/pxr/base/tf/preprocessorUtils.h 2019-10-24 14:39:53 -0600
++++ external_usd/pxr/base/tf/preprocessorUtils.h 2020-01-14 09:30:18 -0700
@@ -189,7 +189,7 @@
/// Exapnds to 1 if the argument is a tuple, and 0 otherwise.
/// \ingroup group_tf_Preprocessor
diff --git a/build_files/buildbot/buildbot_utils.py b/build_files/buildbot/buildbot_utils.py
index 2dc1526c5e8..39a00980cc8 100644
--- a/build_files/buildbot/buildbot_utils.py
+++ b/build_files/buildbot/buildbot_utils.py
@@ -51,7 +51,7 @@ class Builder:
elif name.startswith('linux'):
self.platform = 'linux'
if is_tool('scl'):
- self.command_prefix = ['scl', 'enable', 'devtoolset-6', '--']
+ self.command_prefix = ['scl', 'enable', 'devtoolset-9', '--']
else:
self.command_prefix = []
elif name.startswith('win'):
diff --git a/extern/audaspace/plugins/sdl/SDLDevice.cpp b/extern/audaspace/plugins/sdl/SDLDevice.cpp
index 603e16001b8..8d7a605fa36 100644
--- a/extern/audaspace/plugins/sdl/SDLDevice.cpp
+++ b/extern/audaspace/plugins/sdl/SDLDevice.cpp
@@ -52,7 +52,7 @@ SDLDevice::SDLDevice(DeviceSpecs specs, int buffersize) :
if(specs.channels == CHANNELS_INVALID)
specs.channels = CHANNELS_STEREO;
if(specs.format == FORMAT_INVALID)
- specs.format = FORMAT_S16;
+ specs.format = FORMAT_FLOAT32;
if(specs.rate == RATE_INVALID)
specs.rate = RATE_48000;
@@ -61,10 +61,25 @@ SDLDevice::SDLDevice(DeviceSpecs specs, int buffersize) :
SDL_AudioSpec format, obtained;
format.freq = m_specs.rate;
- if(m_specs.format == FORMAT_U8)
+ switch(m_specs.format)
+ {
+ case FORMAT_U8:
format.format = AUDIO_U8;
- else
+ break;
+ case FORMAT_S16:
format.format = AUDIO_S16SYS;
+ break;
+ case FORMAT_S32:
+ format.format = AUDIO_S32SYS;
+ break;
+ case FORMAT_FLOAT32:
+ format.format = AUDIO_F32SYS;
+ break;
+ default:
+ format.format = AUDIO_F32SYS;
+ break;
+ }
+
format.channels = m_specs.channels;
format.samples = buffersize;
format.callback = SDLDevice::SDL_mix;
@@ -75,14 +90,25 @@ SDLDevice::SDLDevice(DeviceSpecs specs, int buffersize) :
m_specs.rate = (SampleRate)obtained.freq;
m_specs.channels = (Channels)obtained.channels;
- if(obtained.format == AUDIO_U8)
+
+ switch(obtained.format)
+ {
+ case AUDIO_U8:
m_specs.format = FORMAT_U8;
- else if(obtained.format == AUDIO_S16LSB || obtained.format == AUDIO_S16MSB)
+ break;
+ case AUDIO_S16SYS:
m_specs.format = FORMAT_S16;
- else
- {
+ break;
+ case AUDIO_S32SYS:
+ m_specs.format = FORMAT_S32;
+ break;
+ case AUDIO_F32SYS:
+ m_specs.format = FORMAT_FLOAT32;
+ break;
+ default:
SDL_CloseAudio();
AUD_THROW(DeviceException, "The sample format obtained from SDL is not supported.");
+ break;
}
create();
diff --git a/intern/cycles/device/cuda/device_cuda.h b/intern/cycles/device/cuda/device_cuda.h
index 9f31ed12cf4..1aa2fdd0967 100644
--- a/intern/cycles/device/cuda/device_cuda.h
+++ b/intern/cycles/device/cuda/device_cuda.h
@@ -100,11 +100,7 @@ class CUDADevice : public Device {
virtual BVHLayoutMask get_bvh_layout_mask() const;
- void cuda_error_documentation();
-
- bool cuda_error_(CUresult result, const string &stmt);
-
- void cuda_error_message(const string &message);
+ void set_error(const string &error) override;
CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_);
diff --git a/intern/cycles/device/cuda/device_cuda_impl.cpp b/intern/cycles/device/cuda/device_cuda_impl.cpp
index 64c7f5e7d34..7aa63ff48c3 100644
--- a/intern/cycles/device/cuda/device_cuda_impl.cpp
+++ b/intern/cycles/device/cuda/device_cuda_impl.cpp
@@ -135,8 +135,10 @@ BVHLayoutMask CUDADevice::get_bvh_layout_mask() const
return BVH_LAYOUT_BVH2;
}
-void CUDADevice::cuda_error_documentation()
+void CUDADevice::set_error(const string &error)
{
+ Device::set_error(error);
+
if (first_error) {
fprintf(stderr, "\nRefer to the Cycles GPU rendering documentation for possible solutions:\n");
fprintf(stderr,
@@ -148,42 +150,13 @@ void CUDADevice::cuda_error_documentation()
# define cuda_assert(stmt) \
{ \
CUresult result = stmt; \
-\
if (result != CUDA_SUCCESS) { \
- string message = string_printf( \
- "CUDA error: %s in %s, line %d", cuewErrorString(result), #stmt, __LINE__); \
- if (error_msg == "") \
- error_msg = message; \
- fprintf(stderr, "%s\n", message.c_str()); \
- /*cuda_abort();*/ \
- cuda_error_documentation(); \
+ const char *name = cuewErrorString(result); \
+ set_error(string_printf("%s in %s (device_cuda_impl.cpp:%d)", name, #stmt, __LINE__)); \
} \
} \
(void)0
-bool CUDADevice::cuda_error_(CUresult result, const string &stmt)
-{
- if (result == CUDA_SUCCESS)
- return false;
-
- string message = string_printf("CUDA error at %s: %s", stmt.c_str(), cuewErrorString(result));
- if (error_msg == "")
- error_msg = message;
- fprintf(stderr, "%s\n", message.c_str());
- cuda_error_documentation();
- return true;
-}
-
-# define cuda_error(stmt) cuda_error_(stmt, # stmt)
-
-void CUDADevice::cuda_error_message(const string &message)
-{
- if (error_msg == "")
- error_msg = message;
- fprintf(stderr, "%s\n", message.c_str());
- cuda_error_documentation();
-}
-
CUDADevice::CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
: Device(info, stats, profiler, background_), texture_info(this, "__texture_info", MEM_GLOBAL)
{
@@ -212,12 +185,19 @@ CUDADevice::CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
functions.loaded = false;
/* Intialize CUDA. */
- if (cuda_error(cuInit(0)))
+ CUresult result = cuInit(0);
+ if (result != CUDA_SUCCESS) {
+ set_error(string_printf("Failed to initialize CUDA runtime (%s)", cuewErrorString(result)));
return;
+ }
/* Setup device and context. */
- if (cuda_error(cuDeviceGet(&cuDevice, cuDevId)))
+ result = cuDeviceGet(&cuDevice, cuDevId);
+ if (result != CUDA_SUCCESS) {
+ set_error(string_printf("Failed to get CUDA device handle from ordinal (%s)",
+ cuewErrorString(result)));
return;
+ }
/* CU_CTX_MAP_HOST for mapping host memory when out of device memory.
* CU_CTX_LMEM_RESIZE_TO_MAX for reserving local memory ahead of render,
@@ -235,8 +215,6 @@ CUDADevice::CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
}
/* Create context. */
- CUresult result;
-
if (background) {
result = cuCtxCreate(&cuContext, ctx_flags, cuDevice);
}
@@ -249,8 +227,10 @@ CUDADevice::CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
}
}
- if (cuda_error_(result, "cuCtxCreate"))
+ if (result != CUDA_SUCCESS) {
+ set_error(string_printf("Failed to create CUDA context (%s)", cuewErrorString(result)));
return;
+ }
int major, minor;
cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
@@ -280,10 +260,8 @@ bool CUDADevice::support_device(const DeviceRequestedFeatures & /*requested_feat
/* We only support sm_30 and above */
if (major < 3) {
- cuda_error_message(
- string_printf("CUDA device supported only with compute capability 3.0 or up, found %d.%d.",
- major,
- minor));
+ set_error(string_printf(
+ "CUDA backend requires compute capability 3.0 or up, but found %d.%d.", major, minor));
return false;
}
@@ -319,13 +297,19 @@ bool CUDADevice::check_peer_access(Device *peer_device)
// Enable peer access in both directions
{
const CUDAContextScope scope(this);
- if (cuda_error(cuCtxEnablePeerAccess(peer_device_cuda->cuContext, 0))) {
+ CUresult result = cuCtxEnablePeerAccess(peer_device_cuda->cuContext, 0);
+ if (result != CUDA_SUCCESS) {
+ set_error(string_printf("Failed to enable peer access on CUDA context (%s)",
+ cuewErrorString(result)));
return false;
}
}
{
const CUDAContextScope scope(peer_device_cuda);
- if (cuda_error(cuCtxEnablePeerAccess(cuContext, 0))) {
+ CUresult result = cuCtxEnablePeerAccess(cuContext, 0);
+ if (result != CUDA_SUCCESS) {
+ set_error(string_printf("Failed to enable peer access on CUDA context (%s)",
+ cuewErrorString(result)));
return false;
}
}
@@ -432,14 +416,14 @@ string CUDADevice::compile_kernel(const DeviceRequestedFeatures &requested_featu
# ifdef _WIN32
if (!use_adaptive_compilation() && have_precompiled_kernels()) {
if (major < 3) {
- cuda_error_message(
- string_printf("CUDA device requires compute capability 3.0 or up, "
- "found %d.%d. Your GPU is not supported.",
+ set_error(
+ string_printf("CUDA backend requires compute capability 3.0 or up, but found %d.%d. "
+ "Your GPU is not supported.",
major,
minor));
}
else {
- cuda_error_message(
+ set_error(
string_printf("CUDA binary kernel for this graphics card compute "
"capability (%d.%d) not found.",
major,
@@ -452,7 +436,7 @@ string CUDADevice::compile_kernel(const DeviceRequestedFeatures &requested_featu
/* Compile. */
const char *const nvcc = cuewCompilerPath();
if (nvcc == NULL) {
- cuda_error_message(
+ set_error(
"CUDA nvcc compiler not found. "
"Install CUDA toolkit in default location.");
return string();
@@ -504,7 +488,7 @@ string CUDADevice::compile_kernel(const DeviceRequestedFeatures &requested_featu
command = "call " + command;
# endif
if (system(command.c_str()) != 0) {
- cuda_error_message(
+ set_error(
"Failed to execute compilation command, "
"see console for details.");
return string();
@@ -512,7 +496,7 @@ string CUDADevice::compile_kernel(const DeviceRequestedFeatures &requested_featu
/* Verify if compilation succeeded */
if (!path_exists(cubin)) {
- cuda_error_message(
+ set_error(
"CUDA kernel compilation failed, "
"see console for details.");
return string();
@@ -565,16 +549,19 @@ bool CUDADevice::load_kernels(const DeviceRequestedFeatures &requested_features)
else
result = CUDA_ERROR_FILE_NOT_FOUND;
- if (cuda_error_(result, "cuModuleLoad"))
- cuda_error_message(string_printf("Failed loading CUDA kernel %s.", cubin.c_str()));
+ if (result != CUDA_SUCCESS)
+ set_error(string_printf(
+ "Failed to load CUDA kernel from '%s' (%s)", cubin.c_str(), cuewErrorString(result)));
if (path_read_text(filter_cubin, cubin_data))
result = cuModuleLoadData(&cuFilterModule, cubin_data.c_str());
else
result = CUDA_ERROR_FILE_NOT_FOUND;
- if (cuda_error_(result, "cuModuleLoad"))
- cuda_error_message(string_printf("Failed loading CUDA kernel %s.", filter_cubin.c_str()));
+ if (result != CUDA_SUCCESS)
+ set_error(string_printf("Failed to load CUDA kernel from '%s' (%s)",
+ filter_cubin.c_str(),
+ cuewErrorString(result)));
if (result == CUDA_SUCCESS) {
reserve_local_memory(requested_features);
@@ -870,7 +857,7 @@ CUDADevice::CUDAMem *CUDADevice::generic_alloc(device_memory &mem, size_t pitch_
if (mem_alloc_result != CUDA_SUCCESS) {
status = " failed, out of device and host memory";
- cuda_assert(mem_alloc_result);
+ set_error("System is out of GPU and shared host memory");
}
if (mem.name) {
@@ -2458,14 +2445,10 @@ void CUDADevice::task_cancel()
# define cuda_assert(stmt) \
{ \
CUresult result = stmt; \
-\
if (result != CUDA_SUCCESS) { \
- string message = string_printf("CUDA error: %s in %s", cuewErrorString(result), #stmt); \
- if (device->error_msg == "") \
- device->error_msg = message; \
- fprintf(stderr, "%s\n", message.c_str()); \
- /*cuda_abort();*/ \
- device->cuda_error_documentation(); \
+ const char *name = cuewErrorString(result); \
+ device->set_error( \
+ string_printf("%s in %s (device_cuda_impl.cpp:%d)", name, #stmt, __LINE__)); \
} \
} \
(void)0
@@ -2647,14 +2630,15 @@ bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions &dim
SplitKernelFunction *CUDASplitKernel::get_split_kernel_function(const string &kernel_name,
const DeviceRequestedFeatures &)
{
- CUDAContextScope scope(device);
- CUfunction func;
+ const CUDAContextScope scope(device);
- cuda_assert(
- cuModuleGetFunction(&func, device->cuModule, (string("kernel_cuda_") + kernel_name).data()));
- if (device->have_error()) {
- device->cuda_error_message(
- string_printf("kernel \"kernel_cuda_%s\" not found in module", kernel_name.data()));
+ CUfunction func;
+ const CUresult result = cuModuleGetFunction(
+ &func, device->cuModule, (string("kernel_cuda_") + kernel_name).data());
+ if (result != CUDA_SUCCESS) {
+ device->set_error(string_printf("Could not find kernel \"kernel_cuda_%s\" in module (%s)",
+ kernel_name.data(),
+ cuewErrorString(result)));
return NULL;
}
diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp
index db04c13d083..fbf6a914744 100644
--- a/intern/cycles/device/device_optix.cpp
+++ b/intern/cycles/device/device_optix.cpp
@@ -70,7 +70,7 @@ struct KernelParams {
if (res != CUDA_SUCCESS) { \
const char *name; \
cuGetErrorName(res, &name); \
- set_error(string_printf("OptiX CUDA error %s in %s, line %d", name, #stmt, __LINE__)); \
+ set_error(string_printf("%s in %s (device_optix.cpp:%d)", name, #stmt, __LINE__)); \
return; \
} \
} \
@@ -81,7 +81,7 @@ struct KernelParams {
if (res != CUDA_SUCCESS) { \
const char *name; \
cuGetErrorName(res, &name); \
- set_error(string_printf("OptiX CUDA error %s in %s, line %d", name, #stmt, __LINE__)); \
+ set_error(string_printf("%s in %s (device_optix.cpp:%d)", name, #stmt, __LINE__)); \
return false; \
} \
} \
@@ -92,7 +92,7 @@ struct KernelParams {
enum OptixResult res = stmt; \
if (res != OPTIX_SUCCESS) { \
const char *name = optixGetErrorName(res); \
- set_error(string_printf("OptiX error %s in %s, line %d", name, #stmt, __LINE__)); \
+ set_error(string_printf("%s in %s (device_optix.cpp:%d)", name, #stmt, __LINE__)); \
return; \
} \
} \
@@ -102,7 +102,7 @@ struct KernelParams {
enum OptixResult res = stmt; \
if (res != OPTIX_SUCCESS) { \
const char *name = optixGetErrorName(res); \
- set_error(string_printf("OptiX error %s in %s, line %d", name, #stmt, __LINE__)); \
+ set_error(string_printf("%s in %s (device_optix.cpp:%d)", name, #stmt, __LINE__)); \
return false; \
} \
} \
@@ -322,12 +322,12 @@ class OptiXDevice : public CUDADevice {
// Disable baking for now, since its kernel is not well-suited for inlining and is very slow
if (requested_features.use_baking) {
- set_error("OptiX implementation does not support baking yet");
+ set_error("OptiX backend does not support baking yet");
return false;
}
// Disable shader raytracing support for now, since continuation callables are slow
if (requested_features.use_shader_raytrace) {
- set_error("OptiX implementation does not support shader raytracing yet");
+ set_error("OptiX backend does not support 'Ambient Occlusion' and 'Bevel' shader nodes yet");
return false;
}
@@ -386,14 +386,14 @@ class OptiXDevice : public CUDADevice {
if (use_adaptive_compilation() || path_file_size(ptx_filename) == -1) {
if (!getenv("OPTIX_ROOT_DIR")) {
set_error(
- "OPTIX_ROOT_DIR environment variable not set, must be set with the path to the "
- "Optix SDK in order to compile the Optix kernel on demand.");
+ "Missing OPTIX_ROOT_DIR environment variable (which must be set with the path to "
+ "the Optix SDK to be able to compile Optix kernels on demand).");
return false;
}
ptx_filename = compile_kernel(requested_features, "kernel_optix", "optix", true);
}
if (ptx_filename.empty() || !path_read_text(ptx_filename, ptx_data)) {
- set_error("Failed loading OptiX kernel " + ptx_filename + ".");
+ set_error("Failed to load OptiX kernel from '" + ptx_filename + "'");
return false;
}
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 7c50140ecfe..f5bfebbaf78 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -833,7 +833,7 @@ bool Session::load_kernels(bool lock_scene)
message = "Failed loading render kernel, see console for errors";
progress.set_error(message);
- progress.set_status("Error", message);
+ progress.set_status(message);
progress.set_update();
return false;
}
@@ -872,7 +872,7 @@ void Session::run()
/* progress update */
if (progress.get_cancel())
- progress.set_status("Cancel", progress.get_cancel_message());
+ progress.set_status(progress.get_cancel_message());
else
progress.set_update();
}
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index 3aab420a9b6..16687c34679 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -126,6 +126,7 @@ void GHOST_XrContext::storeInstanceProperties()
const std::map<std::string, GHOST_TXrOpenXRRuntimeID> runtime_map = {
{"Monado(XRT) by Collabora et al", OPENXR_RUNTIME_MONADO},
{"Oculus", OPENXR_RUNTIME_OCULUS},
+ {"SteamVR/OpenXR", OPENXR_RUNTIME_STEAMVR},
{"Windows Mixed Reality Runtime", OPENXR_RUNTIME_WMR}};
decltype(runtime_map)::const_iterator runtime_map_iter;
diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h
index 7dbd0a0d011..9be57cd90cc 100644
--- a/intern/ghost/intern/GHOST_XrContext.h
+++ b/intern/ghost/intern/GHOST_XrContext.h
@@ -49,6 +49,7 @@ struct GHOST_XrCustomFuncs {
enum GHOST_TXrOpenXRRuntimeID {
OPENXR_RUNTIME_MONADO,
OPENXR_RUNTIME_OCULUS,
+ OPENXR_RUNTIME_STEAMVR,
OPENXR_RUNTIME_WMR, /* Windows Mixed Reality */
OPENXR_RUNTIME_UNKNOWN
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
index edc4960cf32..7ae819dbfb2 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -380,7 +380,8 @@ static bool ghost_xr_draw_view_expects_srgb_buffer(const GHOST_XrContext *contex
/* Monado seems to be faulty and doesn't do OETF transform correctly. So expect a SRGB buffer to
* compensate. You get way too dark rendering without this, it's pretty obvious (even in the
* default startup scene). */
- return (context->getOpenXRRuntimeID() == OPENXR_RUNTIME_MONADO);
+ GHOST_TXrOpenXRRuntimeID runtime_id = context->getOpenXRRuntimeID();
+ return (runtime_id == OPENXR_RUNTIME_MONADO) || (runtime_id == OPENXR_RUNTIME_STEAMVR);
}
void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 0bf667482c4..79089b7cb89 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -237,7 +237,10 @@ class PHYSICS_PT_cloth_pressure(PhysicButtonsPanel, Panel):
col.prop(cloth, "target_volume")
col = flow.column()
- col.prop(cloth, "pressure_factor", text="Factor")
+ col.prop(cloth, "pressure_factor")
+
+ col = flow.column()
+ col.prop(cloth, "fluid_density")
col = flow.column()
col.prop_search(cloth, "vertex_group_pressure", ob, "vertex_groups", text="Vertex Group")
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 0cd99efcca9..210d850ad06 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -46,8 +46,8 @@ def physics_add(layout, md, name, type, typeicon, toggles):
icon='X',
)
if toggles:
- row.prop(md, "show_render", text="")
row.prop(md, "show_viewport", text="")
+ row.prop(md, "show_render", text="")
else:
row.operator(
"object.modifier_add",
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index f6f22ad464f..553d79fb349 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -400,7 +400,7 @@ class TEXT_MT_edit(Menu):
layout.separator()
layout.operator("text.start_find", text="Find & Replace...")
- layout.operator("text.find_set_selected", text="Find Next")
+ layout.operator("text.find_set_selected")
layout.operator("text.jump", text="Jump To...")
layout.separator()
diff --git a/source/blender/blenkernel/BKE_anim_path.h b/source/blender/blenkernel/BKE_anim_path.h
index 64bcedefa58..4de853303ad 100644
--- a/source/blender/blenkernel/BKE_anim_path.h
+++ b/source/blender/blenkernel/BKE_anim_path.h
@@ -36,13 +36,13 @@ struct Path;
void free_path(struct Path *path);
void calc_curvepath(struct Object *ob, struct ListBase *nurbs);
-int where_on_path(struct Object *ob,
- float ctime,
- float vec[4],
- float dir[3],
- float quat[4],
- float *radius,
- float *weight);
+bool where_on_path(const struct Object *ob,
+ float ctime,
+ float r_vec[4],
+ float r_dir[3],
+ float r_quat[4],
+ float *r_radius,
+ float *r_weight);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index c22e7a24afe..6fb6675a05a 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -28,15 +28,18 @@
extern "C" {
#endif
+struct BMEditMesh;
struct Bone;
struct Depsgraph;
struct ListBase;
struct Main;
+struct Mesh;
struct Object;
struct PoseTree;
struct Scene;
struct bArmature;
struct bConstraint;
+struct bGPDstroke;
struct bPose;
struct bPoseChannel;
@@ -342,6 +345,45 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph,
struct Object *object,
int pchan_index);
+/* -------------------------------------------------------------------- */
+/** \name Deform 3D Coordinates by Armature (armature_deform.c)
+ * \{ */
+
+/* Note that we could have a 'BKE_armature_deform_coords' that doesn't take object data
+ * currently there are no callers for this though. */
+
+void BKE_armature_deform_coords_with_gpencil_stroke(const struct Object *ob_arm,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ struct bGPDstroke *gps_target);
+
+void BKE_armature_deform_coords_with_mesh(const struct Object *ob_arm,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ const struct Mesh *me_target);
+
+void BKE_armature_deform_coords_with_editmesh(const struct Object *ob_arm,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ struct BMEditMesh *em_target);
+
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index f5073ff7aa5..f25482570b1 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -93,9 +93,10 @@ typedef struct Cloth {
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct EdgeSet *edgeset; /* used for selfcollisions */
int last_frame;
- float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */
- struct MEdge *edges; /* Used for hair collisions. */
- struct GHash *sew_edge_graph; /* Sewing edges represented using a GHash */
+ float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */
+ float average_acceleration[3]; /* Moving average of overall acceleration. */
+ struct MEdge *edges; /* Used for hair collisions. */
+ struct GHash *sew_edge_graph; /* Sewing edges represented using a GHash */
} Cloth;
/**
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 40f73ccfe84..d32ab474229 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -29,11 +29,13 @@
extern "C" {
#endif
+struct BMEditMesh;
struct BezTriple;
struct Curve;
struct Depsgraph;
struct GHash;
struct ListBase;
+struct MDeformVert;
struct Main;
struct Nurb;
struct Object;
@@ -278,7 +280,15 @@ enum {
void BKE_curve_batch_cache_dirty_tag(struct Curve *cu, int mode);
void BKE_curve_batch_cache_free(struct Curve *cu);
-/* curve_decimate.c */
+extern void (*BKE_curve_batch_cache_dirty_tag_cb)(struct Curve *cu, int mode);
+extern void (*BKE_curve_batch_cache_free_cb)(struct Curve *cu);
+
+/* -------------------------------------------------------------------- */
+/** \name Decimate Curve (curve_decimate.c)
+ *
+ * Simplify curve data.
+ * \{ */
+
unsigned int BKE_curve_decimate_bezt_array(struct BezTriple *bezt_array,
const unsigned int bezt_array_len,
const unsigned int resolu,
@@ -293,8 +303,38 @@ void BKE_curve_decimate_nurb(struct Nurb *nu,
const float error_sq_max,
const unsigned int error_target_len);
-extern void (*BKE_curve_batch_cache_dirty_tag_cb)(struct Curve *cu, int mode);
-extern void (*BKE_curve_batch_cache_free_cb)(struct Curve *cu);
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Deform 3D Coordinates by Curve (curve_deform.c)
+ * \{ */
+
+void BKE_curve_deform_coords(const struct Object *ob_curve,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const struct MDeformVert *dvert,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis);
+
+void BKE_curve_deform_coords_with_editmesh(const Object *ob_curve,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis,
+ struct BMEditMesh *em_target);
+
+void BKE_curve_deform_co(const struct Object *ob_curve,
+ const struct Object *ob_target,
+ const float orco[3],
+ float vec[3],
+ const int no_rot_axis,
+ float r_mat[3][3]);
+
+/** \} */
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index c86b877b575..04b85aebb39 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -40,14 +40,16 @@ struct bDeformGroup;
struct bDeformGroup *BKE_object_defgroup_new(struct Object *ob, const char *name);
void BKE_defgroup_copy_list(struct ListBase *lb1, const struct ListBase *lb2);
struct bDeformGroup *BKE_defgroup_duplicate(const struct bDeformGroup *ingroup);
-struct bDeformGroup *BKE_object_defgroup_find_name(struct Object *ob, const char *name);
-int *BKE_object_defgroup_flip_map(struct Object *ob, int *flip_map_len, const bool use_default);
-int *BKE_object_defgroup_flip_map_single(struct Object *ob,
+struct bDeformGroup *BKE_object_defgroup_find_name(const struct Object *ob, const char *name);
+int *BKE_object_defgroup_flip_map(const struct Object *ob,
+ int *flip_map_len,
+ const bool use_default);
+int *BKE_object_defgroup_flip_map_single(const struct Object *ob,
int *flip_map_len,
const bool use_default,
int defgroup);
-int BKE_object_defgroup_flip_index(struct Object *ob, int index, const bool use_default);
-int BKE_object_defgroup_name_index(struct Object *ob, const char *name);
+int BKE_object_defgroup_flip_index(const struct Object *ob, int index, const bool use_default);
+int BKE_object_defgroup_name_index(const struct Object *ob, const char *name);
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob);
struct MDeformWeight *BKE_defvert_find_index(const struct MDeformVert *dv, const int defgroup);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 3cd8c69a263..bb23ad63020 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -30,6 +30,7 @@
extern "C" {
#endif
+struct BMEditMesh;
struct BPoint;
struct Depsgraph;
struct Lattice;
@@ -45,48 +46,9 @@ struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
struct Lattice *BKE_lattice_copy(struct Main *bmain, const struct Lattice *lt);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
-struct LatticeDeformData *init_latt_deform(struct Object *oblatt,
- struct Object *ob) ATTR_WARN_UNUSED_RESULT;
-void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight);
-void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
-
bool object_deform_mball(struct Object *ob, struct ListBase *dispbase);
void outside_lattice(struct Lattice *lt);
-void curve_deform_verts(struct Object *cuOb,
- struct Object *target,
- float (*vert_coords)[3],
- int numVerts,
- struct MDeformVert *dvert,
- const int defgrp_index,
- short flag,
- short defaxis);
-void curve_deform_vector(struct Object *cuOb,
- struct Object *target,
- float orco[3],
- float vec[3],
- float mat[3][3],
- int no_rot_axis);
-
-void lattice_deform_verts(struct Object *laOb,
- struct Object *target,
- struct Mesh *mesh,
- float (*vert_coords)[3],
- int numVerts,
- short flag,
- const char *vgroup,
- float influence);
-void armature_deform_verts(struct Object *armOb,
- struct Object *target,
- const struct Mesh *mesh,
- float (*vert_coords)[3],
- float (*defMats)[3][3],
- int numVerts,
- int deformflag,
- float (*prevCos)[3],
- const char *defgrp_name,
- struct bGPDstroke *gps);
-
float (*BKE_lattice_vert_coords_alloc(const struct Lattice *lt, int *r_vert_len))[3];
void BKE_lattice_vert_coords_get(const struct Lattice *lt, float (*vert_coords)[3]);
void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt,
@@ -97,7 +59,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
-struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice);
+struct MDeformVert *BKE_lattice_deform_verts_get(const struct Object *lattice);
struct BPoint *BKE_lattice_active_point_get(struct Lattice *lt);
struct BoundBox *BKE_lattice_boundbox_get(struct Object *ob);
@@ -137,6 +99,44 @@ void BKE_lattice_batch_cache_free(struct Lattice *lt);
extern void (*BKE_lattice_batch_cache_dirty_tag_cb)(struct Lattice *lt, int mode);
extern void (*BKE_lattice_batch_cache_free_cb)(struct Lattice *lt);
+/* -------------------------------------------------------------------- */
+/** \name Deform 3D Coordinates by Lattice (lattice_deform.c)
+ * \{ */
+
+struct LatticeDeformData *BKE_lattice_deform_data_create(
+ const struct Object *oblatt, const struct Object *ob) ATTR_WARN_UNUSED_RESULT;
+void BKE_lattice_deform_data_eval_co(struct LatticeDeformData *lattice_deform_data,
+ float co[3],
+ float weight);
+void BKE_lattice_deform_data_destroy(struct LatticeDeformData *lattice_deform_data);
+
+void BKE_lattice_deform_coords(const struct Object *ob_lattice,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ float influence);
+
+void BKE_lattice_deform_coords_with_mesh(const struct Object *ob_lattice,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float influence,
+ const struct Mesh *me_target);
+
+void BKE_lattice_deform_coords_with_editmesh(const struct Object *ob_lattice,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float influence,
+ struct BMEditMesh *em_target);
+/** \} */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mesh_wrapper.h b/source/blender/blenkernel/BKE_mesh_wrapper.h
index ec6a1e3457c..00e2dd08726 100644
--- a/source/blender/blenkernel/BKE_mesh_wrapper.h
+++ b/source/blender/blenkernel/BKE_mesh_wrapper.h
@@ -31,7 +31,7 @@ extern "C" {
struct Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(
struct BMEditMesh *em,
const struct CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
+ const float (*vert_coords)[3],
const struct Mesh *me_settings);
struct Mesh *BKE_mesh_wrapper_from_editmesh(struct BMEditMesh *em,
const struct CustomData_MeshMasks *cd_mask_extra,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 4d30c5c7fce..144e091d971 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -24,6 +24,7 @@
* \ingroup bke
*/
+#include "BLI_ghash.h"
#include "BLI_utildefines.h"
#include "DNA_object_enums.h"
@@ -268,6 +269,7 @@ typedef struct SculptClothLengthConstraint {
typedef struct SculptClothSimulation {
SculptClothLengthConstraint *length_constraints;
int tot_length_constraints;
+ GSet *created_length_constraints;
int capacity_length_constraints;
float *length_constraint_tweak;
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 45cd4933f80..92e0904c568 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRC
intern/anim_visualization.c
intern/appdir.c
intern/armature.c
+ intern/armature_deform.c
intern/armature_update.c
intern/asset_engine.c
intern/autoexec.c
@@ -100,6 +101,7 @@ set(SRC
intern/crazyspace.c
intern/curve.c
intern/curve_decimate.c
+ intern/curve_deform.c
intern/curveprofile.c
intern/customdata.c
intern/customdata_file.c
@@ -139,6 +141,7 @@ set(SRC
intern/key.c
intern/keyconfig.c
intern/lattice.c
+ intern/lattice_deform.c
intern/layer.c
intern/layer_utils.c
intern/lib_id.c
diff --git a/source/blender/blenkernel/intern/anim_path.c b/source/blender/blenkernel/intern/anim_path.c
index e073bd6fc82..628e54971ce 100644
--- a/source/blender/blenkernel/intern/anim_path.c
+++ b/source/blender/blenkernel/intern/anim_path.c
@@ -42,9 +42,11 @@ static CLG_LogRef LOG = {"bke.anim"};
/* ******************************************************************** */
/* Curve Paths - for curve deforms and/or curve following */
-/* free curve path data
- * NOTE: frees the path itself!
- * NOTE: this is increasingly inaccurate with non-uniform BevPoint subdivisions [#24633]
+/**
+ * Free curve path data
+ *
+ * \note Frees the path itself!
+ * \note This is increasingly inaccurate with non-uniform #BevPoint subdivisions T24633.
*/
void free_path(Path *path)
{
@@ -54,8 +56,9 @@ void free_path(Path *path)
MEM_freeN(path);
}
-/* calculate a curve-deform path for a curve
- * - only called from displist.c -> do_makeDispListCurveTypes
+/**
+ * Calculate a curve-deform path for a curve
+ * - Only called from displist.c -> #do_makeDispListCurveTypes
*/
void calc_curvepath(Object *ob, ListBase *nurbs)
{
@@ -192,39 +195,40 @@ static int interval_test(const int min, const int max, int p1, const int cycl)
return p1;
}
-/* calculate the deformation implied by the curve path at a given parametric position,
+/**
+ * Calculate the deformation implied by the curve path at a given parametric position,
* and returns whether this operation succeeded.
*
- * note: ctime is normalized range <0-1>
+ * \param ctime: Time is normalized range <0-1>.
*
- * returns OK: 1/0
+ * \return success.
*/
-int where_on_path(Object *ob,
- float ctime,
- float vec[4],
- float dir[3],
- float quat[4],
- float *radius,
- float *weight)
+bool where_on_path(const Object *ob,
+ float ctime,
+ float r_vec[4],
+ float r_dir[3],
+ float r_quat[4],
+ float *r_radius,
+ float *r_weight)
{
Curve *cu;
- Nurb *nu;
- BevList *bl;
- Path *path;
- PathPoint *pp, *p0, *p1, *p2, *p3;
+ const Nurb *nu;
+ const BevList *bl;
+ const Path *path;
+ const PathPoint *pp, *p0, *p1, *p2, *p3;
float fac;
float data[4];
int cycl = 0, s0, s1, s2, s3;
- ListBase *nurbs;
+ const ListBase *nurbs;
if (ob == NULL || ob->type != OB_CURVE) {
- return 0;
+ return false;
}
cu = ob->data;
if (ob->runtime.curve_cache == NULL || ob->runtime.curve_cache->path == NULL ||
ob->runtime.curve_cache->path->data == NULL) {
CLOG_WARN(&LOG, "no path!");
- return 0;
+ return false;
}
path = ob->runtime.curve_cache->path;
pp = path->data;
@@ -232,10 +236,10 @@ int where_on_path(Object *ob,
/* test for cyclic */
bl = ob->runtime.curve_cache->bev.first;
if (!bl) {
- return 0;
+ return false;
}
if (!bl->nr) {
- return 0;
+ return false;
}
if (bl->poly > -1) {
cycl = 1;
@@ -262,7 +266,7 @@ int where_on_path(Object *ob,
/* NOTE: commented out for follow constraint
*
- * If it's ever be uncommented watch out for curve_deform_verts()
+ * If it's ever be uncommented watch out for BKE_curve_deform_coords()
* which used to temporary set CU_FOLLOW flag for the curve and no
* longer does it (because of threading issues of such a thing.
*/
@@ -270,10 +274,10 @@ int where_on_path(Object *ob,
key_curve_tangent_weights(1.0f - fac, data, KEY_BSPLINE);
- interp_v3_v3v3v3v3(dir, p0->vec, p1->vec, p2->vec, p3->vec, data);
+ interp_v3_v3v3v3v3(r_dir, p0->vec, p1->vec, p2->vec, p3->vec, data);
- /* make compatible with vectoquat */
- negate_v3(dir);
+ /* Make compatible with #vec_to_quat. */
+ negate_v3(r_dir);
//}
nurbs = BKE_curve_editNurbs_get(cu);
@@ -296,16 +300,16 @@ int where_on_path(Object *ob,
key_curve_position_weights(1.0f - fac, data, KEY_BSPLINE);
}
- vec[0] = data[0] * p0->vec[0] + data[1] * p1->vec[0] + data[2] * p2->vec[0] +
- data[3] * p3->vec[0]; /* X */
- vec[1] = data[0] * p0->vec[1] + data[1] * p1->vec[1] + data[2] * p2->vec[1] +
- data[3] * p3->vec[1]; /* Y */
- vec[2] = data[0] * p0->vec[2] + data[1] * p1->vec[2] + data[2] * p2->vec[2] +
- data[3] * p3->vec[2]; /* Z */
- vec[3] = data[0] * p0->vec[3] + data[1] * p1->vec[3] + data[2] * p2->vec[3] +
- data[3] * p3->vec[3]; /* Tilt, should not be needed since we have quat still used */
+ r_vec[0] = /* X */
+ data[0] * p0->vec[0] + data[1] * p1->vec[0] + data[2] * p2->vec[0] + data[3] * p3->vec[0];
+ r_vec[1] = /* Y */
+ data[0] * p0->vec[1] + data[1] * p1->vec[1] + data[2] * p2->vec[1] + data[3] * p3->vec[1];
+ r_vec[2] = /* Z */
+ data[0] * p0->vec[2] + data[1] * p1->vec[2] + data[2] * p2->vec[2] + data[3] * p3->vec[2];
+ r_vec[3] = /* Tilt, should not be needed since we have quat still used */
+ data[0] * p0->vec[3] + data[1] * p1->vec[3] + data[2] * p2->vec[3] + data[3] * p3->vec[3];
- if (quat) {
+ if (r_quat) {
float totfac, q1[4], q2[4];
totfac = data[0] + data[3];
@@ -326,22 +330,22 @@ int where_on_path(Object *ob,
totfac = data[0] + data[1] + data[2] + data[3];
if (totfac > FLT_EPSILON) {
- interp_qt_qtqt(quat, q1, q2, (data[1] + data[2]) / totfac);
+ interp_qt_qtqt(r_quat, q1, q2, (data[1] + data[2]) / totfac);
}
else {
- copy_qt_qt(quat, q2);
+ copy_qt_qt(r_quat, q2);
}
}
- if (radius) {
- *radius = data[0] * p0->radius + data[1] * p1->radius + data[2] * p2->radius +
- data[3] * p3->radius;
+ if (r_radius) {
+ *r_radius = data[0] * p0->radius + data[1] * p1->radius + data[2] * p2->radius +
+ data[3] * p3->radius;
}
- if (weight) {
- *weight = data[0] * p0->weight + data[1] * p1->weight + data[2] * p2->weight +
- data[3] * p3->weight;
+ if (r_weight) {
+ *r_weight = data[0] * p0->weight + data[1] * p1->weight + data[2] * p2->weight +
+ data[3] * p3->weight;
}
- return 1;
+ return true;
}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 36921bd2662..007062abb5b 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -35,18 +35,12 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
-#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_lattice_types.h"
#include "DNA_listBase.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -55,11 +49,8 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
-#include "BKE_deform.h"
-#include "BKE_displist.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
@@ -71,13 +62,13 @@
#include "BIK_api.h"
-#include "atomic_ops.h"
-
#include "CLG_log.h"
static CLG_LogRef LOG = {"bke.armature"};
-/*************************** Prototypes ***************************/
+/* -------------------------------------------------------------------- */
+/** \name Prototypes
+ * \{ */
static void copy_bonechildren(Bone *bone_dst,
const Bone *bone_src,
@@ -87,7 +78,11 @@ static void copy_bonechildren(Bone *bone_dst,
static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst);
-/*********************** Armature Datablock ***********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Data-block
+ * \{ */
/**
* Only copy internal data of Armature ID from source
@@ -187,7 +182,11 @@ IDTypeInfo IDType_ID_AR = {
.foreach_id = armature_foreach_id,
};
-/* **************** Generic Functions, data level *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic Data-Level Functions
+ * \{ */
bArmature *BKE_armature_add(Main *bmain, const char *name)
{
@@ -284,6 +283,12 @@ bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm)
return arm_copy;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Transform Copy
+ * \{ */
+
static void copy_bone_transform(Bone *bone_dst, const Bone *bone_src)
{
bone_dst->roll = bone_src->roll;
@@ -313,6 +318,14 @@ void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Transform by 4x4 Matrix
+ *
+ * \see #ED_armature_edit_transform for the edit-mode version of this function.
+ * \{ */
+
/** Helper for #ED_armature_transform */
static void armature_transform_recurse(ListBase *bonebase,
const float mat[4][4],
@@ -408,6 +421,14 @@ void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do
armature_transform_recurse(&arm->bonebase, mat, do_props, mat3, scale, NULL, NULL);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Bone Find by Name
+ *
+ * Using fast #GHash look-ups when available.
+ * \{ */
+
static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name)
{
Bone *curBone, *rbone;
@@ -480,6 +501,12 @@ void BKE_armature_bone_hash_free(bArmature *arm)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Bone Flags
+ * \{ */
+
bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
{
if (bone->flag & flag) {
@@ -493,6 +520,12 @@ bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Layer Refresh Used
+ * \{ */
+
static void armature_refresh_layer_used_recursive(bArmature *arm, ListBase *bones)
{
LISTBASE_FOREACH (Bone *, bone, bones) {
@@ -518,6 +551,12 @@ void BKE_armature_refresh_layer_used(struct Depsgraph *depsgraph, struct bArmatu
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Layer Refresh Used
+ * \{ */
+
/* Finds the best possible extension to the name on a particular axis. (For renaming, check for
* unique names afterwards) strip_number: removes number extensions (TODO: not used)
* axis: the axis to name on
@@ -654,7 +693,11 @@ int bone_autoside_name(
}
}
-/* ************* B-Bone support ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature B-Bone Support
+ * \{ */
/* Compute a set of bezier parameter values that produce approximately equally spaced points. */
static void equalize_cubic_bezier(const float control[4][3],
@@ -1209,8 +1252,6 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
return param->segments;
}
-/* ************ Armature Deform ******************* */
-
static void allocate_bbone_cache(bPoseChannel *pchan, int segments)
{
bPoseChannel_Runtime *runtime = &pchan->runtime;
@@ -1331,498 +1372,11 @@ void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan,
*r_blend_next = blend;
}
-/* Add the effect of one bone or B-Bone segment to the accumulated result. */
-static void pchan_deform_accumulate(const DualQuat *deform_dq,
- const float deform_mat[4][4],
- const float co_in[3],
- float weight,
- float co_accum[3],
- DualQuat *dq_accum,
- float mat_accum[3][3])
-{
- if (weight == 0.0f) {
- return;
- }
-
- if (dq_accum) {
- BLI_assert(!co_accum);
-
- add_weighted_dq_dq(dq_accum, deform_dq, weight);
- }
- else {
- float tmp[3];
- mul_v3_m4v3(tmp, deform_mat, co_in);
-
- sub_v3_v3(tmp, co_in);
- madd_v3_v3fl(co_accum, tmp, weight);
-
- if (mat_accum) {
- float tmpmat[3][3];
- copy_m3_m4(tmpmat, deform_mat);
-
- madd_m3_m3m3fl(mat_accum, mat_accum, tmpmat, weight);
- }
- }
-}
-
-static void b_bone_deform(const bPoseChannel *pchan,
- const float co[3],
- float weight,
- float vec[3],
- DualQuat *dq,
- float defmat[3][3])
-{
- const DualQuat *quats = pchan->runtime.bbone_dual_quats;
- const Mat4 *mats = pchan->runtime.bbone_deform_mats;
- const float(*mat)[4] = mats[0].mat;
- float blend, y;
- int index;
-
- /* Transform co to bone space and get its y component. */
- y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
-
- /* Calculate the indices of the 2 affecting b_bone segments. */
- BKE_pchan_bbone_deform_segment_index(pchan, y / pchan->bone->length, &index, &blend);
-
- pchan_deform_accumulate(
- &quats[index], mats[index + 1].mat, co, weight * (1.0f - blend), vec, dq, defmat);
- pchan_deform_accumulate(
- &quats[index + 1], mats[index + 2].mat, co, weight * blend, vec, dq, defmat);
-}
-
-/* using vec with dist to bone b1 - b2 */
-float distfactor_to_bone(
- const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
-{
- float dist_sq;
- float bdelta[3];
- float pdelta[3];
- float hsqr, a, l, rad;
-
- sub_v3_v3v3(bdelta, b2, b1);
- l = normalize_v3(bdelta);
-
- sub_v3_v3v3(pdelta, vec, b1);
-
- a = dot_v3v3(bdelta, pdelta);
- hsqr = len_squared_v3(pdelta);
-
- if (a < 0.0f) {
- /* If we're past the end of the bone, do a spherical field attenuation thing */
- dist_sq = len_squared_v3v3(b1, vec);
- rad = rad1;
- }
- else if (a > l) {
- /* If we're past the end of the bone, do a spherical field attenuation thing */
- dist_sq = len_squared_v3v3(b2, vec);
- rad = rad2;
- }
- else {
- dist_sq = (hsqr - (a * a));
-
- if (l != 0.0f) {
- rad = a / l;
- rad = rad * rad2 + (1.0f - rad) * rad1;
- }
- else {
- rad = rad1;
- }
- }
-
- a = rad * rad;
- if (dist_sq < a) {
- return 1.0f;
- }
- else {
- l = rad + rdist;
- l *= l;
- if (rdist == 0.0f || dist_sq >= l) {
- return 0.0f;
- }
- else {
- a = sqrtf(dist_sq) - rad;
- return 1.0f - (a * a) / (rdist * rdist);
- }
- }
-}
-
-static float dist_bone_deform(
- bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3])
-{
- Bone *bone = pchan->bone;
- float fac, contrib = 0.0;
+/** \} */
- if (bone == NULL) {
- return 0.0f;
- }
-
- fac = distfactor_to_bone(
- co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
-
- if (fac > 0.0f) {
- fac *= bone->weight;
- contrib = fac;
- if (contrib > 0.0f) {
- if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
- b_bone_deform(pchan, co, fac, vec, dq, mat);
- }
- else {
- pchan_deform_accumulate(
- &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, fac, vec, dq, mat);
- }
- }
- }
-
- return contrib;
-}
-
-static void pchan_bone_deform(bPoseChannel *pchan,
- float weight,
- float vec[3],
- DualQuat *dq,
- float mat[3][3],
- const float co[3],
- float *contrib)
-{
- Bone *bone = pchan->bone;
-
- if (!weight) {
- return;
- }
-
- if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
- b_bone_deform(pchan, co, weight, vec, dq, mat);
- }
- else {
- pchan_deform_accumulate(
- &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, weight, vec, dq, mat);
- }
-
- (*contrib) += weight;
-}
-
-typedef struct ArmatureUserdata {
- Object *armOb;
- Object *target;
- const Mesh *mesh;
- float (*vertexCos)[3];
- float (*defMats)[3][3];
- float (*prevCos)[3];
-
- bool use_envelope;
- bool use_quaternion;
- bool invert_vgroup;
- bool use_dverts;
-
- int armature_def_nr;
-
- int target_totvert;
- MDeformVert *dverts;
-
- int defbase_tot;
- bPoseChannel **defnrToPC;
-
- float premat[4][4];
- float postmat[4][4];
-} ArmatureUserdata;
-
-static void armature_vert_task(void *__restrict userdata,
- const int i,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- const ArmatureUserdata *data = userdata;
- float(*const vertexCos)[3] = data->vertexCos;
- float(*const defMats)[3][3] = data->defMats;
- float(*const prevCos)[3] = data->prevCos;
- const bool use_envelope = data->use_envelope;
- const bool use_quaternion = data->use_quaternion;
- const bool use_dverts = data->use_dverts;
- const int armature_def_nr = data->armature_def_nr;
-
- MDeformVert *dvert;
- DualQuat sumdq, *dq = NULL;
- bPoseChannel *pchan;
- float *co, dco[3];
- float sumvec[3], summat[3][3];
- float *vec = NULL, (*smat)[3] = NULL;
- float contrib = 0.0f;
- float armature_weight = 1.0f; /* default to 1 if no overall def group */
- float prevco_weight = 1.0f; /* weight for optional cached vertexcos */
-
- if (use_quaternion) {
- memset(&sumdq, 0, sizeof(DualQuat));
- dq = &sumdq;
- }
- else {
- sumvec[0] = sumvec[1] = sumvec[2] = 0.0f;
- vec = sumvec;
-
- if (defMats) {
- zero_m3(summat);
- smat = summat;
- }
- }
-
- if (use_dverts || armature_def_nr != -1) {
- if (data->mesh) {
- BLI_assert(i < data->mesh->totvert);
- if (data->mesh->dvert != NULL) {
- dvert = data->mesh->dvert + i;
- }
- else {
- dvert = NULL;
- }
- }
- else if (data->dverts && i < data->target_totvert) {
- dvert = data->dverts + i;
- }
- else {
- dvert = NULL;
- }
- }
- else {
- dvert = NULL;
- }
-
- if (armature_def_nr != -1 && dvert) {
- armature_weight = BKE_defvert_find_weight(dvert, armature_def_nr);
-
- if (data->invert_vgroup) {
- armature_weight = 1.0f - armature_weight;
- }
-
- /* hackish: the blending factor can be used for blending with prevCos too */
- if (prevCos) {
- prevco_weight = armature_weight;
- armature_weight = 1.0f;
- }
- }
-
- /* check if there's any point in calculating for this vert */
- if (armature_weight == 0.0f) {
- return;
- }
-
- /* get the coord we work on */
- co = prevCos ? prevCos[i] : vertexCos[i];
-
- /* Apply the object's matrix */
- mul_m4_v3(data->premat, co);
-
- if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
- MDeformWeight *dw = dvert->dw;
- int deformed = 0;
- unsigned int j;
- for (j = dvert->totweight; j != 0; j--, dw++) {
- const uint index = dw->def_nr;
- if (index < data->defbase_tot && (pchan = data->defnrToPC[index])) {
- float weight = dw->weight;
- Bone *bone = pchan->bone;
-
- deformed = 1;
-
- if (bone && bone->flag & BONE_MULT_VG_ENV) {
- weight *= distfactor_to_bone(
- co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
- }
-
- pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
- }
- }
- /* if there are vertexgroups but not groups with bones
- * (like for softbody groups) */
- if (deformed == 0 && use_envelope) {
- for (pchan = data->armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
- contrib += dist_bone_deform(pchan, vec, dq, smat, co);
- }
- }
- }
- }
- else if (use_envelope) {
- for (pchan = data->armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
- contrib += dist_bone_deform(pchan, vec, dq, smat, co);
- }
- }
- }
-
- /* actually should be EPSILON? weight values and contrib can be like 10e-39 small */
- if (contrib > 0.0001f) {
- if (use_quaternion) {
- normalize_dq(dq, contrib);
-
- if (armature_weight != 1.0f) {
- copy_v3_v3(dco, co);
- mul_v3m3_dq(dco, (defMats) ? summat : NULL, dq);
- sub_v3_v3(dco, co);
- mul_v3_fl(dco, armature_weight);
- add_v3_v3(co, dco);
- }
- else {
- mul_v3m3_dq(co, (defMats) ? summat : NULL, dq);
- }
-
- smat = summat;
- }
- else {
- mul_v3_fl(vec, armature_weight / contrib);
- add_v3_v3v3(co, vec, co);
- }
-
- if (defMats) {
- float pre[3][3], post[3][3], tmpmat[3][3];
-
- copy_m3_m4(pre, data->premat);
- copy_m3_m4(post, data->postmat);
- copy_m3_m3(tmpmat, defMats[i]);
-
- if (!use_quaternion) { /* quaternion already is scale corrected */
- mul_m3_fl(smat, armature_weight / contrib);
- }
-
- mul_m3_series(defMats[i], post, smat, pre, tmpmat);
- }
- }
-
- /* always, check above code */
- mul_m4_v3(data->postmat, co);
-
- /* interpolate with previous modifier position using weight group */
- if (prevCos) {
- float mw = 1.0f - prevco_weight;
- vertexCos[i][0] = prevco_weight * vertexCos[i][0] + mw * co[0];
- vertexCos[i][1] = prevco_weight * vertexCos[i][1] + mw * co[1];
- vertexCos[i][2] = prevco_weight * vertexCos[i][2] + mw * co[2];
- }
-}
-
-void armature_deform_verts(Object *armOb,
- Object *target,
- const Mesh *mesh,
- float (*vertexCos)[3],
- float (*defMats)[3][3],
- int numVerts,
- int deformflag,
- float (*prevCos)[3],
- const char *defgrp_name,
- bGPDstroke *gps)
-{
- bArmature *arm = armOb->data;
- bPoseChannel **defnrToPC = NULL;
- MDeformVert *dverts = NULL;
- bDeformGroup *dg;
- const bool use_envelope = (deformflag & ARM_DEF_ENVELOPE) != 0;
- const bool use_quaternion = (deformflag & ARM_DEF_QUATERNION) != 0;
- const bool invert_vgroup = (deformflag & ARM_DEF_INVERT_VGROUP) != 0;
- int defbase_tot = 0; /* safety for vertexgroup index overflow */
- int i, target_totvert = 0; /* safety for vertexgroup overflow */
- bool use_dverts = false;
- int armature_def_nr;
-
- /* in editmode, or not an armature */
- if (arm->edbo || (armOb->pose == NULL)) {
- return;
- }
-
- if ((armOb->pose->flag & POSE_RECALC) != 0) {
- CLOG_ERROR(&LOG,
- "Trying to evaluate influence of armature '%s' which needs Pose recalc!",
- armOb->id.name);
- BLI_assert(0);
- }
-
- /* get the def_nr for the overall armature vertex group if present */
- armature_def_nr = BKE_object_defgroup_name_index(target, defgrp_name);
-
- if (ELEM(target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
- defbase_tot = BLI_listbase_count(&target->defbase);
-
- if (target->type == OB_MESH) {
- Mesh *me = target->data;
- dverts = me->dvert;
- if (dverts) {
- target_totvert = me->totvert;
- }
- }
- else if (target->type == OB_LATTICE) {
- Lattice *lt = target->data;
- dverts = lt->dvert;
- if (dverts) {
- target_totvert = lt->pntsu * lt->pntsv * lt->pntsw;
- }
- }
- else if (target->type == OB_GPENCIL) {
- dverts = gps->dvert;
- if (dverts) {
- target_totvert = gps->totpoints;
- }
- }
- }
-
- /* get a vertex-deform-index to posechannel array */
- if (deformflag & ARM_DEF_VGROUP) {
- if (ELEM(target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
- /* if we have a Mesh, only use dverts if it has them */
- if (mesh) {
- use_dverts = (mesh->dvert != NULL);
- }
- else if (dverts) {
- use_dverts = true;
- }
-
- if (use_dverts) {
- defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone");
- /* TODO(sergey): Some considerations here:
- *
- * - Check whether keeping this consistent across frames gives speedup.
- */
- for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) {
- defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name);
- /* exclude non-deforming bones */
- if (defnrToPC[i]) {
- if (defnrToPC[i]->bone->flag & BONE_NO_DEFORM) {
- defnrToPC[i] = NULL;
- }
- }
- }
- }
- }
- }
-
- ArmatureUserdata data = {.armOb = armOb,
- .target = target,
- .mesh = mesh,
- .vertexCos = vertexCos,
- .defMats = defMats,
- .prevCos = prevCos,
- .use_envelope = use_envelope,
- .use_quaternion = use_quaternion,
- .invert_vgroup = invert_vgroup,
- .use_dverts = use_dverts,
- .armature_def_nr = armature_def_nr,
- .target_totvert = target_totvert,
- .dverts = dverts,
- .defbase_tot = defbase_tot,
- .defnrToPC = defnrToPC};
-
- float obinv[4][4];
- invert_m4_m4(obinv, target->obmat);
-
- mul_m4_m4m4(data.postmat, obinv, armOb->obmat);
- invert_m4_m4(data.premat, data.postmat);
-
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 32;
- BLI_task_parallel_range(0, numVerts, &data, armature_vert_task, &settings);
-
- if (defnrToPC) {
- MEM_freeN(defnrToPC);
- }
-}
-
-/* ************ END Armature Deform ******************* */
+/* -------------------------------------------------------------------- */
+/** \name Bone Space to Space Conversion API
+ * \{ */
void get_objectspace_bone_matrix(struct Bone *bone,
float M_accumulatedMatrix[4][4],
@@ -1832,8 +1386,6 @@ void get_objectspace_bone_matrix(struct Bone *bone,
copy_m4_m4(M_accumulatedMatrix, bone->arm_mat);
}
-/* **************** Space to Space API ****************** */
-
/* Convert World-Space Matrix to Pose-Space Matrix */
void BKE_armature_mat_world_to_pose(Object *ob, float inmat[4][4], float outmat[4][4])
{
@@ -1868,6 +1420,12 @@ void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outl
copy_v3_v3(outloc, nLocMat[3]);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Matrix Calculation API
+ * \{ */
+
/* Simple helper, computes the offset bone matrix.
* offs_bone = yoffs(b-1) + root(b) + bonemat(b). */
void BKE_bone_offset_matrix_get(const Bone *bone, float offs_bone[4][4])
@@ -2156,6 +1714,14 @@ void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], fl
copy_v3_v3(outloc, nLocMat[3]);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Bone Matrix Read/Write API
+ *
+ * High level functions for transforming bones and reading the transform values.
+ * \{ */
+
void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph,
Object *ob,
bPoseChannel *pchan,
@@ -2255,8 +1821,13 @@ void BKE_armature_mat_pose_to_delta(float delta_mat[4][4],
mul_m4_m4m4(delta_mat, imat, pose_mat);
}
-/* **************** Rotation Mode Conversions ****************************** */
-/* Used for Objects and Pose Channels, since both can have multiple rotation representations */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Rotation Mode Conversions
+ *
+ * Used for Objects and Pose Channels, since both can have multiple rotation representations.
+ * \{ */
/* Called from RNA when rotation mode changes
* - the result should be that the rotations given in the provided pointers have had conversions
@@ -2308,9 +1879,15 @@ void BKE_rotMode_change_values(
}
}
-/* **************** The new & simple (but OK!) armature evaluation ********* */
+/** \} */
-/* ****************** And how it works! ****************************************
+/* -------------------------------------------------------------------- */
+/** \name Bone Vector, Roll Conversion
+ *
+ * Used for Objects and Pose Channels, since both can have multiple rotation representations.
+ *
+ * How it Works
+ * ============
*
* This is the bone transformation trick; they're hierarchical so each bone(b)
* is in the coord system of bone(b-1):
@@ -2326,7 +1903,7 @@ void BKE_rotMode_change_values(
*
* pose_mat(b)= arm_mat(b) * chan_mat(b)
*
- * *************************************************************************** */
+ * \{ */
/* Computes vector and roll based on a rotation.
* "mat" must contain only a rotation, and no scaling. */
@@ -2494,6 +2071,12 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3])
vec_roll_to_mat3_normalized(nor, roll, mat);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Bone Matrix Calculation (Recursive)
+ * \{ */
+
/**
* Recursive part, calculates rest-position of entire tree of children.
* \note Used when exiting edit-mode too.
@@ -2548,6 +2131,12 @@ void BKE_armature_where_is(bArmature *arm)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pose Rebuild
+ * \{ */
+
/* if bone layer is protected, copy the data from from->pose
* when used with linked libraries this copies from the linked pose into the local pose */
static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
@@ -2828,7 +2417,11 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
}
}
-/* ********************** THE POSE SOLVER ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Pose Solver
+ * \{ */
/* loc/rot/size to given mat4 */
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float chan_mat[4][4])
@@ -3024,7 +2617,12 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
}
}
-/************** Bounding box ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Calculate Bounding Box (Armature & Pose)
+ * \{ */
+
static int minmax_armature(Object *ob, float r_min[3], float r_max[3])
{
bPoseChannel *pchan;
@@ -3106,7 +2704,11 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden
return changed;
}
-/************** Graph evaluation ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Graph Evaluation
+ * \{ */
bPoseChannel *BKE_armature_ik_solver_find_root(bPoseChannel *pchan, bKinematicConstraint *data)
{
@@ -3145,3 +2747,5 @@ bPoseChannel *BKE_armature_splineik_solver_find_root(bPoseChannel *pchan,
}
return rootchan;
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c
new file mode 100644
index 00000000000..e757e30e524
--- /dev/null
+++ b/source/blender/blenkernel/intern/armature_deform.c
@@ -0,0 +1,688 @@
+/*
+ * 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Deform coordinates by a armature object (used by modifier).
+ */
+
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_deform.h"
+#include "BKE_editmesh.h"
+#include "BKE_lattice.h"
+
+#include "DEG_depsgraph_build.h"
+
+#include "CLG_log.h"
+
+static CLG_LogRef LOG = {"bke.armature_deform"};
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Deform Internal Utilities
+ * \{ */
+
+/* Add the effect of one bone or B-Bone segment to the accumulated result. */
+static void pchan_deform_accumulate(const DualQuat *deform_dq,
+ const float deform_mat[4][4],
+ const float co_in[3],
+ float weight,
+ float co_accum[3],
+ DualQuat *dq_accum,
+ float mat_accum[3][3])
+{
+ if (weight == 0.0f) {
+ return;
+ }
+
+ if (dq_accum) {
+ BLI_assert(!co_accum);
+
+ add_weighted_dq_dq(dq_accum, deform_dq, weight);
+ }
+ else {
+ float tmp[3];
+ mul_v3_m4v3(tmp, deform_mat, co_in);
+
+ sub_v3_v3(tmp, co_in);
+ madd_v3_v3fl(co_accum, tmp, weight);
+
+ if (mat_accum) {
+ float tmpmat[3][3];
+ copy_m3_m4(tmpmat, deform_mat);
+
+ madd_m3_m3m3fl(mat_accum, mat_accum, tmpmat, weight);
+ }
+ }
+}
+
+static void b_bone_deform(const bPoseChannel *pchan,
+ const float co[3],
+ float weight,
+ float vec[3],
+ DualQuat *dq,
+ float defmat[3][3])
+{
+ const DualQuat *quats = pchan->runtime.bbone_dual_quats;
+ const Mat4 *mats = pchan->runtime.bbone_deform_mats;
+ const float(*mat)[4] = mats[0].mat;
+ float blend, y;
+ int index;
+
+ /* Transform co to bone space and get its y component. */
+ y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
+
+ /* Calculate the indices of the 2 affecting b_bone segments. */
+ BKE_pchan_bbone_deform_segment_index(pchan, y / pchan->bone->length, &index, &blend);
+
+ pchan_deform_accumulate(
+ &quats[index], mats[index + 1].mat, co, weight * (1.0f - blend), vec, dq, defmat);
+ pchan_deform_accumulate(
+ &quats[index + 1], mats[index + 2].mat, co, weight * blend, vec, dq, defmat);
+}
+
+/* using vec with dist to bone b1 - b2 */
+float distfactor_to_bone(
+ const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
+{
+ float dist_sq;
+ float bdelta[3];
+ float pdelta[3];
+ float hsqr, a, l, rad;
+
+ sub_v3_v3v3(bdelta, b2, b1);
+ l = normalize_v3(bdelta);
+
+ sub_v3_v3v3(pdelta, vec, b1);
+
+ a = dot_v3v3(bdelta, pdelta);
+ hsqr = len_squared_v3(pdelta);
+
+ if (a < 0.0f) {
+ /* If we're past the end of the bone, do a spherical field attenuation thing */
+ dist_sq = len_squared_v3v3(b1, vec);
+ rad = rad1;
+ }
+ else if (a > l) {
+ /* If we're past the end of the bone, do a spherical field attenuation thing */
+ dist_sq = len_squared_v3v3(b2, vec);
+ rad = rad2;
+ }
+ else {
+ dist_sq = (hsqr - (a * a));
+
+ if (l != 0.0f) {
+ rad = a / l;
+ rad = rad * rad2 + (1.0f - rad) * rad1;
+ }
+ else {
+ rad = rad1;
+ }
+ }
+
+ a = rad * rad;
+ if (dist_sq < a) {
+ return 1.0f;
+ }
+ else {
+ l = rad + rdist;
+ l *= l;
+ if (rdist == 0.0f || dist_sq >= l) {
+ return 0.0f;
+ }
+ else {
+ a = sqrtf(dist_sq) - rad;
+ return 1.0f - (a * a) / (rdist * rdist);
+ }
+ }
+}
+
+static float dist_bone_deform(
+ bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3])
+{
+ Bone *bone = pchan->bone;
+ float fac, contrib = 0.0;
+
+ if (bone == NULL) {
+ return 0.0f;
+ }
+
+ fac = distfactor_to_bone(
+ co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
+
+ if (fac > 0.0f) {
+ fac *= bone->weight;
+ contrib = fac;
+ if (contrib > 0.0f) {
+ if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
+ b_bone_deform(pchan, co, fac, vec, dq, mat);
+ }
+ else {
+ pchan_deform_accumulate(
+ &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, fac, vec, dq, mat);
+ }
+ }
+ }
+
+ return contrib;
+}
+
+static void pchan_bone_deform(bPoseChannel *pchan,
+ float weight,
+ float vec[3],
+ DualQuat *dq,
+ float mat[3][3],
+ const float co[3],
+ float *contrib)
+{
+ Bone *bone = pchan->bone;
+
+ if (!weight) {
+ return;
+ }
+
+ if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
+ b_bone_deform(pchan, co, weight, vec, dq, mat);
+ }
+ else {
+ pchan_deform_accumulate(
+ &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, weight, vec, dq, mat);
+ }
+
+ (*contrib) += weight;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Deform #BKE_armature_deform_coords API
+ *
+ * #BKE_armature_deform_coords and related functions.
+ * \{ */
+
+typedef struct ArmatureUserdata {
+ const Object *ob_arm;
+ const Object *ob_target;
+ const Mesh *me_target;
+ float (*vert_coords)[3];
+ float (*vert_deform_mats)[3][3];
+ float (*vert_coords_prev)[3];
+
+ bool use_envelope;
+ bool use_quaternion;
+ bool invert_vgroup;
+ bool use_dverts;
+
+ int armature_def_nr;
+
+ const MDeformVert *dverts;
+ int dverts_len;
+
+ bPoseChannel **pchan_from_defbase;
+ int defbase_len;
+
+ float premat[4][4];
+ float postmat[4][4];
+
+ /** Specific data types. */
+ struct {
+ int cd_dvert_offset;
+ } bmesh;
+} ArmatureUserdata;
+
+static void armature_vert_task_with_dvert(const ArmatureUserdata *data,
+ const int i,
+ const MDeformVert *dvert)
+{
+ float(*const vert_coords)[3] = data->vert_coords;
+ float(*const vert_deform_mats)[3][3] = data->vert_deform_mats;
+ float(*const vert_coords_prev)[3] = data->vert_coords_prev;
+ const bool use_envelope = data->use_envelope;
+ const bool use_quaternion = data->use_quaternion;
+ const bool use_dverts = data->use_dverts;
+ const int armature_def_nr = data->armature_def_nr;
+
+ DualQuat sumdq, *dq = NULL;
+ bPoseChannel *pchan;
+ float *co, dco[3];
+ float sumvec[3], summat[3][3];
+ float *vec = NULL, (*smat)[3] = NULL;
+ float contrib = 0.0f;
+ float armature_weight = 1.0f; /* default to 1 if no overall def group */
+ float prevco_weight = 1.0f; /* weight for optional cached vertexcos */
+
+ if (use_quaternion) {
+ memset(&sumdq, 0, sizeof(DualQuat));
+ dq = &sumdq;
+ }
+ else {
+ zero_v3(sumvec);
+ vec = sumvec;
+
+ if (vert_deform_mats) {
+ zero_m3(summat);
+ smat = summat;
+ }
+ }
+
+ if (armature_def_nr != -1 && dvert) {
+ armature_weight = BKE_defvert_find_weight(dvert, armature_def_nr);
+
+ if (data->invert_vgroup) {
+ armature_weight = 1.0f - armature_weight;
+ }
+
+ /* hackish: the blending factor can be used for blending with vert_coords_prev too */
+ if (vert_coords_prev) {
+ prevco_weight = armature_weight;
+ armature_weight = 1.0f;
+ }
+ }
+
+ /* check if there's any point in calculating for this vert */
+ if (armature_weight == 0.0f) {
+ return;
+ }
+
+ /* get the coord we work on */
+ co = vert_coords_prev ? vert_coords_prev[i] : vert_coords[i];
+
+ /* Apply the object's matrix */
+ mul_m4_v3(data->premat, co);
+
+ if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
+ const MDeformWeight *dw = dvert->dw;
+ int deformed = 0;
+ unsigned int j;
+ for (j = dvert->totweight; j != 0; j--, dw++) {
+ const uint index = dw->def_nr;
+ if (index < data->defbase_len && (pchan = data->pchan_from_defbase[index])) {
+ float weight = dw->weight;
+ Bone *bone = pchan->bone;
+
+ deformed = 1;
+
+ if (bone && bone->flag & BONE_MULT_VG_ENV) {
+ weight *= distfactor_to_bone(
+ co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
+ }
+
+ pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
+ }
+ }
+ /* if there are vertexgroups but not groups with bones
+ * (like for softbody groups) */
+ if (deformed == 0 && use_envelope) {
+ for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+ contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+ }
+ }
+ }
+ }
+ else if (use_envelope) {
+ for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+ contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+ }
+ }
+ }
+
+ /* actually should be EPSILON? weight values and contrib can be like 10e-39 small */
+ if (contrib > 0.0001f) {
+ if (use_quaternion) {
+ normalize_dq(dq, contrib);
+
+ if (armature_weight != 1.0f) {
+ copy_v3_v3(dco, co);
+ mul_v3m3_dq(dco, (vert_deform_mats) ? summat : NULL, dq);
+ sub_v3_v3(dco, co);
+ mul_v3_fl(dco, armature_weight);
+ add_v3_v3(co, dco);
+ }
+ else {
+ mul_v3m3_dq(co, (vert_deform_mats) ? summat : NULL, dq);
+ }
+
+ smat = summat;
+ }
+ else {
+ mul_v3_fl(vec, armature_weight / contrib);
+ add_v3_v3v3(co, vec, co);
+ }
+
+ if (vert_deform_mats) {
+ float pre[3][3], post[3][3], tmpmat[3][3];
+
+ copy_m3_m4(pre, data->premat);
+ copy_m3_m4(post, data->postmat);
+ copy_m3_m3(tmpmat, vert_deform_mats[i]);
+
+ if (!use_quaternion) { /* quaternion already is scale corrected */
+ mul_m3_fl(smat, armature_weight / contrib);
+ }
+
+ mul_m3_series(vert_deform_mats[i], post, smat, pre, tmpmat);
+ }
+ }
+
+ /* always, check above code */
+ mul_m4_v3(data->postmat, co);
+
+ /* interpolate with previous modifier position using weight group */
+ if (vert_coords_prev) {
+ float mw = 1.0f - prevco_weight;
+ vert_coords[i][0] = prevco_weight * vert_coords[i][0] + mw * co[0];
+ vert_coords[i][1] = prevco_weight * vert_coords[i][1] + mw * co[1];
+ vert_coords[i][2] = prevco_weight * vert_coords[i][2] + mw * co[2];
+ }
+}
+
+static void armature_vert_task(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ const ArmatureUserdata *data = userdata;
+ const MDeformVert *dvert;
+ if (data->use_dverts || data->armature_def_nr != -1) {
+ if (data->me_target) {
+ BLI_assert(i < data->me_target->totvert);
+ if (data->me_target->dvert != NULL) {
+ dvert = data->me_target->dvert + i;
+ }
+ else {
+ dvert = NULL;
+ }
+ }
+ else if (data->dverts && i < data->dverts_len) {
+ dvert = data->dverts + i;
+ }
+ else {
+ dvert = NULL;
+ }
+ }
+ else {
+ dvert = NULL;
+ }
+
+ armature_vert_task_with_dvert(data, i, dvert);
+}
+
+static void armature_vert_task_editmesh(void *__restrict userdata, MempoolIterData *iter)
+{
+ const ArmatureUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v, data->bmesh.cd_dvert_offset);
+ armature_vert_task_with_dvert(data, BM_elem_index_get(v), dvert);
+}
+
+static void armature_vert_task_editmesh_no_dvert(void *__restrict userdata, MempoolIterData *iter)
+{
+ const ArmatureUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ armature_vert_task_with_dvert(data, BM_elem_index_get(v), NULL);
+}
+
+static void armature_deform_coords_impl(const Object *ob_arm,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ const int vert_coords_len,
+ const int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ const Mesh *me_target,
+ BMEditMesh *em_target,
+ bGPDstroke *gps_target)
+{
+ bArmature *arm = ob_arm->data;
+ bPoseChannel **pchan_from_defbase = NULL;
+ const MDeformVert *dverts = NULL;
+ bDeformGroup *dg;
+ const bool use_envelope = (deformflag & ARM_DEF_ENVELOPE) != 0;
+ const bool use_quaternion = (deformflag & ARM_DEF_QUATERNION) != 0;
+ const bool invert_vgroup = (deformflag & ARM_DEF_INVERT_VGROUP) != 0;
+ int defbase_len = 0; /* safety for vertexgroup index overflow */
+ int i, dverts_len = 0; /* safety for vertexgroup overflow */
+ bool use_dverts = false;
+ int armature_def_nr;
+ int cd_dvert_offset = -1;
+
+ /* in editmode, or not an armature */
+ if (arm->edbo || (ob_arm->pose == NULL)) {
+ return;
+ }
+
+ if ((ob_arm->pose->flag & POSE_RECALC) != 0) {
+ CLOG_ERROR(&LOG,
+ "Trying to evaluate influence of armature '%s' which needs Pose recalc!",
+ ob_arm->id.name);
+ BLI_assert(0);
+ }
+
+ /* get the def_nr for the overall armature vertex group if present */
+ armature_def_nr = BKE_object_defgroup_name_index(ob_target, defgrp_name);
+
+ if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
+ defbase_len = BLI_listbase_count(&ob_target->defbase);
+
+ if (ob_target->type == OB_MESH) {
+ if (em_target == NULL) {
+ Mesh *me = ob_target->data;
+ dverts = me->dvert;
+ if (dverts) {
+ dverts_len = me->totvert;
+ }
+ }
+ }
+ else if (ob_target->type == OB_LATTICE) {
+ Lattice *lt = ob_target->data;
+ dverts = lt->dvert;
+ if (dverts) {
+ dverts_len = lt->pntsu * lt->pntsv * lt->pntsw;
+ }
+ }
+ else if (ob_target->type == OB_GPENCIL) {
+ dverts = gps_target->dvert;
+ if (dverts) {
+ dverts_len = gps_target->totpoints;
+ }
+ }
+ }
+
+ /* get a vertex-deform-index to posechannel array */
+ if (deformflag & ARM_DEF_VGROUP) {
+ if (ELEM(ob_target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) {
+ /* if we have a Mesh, only use dverts if it has them */
+ if (em_target) {
+ cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
+ use_dverts = (cd_dvert_offset != -1);
+ }
+ else if (me_target) {
+ use_dverts = (me_target->dvert != NULL);
+ }
+ else if (dverts) {
+ use_dverts = true;
+ }
+
+ if (use_dverts) {
+ pchan_from_defbase = MEM_callocN(sizeof(*pchan_from_defbase) * defbase_len, "defnrToBone");
+ /* TODO(sergey): Some considerations here:
+ *
+ * - Check whether keeping this consistent across frames gives speedup.
+ */
+ for (i = 0, dg = ob_target->defbase.first; dg; i++, dg = dg->next) {
+ pchan_from_defbase[i] = BKE_pose_channel_find_name(ob_arm->pose, dg->name);
+ /* exclude non-deforming bones */
+ if (pchan_from_defbase[i]) {
+ if (pchan_from_defbase[i]->bone->flag & BONE_NO_DEFORM) {
+ pchan_from_defbase[i] = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ArmatureUserdata data = {
+ .ob_arm = ob_arm,
+ .ob_target = ob_target,
+ .me_target = me_target,
+ .vert_coords = vert_coords,
+ .vert_deform_mats = vert_deform_mats,
+ .vert_coords_prev = vert_coords_prev,
+ .use_envelope = use_envelope,
+ .use_quaternion = use_quaternion,
+ .invert_vgroup = invert_vgroup,
+ .use_dverts = use_dverts,
+ .armature_def_nr = armature_def_nr,
+ .dverts = dverts,
+ .dverts_len = dverts_len,
+ .pchan_from_defbase = pchan_from_defbase,
+ .defbase_len = defbase_len,
+ .bmesh =
+ {
+ .cd_dvert_offset = cd_dvert_offset,
+ },
+ };
+
+ float obinv[4][4];
+ invert_m4_m4(obinv, ob_target->obmat);
+
+ mul_m4_m4m4(data.postmat, obinv, ob_arm->obmat);
+ invert_m4_m4(data.premat, data.postmat);
+
+ if (em_target != NULL) {
+ /* While this could cause an extra loop over mesh data, in most cases this will
+ * have already been properly set. */
+ BM_mesh_elem_index_ensure(em_target->bm, BM_VERT);
+
+ if (use_dverts) {
+ BLI_task_parallel_mempool(em_target->bm->vpool, &data, armature_vert_task_editmesh, true);
+ }
+ else {
+ BLI_task_parallel_mempool(
+ em_target->bm->vpool, &data, armature_vert_task_editmesh_no_dvert, true);
+ }
+ }
+ else {
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 32;
+ BLI_task_parallel_range(0, vert_coords_len, &data, armature_vert_task, &settings);
+ }
+
+ if (pchan_from_defbase) {
+ MEM_freeN(pchan_from_defbase);
+ }
+}
+
+void BKE_armature_deform_coords_with_gpencil_stroke(const Object *ob_arm,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ bGPDstroke *gps_target)
+{
+ armature_deform_coords_impl(ob_arm,
+ ob_target,
+ vert_coords,
+ vert_deform_mats,
+ vert_coords_len,
+ deformflag,
+ vert_coords_prev,
+ defgrp_name,
+ NULL,
+ NULL,
+ gps_target);
+}
+
+void BKE_armature_deform_coords_with_mesh(const Object *ob_arm,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ const Mesh *me_target)
+{
+ armature_deform_coords_impl(ob_arm,
+ ob_target,
+ vert_coords,
+ vert_deform_mats,
+ vert_coords_len,
+ deformflag,
+ vert_coords_prev,
+ defgrp_name,
+ me_target,
+ NULL,
+ NULL);
+}
+
+void BKE_armature_deform_coords_with_editmesh(const Object *ob_arm,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ float (*vert_deform_mats)[3][3],
+ int vert_coords_len,
+ int deformflag,
+ float (*vert_coords_prev)[3],
+ const char *defgrp_name,
+ BMEditMesh *em_target)
+{
+ armature_deform_coords_impl(ob_arm,
+ ob_target,
+ vert_coords,
+ vert_deform_mats,
+ vert_coords_len,
+ deformflag,
+ vert_coords_prev,
+ defgrp_name,
+ NULL,
+ em_target,
+ NULL);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 0b9780ac81c..ce6143116a1 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -146,6 +146,7 @@ void cloth_init(ClothModifierData *clmd)
clmd->sim_parms->uniform_pressure_force = 0.0f;
clmd->sim_parms->target_volume = 0.0f;
clmd->sim_parms->pressure_factor = 1.0f;
+ clmd->sim_parms->fluid_density = 0.0f;
clmd->sim_parms->vgroup_pressure = 0;
// also from softbodies
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 290b181f172..a9d3c7c1b65 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -716,6 +716,31 @@ static void collection_tag_update_parent_recursive(Main *bmain,
}
}
+static Collection *collection_parent_editable_find_recursive(Collection *collection)
+{
+ if (!ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) {
+ return collection;
+ }
+
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ return NULL;
+ }
+
+ LISTBASE_FOREACH (CollectionParent *, collection_parent, &collection->parents) {
+ if (!ID_IS_LINKED(collection_parent->collection) &&
+ !ID_IS_OVERRIDE_LIBRARY(collection_parent->collection)) {
+ return collection_parent->collection;
+ }
+ Collection *editable_collection = collection_parent_editable_find_recursive(
+ collection_parent->collection);
+ if (editable_collection != NULL) {
+ return editable_collection;
+ }
+ }
+
+ return NULL;
+}
+
static bool collection_object_add(
Main *bmain, Collection *collection, Object *ob, int flag, const bool add_us)
{
@@ -786,6 +811,15 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
return false;
}
+ collection = collection_parent_editable_find_recursive(collection);
+
+ /* Only case where this pointer can be NULL is when scene itself is linked, this case should
+ * never be reached. */
+ BLI_assert(collection != NULL);
+ if (collection == NULL) {
+ return false;
+ }
+
if (!collection_object_add(bmain, collection, ob, 0, true)) {
return false;
}
@@ -808,7 +842,8 @@ void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, O
bool is_instantiated = false;
FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
- if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) {
+ if (!ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection) &&
+ BKE_collection_has_object(collection, ob_src)) {
collection_object_add(bmain, collection, ob_dst, 0, true);
is_instantiated = true;
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index e67cf8573f3..0b65f53708f 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -29,7 +29,6 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
-#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -43,7 +42,6 @@
/* for dereferencing pointers */
#include "DNA_key_types.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
#include "BKE_curve.h"
@@ -54,7 +52,6 @@
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
-#include "BKE_material.h"
#include "BKE_object.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c
new file mode 100644
index 00000000000..d4f197521a1
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve_deform.c
@@ -0,0 +1,504 @@
+/*
+ * 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Deform coordinates by a curve object (used by modifier).
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_anim_path.h"
+#include "BKE_curve.h"
+#include "BKE_editmesh.h"
+#include "BKE_lattice.h"
+#include "BKE_modifier.h"
+
+#include "BKE_deform.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Curve Deform Internal Utilities
+ * \{ */
+
+/**
+ * Calculations is in local space of deformed object
+ * so we store matrices to transform points to/from local-space.
+ */
+typedef struct {
+ float dmin[3], dmax[3];
+ float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
+ int no_rot_axis;
+} CurveDeform;
+
+static void init_curve_deform(const Object *ob_curve, const Object *ob_target, CurveDeform *cd)
+{
+ float imat[4][4];
+ invert_m4_m4(imat, ob_target->obmat);
+ mul_m4_m4m4(cd->objectspace, imat, ob_curve->obmat);
+ invert_m4_m4(cd->curvespace, cd->objectspace);
+ copy_m3_m4(cd->objectspace3, cd->objectspace);
+ cd->no_rot_axis = 0;
+}
+
+/**
+ * This makes sure we can extend for non-cyclic.
+ *
+ * \return Success.
+ */
+static bool where_on_path_deform(const Object *ob_curve,
+ float ctime,
+ float r_vec[4],
+ float r_dir[3],
+ float r_quat[4],
+ float *r_radius)
+{
+ BevList *bl;
+ float ctime1;
+ int cycl = 0;
+
+ /* test for cyclic */
+ bl = ob_curve->runtime.curve_cache->bev.first;
+ if (!bl->nr) {
+ return false;
+ }
+ if (bl->poly > -1) {
+ cycl = 1;
+ }
+
+ if (cycl == 0) {
+ ctime1 = CLAMPIS(ctime, 0.0f, 1.0f);
+ }
+ else {
+ ctime1 = ctime;
+ }
+
+ /* vec needs 4 items */
+ if (where_on_path(ob_curve, ctime1, r_vec, r_dir, r_quat, r_radius, NULL)) {
+
+ if (cycl == 0) {
+ Path *path = ob_curve->runtime.curve_cache->path;
+ float dvec[3];
+
+ if (ctime < 0.0f) {
+ sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec);
+ mul_v3_fl(dvec, ctime * (float)path->len);
+ add_v3_v3(r_vec, dvec);
+ if (r_quat) {
+ copy_qt_qt(r_quat, path->data[0].quat);
+ }
+ if (r_radius) {
+ *r_radius = path->data[0].radius;
+ }
+ }
+ else if (ctime > 1.0f) {
+ sub_v3_v3v3(dvec, path->data[path->len - 1].vec, path->data[path->len - 2].vec);
+ mul_v3_fl(dvec, (ctime - 1.0f) * (float)path->len);
+ add_v3_v3(r_vec, dvec);
+ if (r_quat) {
+ copy_qt_qt(r_quat, path->data[path->len - 1].quat);
+ }
+ if (r_radius) {
+ *r_radius = path->data[path->len - 1].radius;
+ }
+ /* weight - not used but could be added */
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * For each point, rotate & translate to curve use path, since it has constant distances.
+ *
+ * \param co: local coord, result local too.
+ * \param r_quat: returns quaternion for rotation,
+ * using #CurveDeform.no_rot_axis axis is using another define.
+ */
+static bool calc_curve_deform(
+ const Object *ob_curve, float co[3], const short axis, const CurveDeform *cd, float r_quat[4])
+{
+ Curve *cu = ob_curve->data;
+ float fac, loc[4], dir[3], new_quat[4], radius;
+ short index;
+ const bool is_neg_axis = (axis > 2);
+
+ if (ob_curve->runtime.curve_cache == NULL) {
+ /* Happens with a cyclic dependencies. */
+ return false;
+ }
+
+ if (ob_curve->runtime.curve_cache->path == NULL) {
+ return false; /* happens on append, cyclic dependencies and empty curves */
+ }
+
+ /* options */
+ if (is_neg_axis) {
+ index = axis - 3;
+ if (cu->flag & CU_STRETCH) {
+ fac = -(co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
+ }
+ else {
+ fac = -(co[index] - cd->dmax[index]) / (ob_curve->runtime.curve_cache->path->totdist);
+ }
+ }
+ else {
+ index = axis;
+ if (cu->flag & CU_STRETCH) {
+ fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
+ }
+ else {
+ if (LIKELY(ob_curve->runtime.curve_cache->path->totdist > FLT_EPSILON)) {
+ fac = +(co[index] - cd->dmin[index]) / (ob_curve->runtime.curve_cache->path->totdist);
+ }
+ else {
+ fac = 0.0f;
+ }
+ }
+ }
+
+ if (where_on_path_deform(ob_curve, fac, loc, dir, new_quat, &radius)) { /* returns OK */
+ float quat[4], cent[3];
+
+ if (cd->no_rot_axis) { /* set by caller */
+
+ /* This is not exactly the same as 2.4x, since the axis is having rotation removed rather
+ * than changing the axis before calculating the tilt but serves much the same purpose. */
+ float dir_flat[3] = {0, 0, 0}, q[4];
+ copy_v3_v3(dir_flat, dir);
+ dir_flat[cd->no_rot_axis - 1] = 0.0f;
+
+ normalize_v3(dir);
+ normalize_v3(dir_flat);
+
+ rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */
+
+ mul_qt_qtqt(new_quat, q, new_quat);
+ }
+
+ /* Logic for 'cent' orientation *
+ *
+ * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
+ *
+ * Use a curve modifier to stretch a cube out, color each side RGB,
+ * positive side light, negative dark.
+ * view with X up (default), from the angle that you can see 3 faces RGB colors (light),
+ * anti-clockwise
+ * Notice X,Y,Z Up all have light colors and each ordered CCW.
+ *
+ * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
+ *
+ * note: moved functions into quat_apply_track/vec_apply_track
+ * */
+ copy_qt_qt(quat, new_quat);
+ copy_v3_v3(cent, co);
+
+ /* zero the axis which is not used,
+ * the big block of text above now applies to these 3 lines */
+ quat_apply_track(
+ quat,
+ axis,
+ (axis == 0 || axis == 2) ? 1 : 0); /* up flag is a dummy, set so no rotation is done */
+ vec_apply_track(cent, axis);
+ cent[index] = 0.0f;
+
+ /* scale if enabled */
+ if (cu->flag & CU_PATH_RADIUS) {
+ mul_v3_fl(cent, radius);
+ }
+
+ /* local rotation */
+ normalize_qt(quat);
+ mul_qt_v3(quat, cent);
+
+ /* translation */
+ add_v3_v3v3(co, cent, loc);
+
+ if (r_quat) {
+ copy_qt_qt(r_quat, quat);
+ }
+
+ return true;
+ }
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Curve Deform #BKE_curve_deform_coords API
+ *
+ * #BKE_curve_deform and related functions.
+ * \{ */
+
+static void curve_deform_coords_impl(const Object *ob_curve,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const MDeformVert *dvert,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis,
+ BMEditMesh *em_target)
+{
+ Curve *cu;
+ int a;
+ CurveDeform cd;
+ const bool is_neg_axis = (defaxis > 2);
+ const bool invert_vgroup = (flag & MOD_CURVE_INVERT_VGROUP) != 0;
+ bool use_dverts = false;
+ int cd_dvert_offset;
+
+ if (ob_curve->type != OB_CURVE) {
+ return;
+ }
+
+ cu = ob_curve->data;
+
+ init_curve_deform(ob_curve, ob_target, &cd);
+
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+ /* Dummy bounds. */
+ if (is_neg_axis == false) {
+ cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = 0.0f;
+ cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 1.0f;
+ }
+ else {
+ /* Negative, these bounds give a good rest position. */
+ cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = -1.0f;
+ cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f;
+ }
+ }
+ else {
+ /* Set mesh min/max bounds. */
+ INIT_MINMAX(cd.dmin, cd.dmax);
+ }
+
+ if (em_target != NULL) {
+ cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
+ if (cd_dvert_offset != -1) {
+ use_dverts = true;
+ }
+ }
+ else {
+ if (dvert != NULL) {
+ use_dverts = true;
+ }
+ }
+
+ if (use_dverts) {
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+
+#define DEFORM_OP(dvert) \
+ { \
+ const float weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dvert, defgrp_index) : \
+ BKE_defvert_find_weight(dvert, defgrp_index); \
+ if (weight > 0.0f) { \
+ float vec[3]; \
+ mul_m4_v3(cd.curvespace, vert_coords[a]); \
+ copy_v3_v3(vec, vert_coords[a]); \
+ calc_curve_deform(ob_curve, vec, defaxis, &cd, NULL); \
+ interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight); \
+ mul_m4_v3(cd.objectspace, vert_coords[a]); \
+ } \
+ } \
+ ((void)0)
+
+ if (em_target != NULL) {
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_MESH_INDEX (v, &iter, em_target->bm, BM_VERTS_OF_MESH, a) {
+ dvert = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset);
+ DEFORM_OP(dvert);
+ }
+ }
+ else {
+ for (a = 0; a < vert_coords_len; a++) {
+ DEFORM_OP(&dvert[a]);
+ }
+ }
+
+#undef DEFORM_OP
+ }
+ else {
+
+#define DEFORM_OP_MINMAX(dvert) \
+ { \
+ const float weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dvert, defgrp_index) : \
+ BKE_defvert_find_weight(dvert, defgrp_index); \
+ if (weight > 0.0f) { \
+ mul_m4_v3(cd.curvespace, vert_coords[a]); \
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]); \
+ } \
+ } \
+ ((void)0)
+
+ /* already in 'cd.curvespace', prev for loop */
+#define DEFORM_OP_CLAMPED(dvert) \
+ { \
+ const float weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dvert, defgrp_index) : \
+ BKE_defvert_find_weight(dvert, defgrp_index); \
+ if (weight > 0.0f) { \
+ float vec[3]; \
+ copy_v3_v3(vec, vert_coords[a]); \
+ calc_curve_deform(ob_curve, vec, defaxis, &cd, NULL); \
+ interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight); \
+ mul_m4_v3(cd.objectspace, vert_coords[a]); \
+ } \
+ } \
+ ((void)0)
+
+ if (em_target != NULL) {
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_MESH_INDEX (v, &iter, em_target->bm, BM_VERTS_OF_MESH, a) {
+ dvert = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset);
+ DEFORM_OP_MINMAX(dvert);
+ }
+
+ BM_ITER_MESH_INDEX (v, &iter, em_target->bm, BM_VERTS_OF_MESH, a) {
+ dvert = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset);
+ DEFORM_OP_CLAMPED(dvert);
+ }
+ }
+ else {
+
+ for (a = 0; a < vert_coords_len; a++) {
+ DEFORM_OP_MINMAX(&dvert[a]);
+ }
+
+ for (a = 0; a < vert_coords_len; a++) {
+ DEFORM_OP_CLAMPED(&dvert[a]);
+ }
+ }
+ }
+
+#undef DEFORM_OP_MINMAX
+#undef DEFORM_OP_CLAMPED
+ }
+ else {
+ if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
+ for (a = 0; a < vert_coords_len; a++) {
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ calc_curve_deform(ob_curve, vert_coords[a], defaxis, &cd, NULL);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
+ }
+ }
+ else {
+ for (a = 0; a < vert_coords_len; a++) {
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
+ }
+
+ for (a = 0; a < vert_coords_len; a++) {
+ /* already in 'cd.curvespace', prev for loop */
+ calc_curve_deform(ob_curve, vert_coords[a], defaxis, &cd, NULL);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
+ }
+ }
+ }
+}
+
+void BKE_curve_deform_coords(const Object *ob_curve,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const MDeformVert *dvert,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis)
+{
+ curve_deform_coords_impl(
+ ob_curve, ob_target, vert_coords, vert_coords_len, dvert, defgrp_index, flag, defaxis, NULL);
+}
+
+void BKE_curve_deform_coords_with_editmesh(const Object *ob_curve,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const int defgrp_index,
+ const short flag,
+ const short defaxis,
+ BMEditMesh *em_target)
+{
+ curve_deform_coords_impl(ob_curve,
+ ob_target,
+ vert_coords,
+ vert_coords_len,
+ NULL,
+ defgrp_index,
+ flag,
+ defaxis,
+ em_target);
+}
+
+/**
+ * \param orco: Input vec and orco = local coord in curve space
+ * orco is original not-animated or deformed reference point.
+ *
+ * The result written in vec and r_mat.
+ */
+void BKE_curve_deform_co(const Object *ob_curve,
+ const Object *ob_target,
+ const float orco[3],
+ float vec[3],
+ const int no_rot_axis,
+ float r_mat[3][3])
+{
+ CurveDeform cd;
+ float quat[4];
+
+ if (ob_curve->type != OB_CURVE) {
+ unit_m3(r_mat);
+ return;
+ }
+
+ init_curve_deform(ob_curve, ob_target, &cd);
+ cd.no_rot_axis = no_rot_axis; /* option to only rotate for XY, for example */
+
+ copy_v3_v3(cd.dmin, orco);
+ copy_v3_v3(cd.dmax, orco);
+
+ mul_m4_v3(cd.curvespace, vec);
+
+ if (calc_curve_deform(ob_curve, vec, ob_target->trackflag, &cd, quat)) {
+ float qmat[3][3];
+
+ quat_to_mat3(qmat, quat);
+ mul_m3_m3m3(r_mat, qmat, cd.objectspace3);
+ }
+ else {
+ unit_m3(r_mat);
+ }
+
+ mul_m4_v3(cd.objectspace, vec);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 9a3965a86f6..b97935d57f2 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -486,14 +486,14 @@ void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int
}
}
-bDeformGroup *BKE_object_defgroup_find_name(Object *ob, const char *name)
+bDeformGroup *BKE_object_defgroup_find_name(const Object *ob, const char *name)
{
return (name && name[0] != '\0') ?
BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name)) :
NULL;
}
-int BKE_object_defgroup_name_index(Object *ob, const char *name)
+int BKE_object_defgroup_name_index(const Object *ob, const char *name)
{
return (name && name[0] != '\0') ?
BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) :
@@ -503,7 +503,7 @@ int BKE_object_defgroup_name_index(Object *ob, const char *name)
/**
* \note caller must free.
*/
-int *BKE_object_defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default)
+int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default)
{
int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase);
@@ -545,7 +545,7 @@ int *BKE_object_defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_
/**
* \note caller must free.
*/
-int *BKE_object_defgroup_flip_map_single(Object *ob,
+int *BKE_object_defgroup_flip_map_single(const Object *ob,
int *flip_map_len,
const bool use_default,
int defgroup)
@@ -580,7 +580,7 @@ int *BKE_object_defgroup_flip_map_single(Object *ob,
}
}
-int BKE_object_defgroup_flip_index(Object *ob, int index, const bool use_default)
+int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_default)
{
bDeformGroup *dg = BLI_findlink(&ob->defbase, index);
int flip_index = -1;
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index b889b91e366..2f8500bd1df 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -286,11 +286,11 @@ void BKE_gpencil_lattice_init(Object *ob)
return;
}
if (mmd->cache_data) {
- end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
+ BKE_lattice_deform_data_destroy(mmd->cache_data);
}
/* init deform data */
- mmd->cache_data = (struct LatticeDeformData *)init_latt_deform(latob, ob);
+ mmd->cache_data = BKE_lattice_deform_data_create(latob, ob);
}
}
}
@@ -303,7 +303,7 @@ void BKE_gpencil_lattice_clear(Object *ob)
if (md->type == eGpencilModifierType_Lattice) {
LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
if ((mmd) && (mmd->cache_data)) {
- end_latt_deform((struct LatticeDeformData *)mmd->cache_data);
+ BKE_lattice_deform_data_destroy(mmd->cache_data);
mmd->cache_data = NULL;
}
}
@@ -859,7 +859,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
}
ob->runtime.gpd_eval = gpencil_copy_for_eval(ob->runtime.gpd_orig);
gpencil_assign_object_eval(ob);
- BKE_gpencil_update_orig_pointers(ob_orig, (Object *)ob);
+ BKE_gpencil_update_orig_pointers(ob_orig, ob);
}
/* Calculate gpencil modifiers */
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index e7a2421a625..8820434cbcf 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -31,7 +31,6 @@
#include "BLI_bitmap.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -40,16 +39,13 @@
#include "DNA_defaults.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BKE_anim_path.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_idtype.h"
-#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
@@ -299,7 +295,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
copy_m4_m4(mat, ltOb->obmat);
unit_m4(ltOb->obmat);
- lattice_deform_verts(ltOb, NULL, NULL, vert_coords, uNew * vNew * wNew, 0, NULL, 1.0f);
+ BKE_lattice_deform_coords(ltOb, NULL, vert_coords, uNew * vNew * wNew, 0, NULL, 1.0f);
copy_m4_m4(ltOb->obmat, mat);
lt->typeu = typeu;
@@ -349,651 +345,13 @@ Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt)
return lt_copy;
}
-typedef struct LatticeDeformData {
- Object *object;
- float *latticedata;
- float latmat[4][4];
-} LatticeDeformData;
-
-LatticeDeformData *init_latt_deform(Object *oblatt, Object *ob)
-{
- /* we make an array with all differences */
- Lattice *lt = oblatt->data;
- BPoint *bp;
- DispList *dl = oblatt->runtime.curve_cache ?
- BKE_displist_find(&oblatt->runtime.curve_cache->disp, DL_VERTS) :
- NULL;
- const float *co = dl ? dl->verts : NULL;
- float *fp, imat[4][4];
- float fu, fv, fw;
- int u, v, w;
- float *latticedata;
- float latmat[4][4];
- LatticeDeformData *lattice_deform_data;
-
- if (lt->editlatt) {
- lt = lt->editlatt->latt;
- }
- bp = lt->def;
-
- fp = latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw,
- "latticedata");
-
- /* for example with a particle system: (ob == NULL) */
- if (ob == NULL) {
- /* in deformspace, calc matrix */
- invert_m4_m4(latmat, oblatt->obmat);
-
- /* back: put in deform array */
- invert_m4_m4(imat, latmat);
- }
- else {
- /* in deformspace, calc matrix */
- invert_m4_m4(imat, oblatt->obmat);
- mul_m4_m4m4(latmat, imat, ob->obmat);
-
- /* back: put in deform array */
- invert_m4_m4(imat, latmat);
- }
-
- for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) {
- for (v = 0, fv = lt->fv; v < lt->pntsv; v++, fv += lt->dv) {
- for (u = 0, fu = lt->fu; u < lt->pntsu; u++, bp++, co += 3, fp += 3, fu += lt->du) {
- if (dl) {
- fp[0] = co[0] - fu;
- fp[1] = co[1] - fv;
- fp[2] = co[2] - fw;
- }
- else {
- fp[0] = bp->vec[0] - fu;
- fp[1] = bp->vec[1] - fv;
- fp[2] = bp->vec[2] - fw;
- }
-
- mul_mat3_m4_v3(imat, fp);
- }
- }
- }
-
- lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data");
- lattice_deform_data->latticedata = latticedata;
- lattice_deform_data->object = oblatt;
- copy_m4_m4(lattice_deform_data->latmat, latmat);
-
- return lattice_deform_data;
-}
-
-void calc_latt_deform(LatticeDeformData *lattice_deform_data, float co[3], float weight)
-{
- Object *ob = lattice_deform_data->object;
- Lattice *lt = ob->data;
- float u, v, w, tu[4], tv[4], tw[4];
- float vec[3];
- int idx_w, idx_v, idx_u;
- int ui, vi, wi, uu, vv, ww;
-
- /* vgroup influence */
- int defgrp_index = -1;
- float co_prev[3], weight_blend = 0.0f;
- MDeformVert *dvert = BKE_lattice_deform_verts_get(ob);
- float *__restrict latticedata = lattice_deform_data->latticedata;
-
- if (lt->editlatt) {
- lt = lt->editlatt->latt;
- }
- if (latticedata == NULL) {
- return;
- }
-
- if (lt->vgroup[0] && dvert) {
- defgrp_index = BKE_object_defgroup_name_index(ob, lt->vgroup);
- copy_v3_v3(co_prev, co);
- }
-
- /* co is in local coords, treat with latmat */
- mul_v3_m4v3(vec, lattice_deform_data->latmat, co);
-
- /* u v w coords */
-
- if (lt->pntsu > 1) {
- u = (vec[0] - lt->fu) / lt->du;
- ui = (int)floor(u);
- u -= ui;
- key_curve_position_weights(u, tu, lt->typeu);
- }
- else {
- tu[0] = tu[2] = tu[3] = 0.0;
- tu[1] = 1.0;
- ui = 0;
- }
-
- if (lt->pntsv > 1) {
- v = (vec[1] - lt->fv) / lt->dv;
- vi = (int)floor(v);
- v -= vi;
- key_curve_position_weights(v, tv, lt->typev);
- }
- else {
- tv[0] = tv[2] = tv[3] = 0.0;
- tv[1] = 1.0;
- vi = 0;
- }
-
- if (lt->pntsw > 1) {
- w = (vec[2] - lt->fw) / lt->dw;
- wi = (int)floor(w);
- w -= wi;
- key_curve_position_weights(w, tw, lt->typew);
- }
- else {
- tw[0] = tw[2] = tw[3] = 0.0;
- tw[1] = 1.0;
- wi = 0;
- }
-
- for (ww = wi - 1; ww <= wi + 2; ww++) {
- w = tw[ww - wi + 1];
-
- if (w != 0.0f) {
- if (ww > 0) {
- if (ww < lt->pntsw) {
- idx_w = ww * lt->pntsu * lt->pntsv;
- }
- else {
- idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv;
- }
- }
- else {
- idx_w = 0;
- }
-
- for (vv = vi - 1; vv <= vi + 2; vv++) {
- v = w * tv[vv - vi + 1];
-
- if (v != 0.0f) {
- if (vv > 0) {
- if (vv < lt->pntsv) {
- idx_v = idx_w + vv * lt->pntsu;
- }
- else {
- idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu;
- }
- }
- else {
- idx_v = idx_w;
- }
-
- for (uu = ui - 1; uu <= ui + 2; uu++) {
- u = weight * v * tu[uu - ui + 1];
-
- if (u != 0.0f) {
- if (uu > 0) {
- if (uu < lt->pntsu) {
- idx_u = idx_v + uu;
- }
- else {
- idx_u = idx_v + (lt->pntsu - 1);
- }
- }
- else {
- idx_u = idx_v;
- }
-
- madd_v3_v3fl(co, &latticedata[idx_u * 3], u);
-
- if (defgrp_index != -1) {
- weight_blend += (u * BKE_defvert_find_weight(dvert + idx_u, defgrp_index));
- }
- }
- }
- }
- }
- }
- }
-
- if (defgrp_index != -1) {
- interp_v3_v3v3(co, co_prev, co, weight_blend);
- }
-}
-
-void end_latt_deform(LatticeDeformData *lattice_deform_data)
-{
- if (lattice_deform_data->latticedata) {
- MEM_freeN(lattice_deform_data->latticedata);
- }
-
- MEM_freeN(lattice_deform_data);
-}
-
-/* calculations is in local space of deformed object
- * so we store in latmat transform from path coord inside object
- */
-typedef struct {
- float dmin[3], dmax[3];
- float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
- int no_rot_axis;
-} CurveDeform;
-
-static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
-{
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_m4m4(cd->objectspace, ob->imat, par->obmat);
- invert_m4_m4(cd->curvespace, cd->objectspace);
- copy_m3_m4(cd->objectspace3, cd->objectspace);
- cd->no_rot_axis = 0;
-}
-
-/* this makes sure we can extend for non-cyclic.
- *
- * returns OK: 1/0
- */
-static bool where_on_path_deform(
- Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius)
-{
- BevList *bl;
- float ctime1;
- int cycl = 0;
-
- /* test for cyclic */
- bl = ob->runtime.curve_cache->bev.first;
- if (!bl->nr) {
- return false;
- }
- if (bl->poly > -1) {
- cycl = 1;
- }
-
- if (cycl == 0) {
- ctime1 = CLAMPIS(ctime, 0.0f, 1.0f);
- }
- else {
- ctime1 = ctime;
- }
-
- /* vec needs 4 items */
- if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
-
- if (cycl == 0) {
- Path *path = ob->runtime.curve_cache->path;
- float dvec[3];
-
- if (ctime < 0.0f) {
- sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec);
- mul_v3_fl(dvec, ctime * (float)path->len);
- add_v3_v3(vec, dvec);
- if (quat) {
- copy_qt_qt(quat, path->data[0].quat);
- }
- if (radius) {
- *radius = path->data[0].radius;
- }
- }
- else if (ctime > 1.0f) {
- sub_v3_v3v3(dvec, path->data[path->len - 1].vec, path->data[path->len - 2].vec);
- mul_v3_fl(dvec, (ctime - 1.0f) * (float)path->len);
- add_v3_v3(vec, dvec);
- if (quat) {
- copy_qt_qt(quat, path->data[path->len - 1].quat);
- }
- if (radius) {
- *radius = path->data[path->len - 1].radius;
- }
- /* weight - not used but could be added */
- }
- }
- return true;
- }
- return false;
-}
-
-/* for each point, rotate & translate to curve */
-/* use path, since it has constant distances */
-/* co: local coord, result local too */
-/* returns quaternion for rotation, using cd->no_rot_axis */
-/* axis is using another define!!! */
-static bool calc_curve_deform(
- Object *par, float co[3], const short axis, CurveDeform *cd, float r_quat[4])
-{
- Curve *cu = par->data;
- float fac, loc[4], dir[3], new_quat[4], radius;
- short index;
- const bool is_neg_axis = (axis > 2);
-
- if (par->runtime.curve_cache == NULL) {
- /* Happens with a cyclic dependencies. */
- return false;
- }
-
- if (par->runtime.curve_cache->path == NULL) {
- return false; /* happens on append, cyclic dependencies and empty curves */
- }
-
- /* options */
- if (is_neg_axis) {
- index = axis - 3;
- if (cu->flag & CU_STRETCH) {
- fac = -(co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
- }
- else {
- fac = -(co[index] - cd->dmax[index]) / (par->runtime.curve_cache->path->totdist);
- }
- }
- else {
- index = axis;
- if (cu->flag & CU_STRETCH) {
- fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
- }
- else {
- if (LIKELY(par->runtime.curve_cache->path->totdist > FLT_EPSILON)) {
- fac = +(co[index] - cd->dmin[index]) / (par->runtime.curve_cache->path->totdist);
- }
- else {
- fac = 0.0f;
- }
- }
- }
-
- if (where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */
- float quat[4], cent[3];
-
- if (cd->no_rot_axis) { /* set by caller */
-
- /* This is not exactly the same as 2.4x, since the axis is having rotation removed rather
- * than changing the axis before calculating the tilt but serves much the same purpose. */
- float dir_flat[3] = {0, 0, 0}, q[4];
- copy_v3_v3(dir_flat, dir);
- dir_flat[cd->no_rot_axis - 1] = 0.0f;
-
- normalize_v3(dir);
- normalize_v3(dir_flat);
-
- rotation_between_vecs_to_quat(q, dir, dir_flat); /* Could this be done faster? */
-
- mul_qt_qtqt(new_quat, q, new_quat);
- }
-
- /* Logic for 'cent' orientation *
- *
- * The way 'co' is copied to 'cent' may seem to have no meaning, but it does.
- *
- * Use a curve modifier to stretch a cube out, color each side RGB,
- * positive side light, negative dark.
- * view with X up (default), from the angle that you can see 3 faces RGB colors (light),
- * anti-clockwise
- * Notice X,Y,Z Up all have light colors and each ordered CCW.
- *
- * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
- *
- * note: moved functions into quat_apply_track/vec_apply_track
- * */
- copy_qt_qt(quat, new_quat);
- copy_v3_v3(cent, co);
-
- /* zero the axis which is not used,
- * the big block of text above now applies to these 3 lines */
- quat_apply_track(
- quat,
- axis,
- (axis == 0 || axis == 2) ? 1 : 0); /* up flag is a dummy, set so no rotation is done */
- vec_apply_track(cent, axis);
- cent[index] = 0.0f;
-
- /* scale if enabled */
- if (cu->flag & CU_PATH_RADIUS) {
- mul_v3_fl(cent, radius);
- }
-
- /* local rotation */
- normalize_qt(quat);
- mul_qt_v3(quat, cent);
-
- /* translation */
- add_v3_v3v3(co, cent, loc);
-
- if (r_quat) {
- copy_qt_qt(r_quat, quat);
- }
-
- return true;
- }
- return false;
-}
-
-void curve_deform_verts(Object *cuOb,
- Object *target,
- float (*vert_coords)[3],
- int numVerts,
- MDeformVert *dvert,
- const int defgrp_index,
- short flag,
- short defaxis)
-{
- Curve *cu;
- int a;
- CurveDeform cd;
- const bool is_neg_axis = (defaxis > 2);
- const bool invert_vgroup = (flag & MOD_CURVE_INVERT_VGROUP) != 0;
-
- if (cuOb->type != OB_CURVE) {
- return;
- }
-
- cu = cuOb->data;
-
- init_curve_deform(cuOb, target, &cd);
-
- /* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */
- if (is_neg_axis == false) {
- cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = 0.0f;
- cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 1.0f;
- }
- else {
- /* negative, these bounds give a good rest position */
- cd.dmin[0] = cd.dmin[1] = cd.dmin[2] = -1.0f;
- cd.dmax[0] = cd.dmax[1] = cd.dmax[2] = 0.0f;
- }
-
- if (dvert) {
- MDeformVert *dvert_iter;
- float vec[3];
-
- if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
- for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
- const float weight = invert_vgroup ?
- 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
- BKE_defvert_find_weight(dvert_iter, defgrp_index);
-
- if (weight > 0.0f) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- copy_v3_v3(vec, vert_coords[a]);
- calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- }
- else {
- /* set mesh min/max bounds */
- INIT_MINMAX(cd.dmin, cd.dmax);
-
- for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
- const float weight = invert_vgroup ?
- 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
- BKE_defvert_find_weight(dvert_iter, defgrp_index);
- if (weight > 0.0f) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
- }
- }
-
- for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
- const float weight = invert_vgroup ?
- 1.0f - BKE_defvert_find_weight(dvert_iter, defgrp_index) :
- BKE_defvert_find_weight(dvert_iter, defgrp_index);
-
- if (weight > 0.0f) {
- /* already in 'cd.curvespace', prev for loop */
- copy_v3_v3(vec, vert_coords[a]);
- calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- }
- }
- else {
- if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
- for (a = 0; a < numVerts; a++) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- calc_curve_deform(cuOb, vert_coords[a], defaxis, &cd, NULL);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- else {
- /* set mesh min max bounds */
- INIT_MINMAX(cd.dmin, cd.dmax);
-
- for (a = 0; a < numVerts; a++) {
- mul_m4_v3(cd.curvespace, vert_coords[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
- }
-
- for (a = 0; a < numVerts; a++) {
- /* already in 'cd.curvespace', prev for loop */
- calc_curve_deform(cuOb, vert_coords[a], defaxis, &cd, NULL);
- mul_m4_v3(cd.objectspace, vert_coords[a]);
- }
- }
- }
-}
-
-/* input vec and orco = local coord in armature space */
-/* orco is original not-animated or deformed reference point */
-/* result written in vec and mat */
-void curve_deform_vector(
- Object *cuOb, Object *target, float orco[3], float vec[3], float mat[3][3], int no_rot_axis)
-{
- CurveDeform cd;
- float quat[4];
-
- if (cuOb->type != OB_CURVE) {
- unit_m3(mat);
- return;
- }
-
- init_curve_deform(cuOb, target, &cd);
- cd.no_rot_axis = no_rot_axis; /* option to only rotate for XY, for example */
-
- copy_v3_v3(cd.dmin, orco);
- copy_v3_v3(cd.dmax, orco);
-
- mul_m4_v3(cd.curvespace, vec);
-
- if (calc_curve_deform(cuOb, vec, target->trackflag, &cd, quat)) {
- float qmat[3][3];
-
- quat_to_mat3(qmat, quat);
- mul_m3_m3m3(mat, qmat, cd.objectspace3);
- }
- else {
- unit_m3(mat);
- }
-
- mul_m4_v3(cd.objectspace, vec);
-}
-
-typedef struct LatticeDeformUserdata {
- LatticeDeformData *lattice_deform_data;
- float (*vert_coords)[3];
- MDeformVert *dvert;
- int defgrp_index;
- float fac;
- bool invert_vgroup;
-} LatticeDeformUserdata;
-
-static void lattice_deform_vert_task(void *__restrict userdata,
- const int index,
- const TaskParallelTLS *__restrict UNUSED(tls))
-{
- const LatticeDeformUserdata *data = userdata;
-
- if (data->dvert != NULL) {
- const float weight = data->invert_vgroup ?
- 1.0f -
- BKE_defvert_find_weight(data->dvert + index, data->defgrp_index) :
- BKE_defvert_find_weight(data->dvert + index, data->defgrp_index);
- if (weight > 0.0f) {
- calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
- }
- }
- else {
- calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], data->fac);
- }
-}
-
-void lattice_deform_verts(Object *laOb,
- Object *target,
- Mesh *mesh,
- float (*vert_coords)[3],
- int numVerts,
- short flag,
- const char *vgroup,
- float fac)
-{
- LatticeDeformData *lattice_deform_data;
- MDeformVert *dvert = NULL;
- int defgrp_index = -1;
-
- if (laOb->type != OB_LATTICE) {
- return;
- }
-
- lattice_deform_data = init_latt_deform(laOb, target);
-
- /* Check whether to use vertex groups (only possible if target is a Mesh or Lattice).
- * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
- */
- if (vgroup && vgroup[0] && target && ELEM(target->type, OB_MESH, OB_LATTICE)) {
- defgrp_index = BKE_object_defgroup_name_index(target, vgroup);
-
- if (defgrp_index != -1) {
- /* if there's derived data without deformverts, don't use vgroups */
- if (mesh) {
- dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
- }
- else if (target->type == OB_LATTICE) {
- dvert = ((Lattice *)target->data)->dvert;
- }
- else {
- dvert = ((Mesh *)target->data)->dvert;
- }
- }
- }
-
- LatticeDeformUserdata data = {
- .lattice_deform_data = lattice_deform_data,
- .vert_coords = vert_coords,
- .dvert = dvert,
- .defgrp_index = defgrp_index,
- .fac = fac,
- .invert_vgroup = (flag & MOD_LATTICE_INVERT_VGROUP) != 0,
- };
-
- TaskParallelSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 32;
- BLI_task_parallel_range(0, numVerts, &data, lattice_deform_vert_task, &settings);
-
- end_latt_deform(lattice_deform_data);
-}
-
bool object_deform_mball(Object *ob, ListBase *dispbase)
{
if (ob->parent && ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
DispList *dl;
for (dl = dispbase->first; dl; dl = dl->next) {
- lattice_deform_verts(ob->parent, ob, NULL, (float(*)[3])dl->verts, dl->nr, 0, NULL, 1.0f);
+ BKE_lattice_deform_coords(ob->parent, ob, (float(*)[3])dl->verts, dl->nr, 0, NULL, 1.0f);
}
return true;
@@ -1194,7 +552,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
}
}
-struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *oblatt)
+struct MDeformVert *BKE_lattice_deform_verts_get(const struct Object *oblatt)
{
Lattice *lt = (Lattice *)oblatt->data;
BLI_assert(oblatt->type == OB_LATTICE);
diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c
new file mode 100644
index 00000000000..2b3349d4d9a
--- /dev/null
+++ b/source/blender/blenkernel/intern/lattice_deform.c
@@ -0,0 +1,470 @@
+/*
+ * 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Deform coordinates by a lattice object (used by modifier).
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_editmesh.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_modifier.h"
+
+#include "BKE_deform.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Lattice Deform API
+ * \{ */
+
+typedef struct LatticeDeformData {
+ const Object *object;
+ float *latticedata;
+ float latmat[4][4];
+} LatticeDeformData;
+
+LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Object *ob)
+{
+ /* we make an array with all differences */
+ Lattice *lt = oblatt->data;
+ BPoint *bp;
+ DispList *dl = oblatt->runtime.curve_cache ?
+ BKE_displist_find(&oblatt->runtime.curve_cache->disp, DL_VERTS) :
+ NULL;
+ const float *co = dl ? dl->verts : NULL;
+ float *fp, imat[4][4];
+ float fu, fv, fw;
+ int u, v, w;
+ float *latticedata;
+ float latmat[4][4];
+ LatticeDeformData *lattice_deform_data;
+
+ if (lt->editlatt) {
+ lt = lt->editlatt->latt;
+ }
+ bp = lt->def;
+
+ fp = latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw,
+ "latticedata");
+
+ /* for example with a particle system: (ob == NULL) */
+ if (ob == NULL) {
+ /* in deformspace, calc matrix */
+ invert_m4_m4(latmat, oblatt->obmat);
+
+ /* back: put in deform array */
+ invert_m4_m4(imat, latmat);
+ }
+ else {
+ /* in deformspace, calc matrix */
+ invert_m4_m4(imat, oblatt->obmat);
+ mul_m4_m4m4(latmat, imat, ob->obmat);
+
+ /* back: put in deform array */
+ invert_m4_m4(imat, latmat);
+ }
+
+ for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) {
+ for (v = 0, fv = lt->fv; v < lt->pntsv; v++, fv += lt->dv) {
+ for (u = 0, fu = lt->fu; u < lt->pntsu; u++, bp++, co += 3, fp += 3, fu += lt->du) {
+ if (dl) {
+ fp[0] = co[0] - fu;
+ fp[1] = co[1] - fv;
+ fp[2] = co[2] - fw;
+ }
+ else {
+ fp[0] = bp->vec[0] - fu;
+ fp[1] = bp->vec[1] - fv;
+ fp[2] = bp->vec[2] - fw;
+ }
+
+ mul_mat3_m4_v3(imat, fp);
+ }
+ }
+ }
+
+ lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data");
+ lattice_deform_data->latticedata = latticedata;
+ lattice_deform_data->object = oblatt;
+ copy_m4_m4(lattice_deform_data->latmat, latmat);
+
+ return lattice_deform_data;
+}
+
+void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data,
+ float co[3],
+ float weight)
+{
+ const Object *ob = lattice_deform_data->object;
+ Lattice *lt = ob->data;
+ float u, v, w, tu[4], tv[4], tw[4];
+ float vec[3];
+ int idx_w, idx_v, idx_u;
+ int ui, vi, wi, uu, vv, ww;
+
+ /* vgroup influence */
+ int defgrp_index = -1;
+ float co_prev[3], weight_blend = 0.0f;
+ const MDeformVert *dvert = BKE_lattice_deform_verts_get(ob);
+ float *__restrict latticedata = lattice_deform_data->latticedata;
+
+ if (lt->editlatt) {
+ lt = lt->editlatt->latt;
+ }
+ if (latticedata == NULL) {
+ return;
+ }
+
+ if (lt->vgroup[0] && dvert) {
+ defgrp_index = BKE_object_defgroup_name_index(ob, lt->vgroup);
+ copy_v3_v3(co_prev, co);
+ }
+
+ /* co is in local coords, treat with latmat */
+ mul_v3_m4v3(vec, lattice_deform_data->latmat, co);
+
+ /* u v w coords */
+
+ if (lt->pntsu > 1) {
+ u = (vec[0] - lt->fu) / lt->du;
+ ui = (int)floor(u);
+ u -= ui;
+ key_curve_position_weights(u, tu, lt->typeu);
+ }
+ else {
+ tu[0] = tu[2] = tu[3] = 0.0;
+ tu[1] = 1.0;
+ ui = 0;
+ }
+
+ if (lt->pntsv > 1) {
+ v = (vec[1] - lt->fv) / lt->dv;
+ vi = (int)floor(v);
+ v -= vi;
+ key_curve_position_weights(v, tv, lt->typev);
+ }
+ else {
+ tv[0] = tv[2] = tv[3] = 0.0;
+ tv[1] = 1.0;
+ vi = 0;
+ }
+
+ if (lt->pntsw > 1) {
+ w = (vec[2] - lt->fw) / lt->dw;
+ wi = (int)floor(w);
+ w -= wi;
+ key_curve_position_weights(w, tw, lt->typew);
+ }
+ else {
+ tw[0] = tw[2] = tw[3] = 0.0;
+ tw[1] = 1.0;
+ wi = 0;
+ }
+
+ for (ww = wi - 1; ww <= wi + 2; ww++) {
+ w = tw[ww - wi + 1];
+
+ if (w != 0.0f) {
+ if (ww > 0) {
+ if (ww < lt->pntsw) {
+ idx_w = ww * lt->pntsu * lt->pntsv;
+ }
+ else {
+ idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv;
+ }
+ }
+ else {
+ idx_w = 0;
+ }
+
+ for (vv = vi - 1; vv <= vi + 2; vv++) {
+ v = w * tv[vv - vi + 1];
+
+ if (v != 0.0f) {
+ if (vv > 0) {
+ if (vv < lt->pntsv) {
+ idx_v = idx_w + vv * lt->pntsu;
+ }
+ else {
+ idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu;
+ }
+ }
+ else {
+ idx_v = idx_w;
+ }
+
+ for (uu = ui - 1; uu <= ui + 2; uu++) {
+ u = weight * v * tu[uu - ui + 1];
+
+ if (u != 0.0f) {
+ if (uu > 0) {
+ if (uu < lt->pntsu) {
+ idx_u = idx_v + uu;
+ }
+ else {
+ idx_u = idx_v + (lt->pntsu - 1);
+ }
+ }
+ else {
+ idx_u = idx_v;
+ }
+
+ madd_v3_v3fl(co, &latticedata[idx_u * 3], u);
+
+ if (defgrp_index != -1) {
+ weight_blend += (u * BKE_defvert_find_weight(dvert + idx_u, defgrp_index));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (defgrp_index != -1) {
+ interp_v3_v3v3(co, co_prev, co, weight_blend);
+ }
+}
+
+void BKE_lattice_deform_data_destroy(LatticeDeformData *lattice_deform_data)
+{
+ if (lattice_deform_data->latticedata) {
+ MEM_freeN(lattice_deform_data->latticedata);
+ }
+
+ MEM_freeN(lattice_deform_data);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Lattice Deform #BKE_lattice_deform_coords API
+ *
+ * #BKE_lattice_deform_coords and related functions.
+ * \{ */
+
+typedef struct LatticeDeformUserdata {
+ LatticeDeformData *lattice_deform_data;
+ float (*vert_coords)[3];
+ const MDeformVert *dvert;
+ int defgrp_index;
+ float fac;
+ bool invert_vgroup;
+
+ /** Specific data types. */
+ struct {
+ int cd_dvert_offset;
+ } bmesh;
+} LatticeDeformUserdata;
+
+static void lattice_deform_vert_with_dvert(const LatticeDeformUserdata *data,
+ const int index,
+ const MDeformVert *dvert)
+{
+ if (dvert != NULL) {
+ const float weight = data->invert_vgroup ?
+ 1.0f - BKE_defvert_find_weight(dvert, data->defgrp_index) :
+ BKE_defvert_find_weight(dvert, data->defgrp_index);
+ if (weight > 0.0f) {
+ BKE_lattice_deform_data_eval_co(
+ data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
+ }
+ }
+ else {
+ BKE_lattice_deform_data_eval_co(
+ data->lattice_deform_data, data->vert_coords[index], data->fac);
+ }
+}
+
+static void lattice_deform_vert_task(void *__restrict userdata,
+ const int index,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ const LatticeDeformUserdata *data = userdata;
+ lattice_deform_vert_with_dvert(data, index, data->dvert ? &data->dvert[index] : NULL);
+}
+
+static void lattice_vert_task_editmesh(void *__restrict userdata, MempoolIterData *iter)
+{
+ const LatticeDeformUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v, data->bmesh.cd_dvert_offset);
+ lattice_deform_vert_with_dvert(data, BM_elem_index_get(v), dvert);
+}
+
+static void lattice_vert_task_editmesh_no_dvert(void *__restrict userdata, MempoolIterData *iter)
+{
+ const LatticeDeformUserdata *data = userdata;
+ BMVert *v = (BMVert *)iter;
+ lattice_deform_vert_with_dvert(data, BM_elem_index_get(v), NULL);
+}
+
+static void lattice_deform_coords_impl(const Object *ob_lattice,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float fac,
+ const Mesh *me_target,
+ BMEditMesh *em_target)
+{
+ LatticeDeformData *lattice_deform_data;
+ const MDeformVert *dvert = NULL;
+ int defgrp_index = -1;
+ int cd_dvert_offset = -1;
+
+ if (ob_lattice->type != OB_LATTICE) {
+ return;
+ }
+
+ lattice_deform_data = BKE_lattice_deform_data_create(ob_lattice, ob_target);
+
+ /* Check whether to use vertex groups (only possible if ob_target is a Mesh or Lattice).
+ * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
+ */
+ if (defgrp_name && defgrp_name[0] && ob_target && ELEM(ob_target->type, OB_MESH, OB_LATTICE)) {
+ defgrp_index = BKE_object_defgroup_name_index(ob_target, defgrp_name);
+
+ if (defgrp_index != -1) {
+ /* if there's derived data without deformverts, don't use vgroups */
+ if (em_target) {
+ cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
+ }
+ else if (me_target) {
+ dvert = CustomData_get_layer(&me_target->vdata, CD_MDEFORMVERT);
+ }
+ else if (ob_target->type == OB_LATTICE) {
+ dvert = ((Lattice *)ob_target->data)->dvert;
+ }
+ else {
+ dvert = ((Mesh *)ob_target->data)->dvert;
+ }
+ }
+ }
+
+ LatticeDeformUserdata data = {
+ .lattice_deform_data = lattice_deform_data,
+ .vert_coords = vert_coords,
+ .dvert = dvert,
+ .defgrp_index = defgrp_index,
+ .fac = fac,
+ .invert_vgroup = (flag & MOD_LATTICE_INVERT_VGROUP) != 0,
+ .bmesh =
+ {
+ .cd_dvert_offset = cd_dvert_offset,
+ },
+ };
+
+ if (em_target != NULL) {
+ /* While this could cause an extra loop over mesh data, in most cases this will
+ * have already been properly set. */
+ BM_mesh_elem_index_ensure(em_target->bm, BM_VERT);
+
+ if (cd_dvert_offset != -1) {
+ BLI_task_parallel_mempool(em_target->bm->vpool, &data, lattice_vert_task_editmesh, true);
+ }
+ else {
+ BLI_task_parallel_mempool(
+ em_target->bm->vpool, &data, lattice_vert_task_editmesh_no_dvert, true);
+ }
+ }
+ else {
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 32;
+ BLI_task_parallel_range(0, vert_coords_len, &data, lattice_deform_vert_task, &settings);
+ }
+
+ BKE_lattice_deform_data_destroy(lattice_deform_data);
+}
+
+void BKE_lattice_deform_coords(const Object *ob_lattice,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ int vert_coords_len,
+ short flag,
+ const char *defgrp_name,
+ float fac)
+{
+ lattice_deform_coords_impl(
+ ob_lattice, ob_target, vert_coords, vert_coords_len, flag, defgrp_name, fac, NULL, NULL);
+}
+
+void BKE_lattice_deform_coords_with_mesh(const Object *ob_lattice,
+ const Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float fac,
+ const Mesh *me_target)
+{
+ lattice_deform_coords_impl(ob_lattice,
+ ob_target,
+ vert_coords,
+ vert_coords_len,
+ flag,
+ defgrp_name,
+ fac,
+ me_target,
+ NULL);
+}
+
+void BKE_lattice_deform_coords_with_editmesh(const struct Object *ob_lattice,
+ const struct Object *ob_target,
+ float (*vert_coords)[3],
+ const int vert_coords_len,
+ const short flag,
+ const char *defgrp_name,
+ const float influence,
+ struct BMEditMesh *em_target)
+{
+ lattice_deform_coords_impl(ob_lattice,
+ ob_target,
+ vert_coords,
+ vert_coords_len,
+ flag,
+ defgrp_name,
+ influence,
+ NULL,
+ em_target);
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 3ad429c5f5a..ca23ec90c97 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1694,7 +1694,7 @@ static void library_make_local_copying_check(ID *id,
continue;
}
- /* Shapekeys are considered 'private' to their owner ID here, and never tagged
+ /* Shape-keys are considered 'private' to their owner ID here, and never tagged
* (since they cannot be linked), so we have to switch effective parent to their owner.
*/
if (GS(par_id->name) == ID_KE) {
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index d16428ccd60..d6f037f64a4 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -197,7 +197,6 @@ static ID *lib_override_library_create_from(Main *bmain, ID *reference_id)
id_us_min(local_id);
BKE_lib_override_library_init(local_id, reference_id);
- local_id->override_library->flag |= OVERRIDE_LIBRARY_AUTO;
return local_id;
}
@@ -736,13 +735,15 @@ bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local)
* Generating diff values and applying overrides are much cheaper.
*
* \return true if new overriding op was created, or some local data was reset. */
-bool BKE_lib_override_library_operations_create(Main *bmain, ID *local, const bool force_auto)
+bool BKE_lib_override_library_operations_create(Main *bmain,
+ ID *local,
+ const bool UNUSED(force_auto))
{
BLI_assert(local->override_library != NULL);
const bool is_template = (local->override_library->reference == NULL);
bool ret = false;
- if (!is_template && (force_auto || local->override_library->flag & OVERRIDE_LIBRARY_AUTO)) {
+ if (!is_template) {
/* Do not attempt to generate overriding rules from an empty place-holder generated by link
* code when it cannot find to actual library/ID. Much better to keep the local datablock as
* is in the file in that case, until broken lib is fixed. */
@@ -804,7 +805,7 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if ((ID_IS_OVERRIDE_LIBRARY(id) && force_auto) ||
- (ID_IS_OVERRIDE_LIBRARY_AUTO(id) && (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) {
+ (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH)) {
BKE_lib_override_library_operations_create(bmain, id, force_auto);
id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH;
}
diff --git a/source/blender/blenkernel/intern/mesh_wrapper.c b/source/blender/blenkernel/intern/mesh_wrapper.c
index 98b77256ad7..6a8bc698b11 100644
--- a/source/blender/blenkernel/intern/mesh_wrapper.c
+++ b/source/blender/blenkernel/intern/mesh_wrapper.c
@@ -53,7 +53,7 @@
Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
const CustomData_MeshMasks *cd_mask_extra,
- float (*vertexCos)[3],
+ const float (*vert_coords)[3],
const Mesh *me_settings)
{
Mesh *me = BKE_id_new_nomain(ID_ME, NULL);
@@ -83,7 +83,7 @@ Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
#endif
EditMeshData *edit_data = me->runtime.edit_data;
- edit_data->vertexCos = vertexCos;
+ edit_data->vertexCos = vert_coords;
return me;
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index d4b7d05c228..7c77746ea1c 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -878,10 +878,7 @@ void BKE_modifier_free_temporary_data(ModifierData *md)
if (md->type == eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
- if (amd->prevCos) {
- MEM_freeN(amd->prevCos);
- amd->prevCos = NULL;
- }
+ MEM_SAFE_FREE(amd->vert_coords_prev);
}
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 474142e8555..4c6354f12a1 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -1053,7 +1053,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index eb485e1522f..c201cb83c44 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -410,7 +410,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData
}
}
if (lattice) {
- lattice_deform_data = init_latt_deform(lattice, NULL);
+ lattice_deform_data = BKE_lattice_deform_data_create(lattice, NULL);
}
}
@@ -3150,7 +3150,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
/* lattices have to be calculated separately to avoid mixups between effector calculations */
if (psys->lattice_deform_data) {
for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
- calc_latt_deform(psys->lattice_deform_data, ca->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, ca->co, psys->lattice_strength);
}
}
}
@@ -3185,7 +3186,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
psys->totcached = totpart;
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
@@ -4413,7 +4414,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
}
if (psys->lattice_deform_data && edit == 0) {
- calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, state->co, psys->lattice_strength);
}
}
}
@@ -4696,7 +4698,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
do_child_modifiers(&modifier_ctx, mat, state, t);
if (psys->lattice_deform_data) {
- calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, state->co, psys->lattice_strength);
}
}
else {
@@ -4760,7 +4763,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
if (sim->psys->lattice_deform_data) {
- calc_latt_deform(sim->psys->lattice_deform_data, state->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ sim->psys->lattice_deform_data, state->co, psys->lattice_strength);
}
}
@@ -4970,12 +4974,13 @@ void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, Par
hkey = pa->hair;
for (h = 0; h < pa->totkey; h++, hkey++) {
mul_m4_v3(hairmat, hkey->co);
- calc_latt_deform(psys->lattice_deform_data, hkey->co, psys->lattice_strength);
+ BKE_lattice_deform_data_eval_co(
+ psys->lattice_deform_data, hkey->co, psys->lattice_strength);
mul_m4_v3(imat, hkey->co);
}
}
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
/* protect the applied shape */
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 31d51a74e7f..606291a9ae0 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -536,7 +536,7 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
}
if (ctx->sim.psys->lattice_deform_data) {
- end_latt_deform(ctx->sim.psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(ctx->sim.psys->lattice_deform_data);
ctx->sim.psys->lattice_deform_data = NULL;
}
@@ -4126,7 +4126,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_
}
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
@@ -4616,7 +4616,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
/* cleanup */
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 9cd17310f07..836fe59d7bd 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -138,6 +138,7 @@ static int ptcache_data_size[] = {
static int ptcache_extra_datasize[] = {
0,
sizeof(ParticleSpring),
+ sizeof(float) * 3,
};
/* forward declarations */
@@ -176,6 +177,23 @@ static int ptcache_basic_header_write(PTCacheFile *pf)
return 1;
}
+static void ptcache_add_extra_data(PTCacheMem *pm,
+ unsigned int type,
+ unsigned int count,
+ void *data)
+{
+ PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: extra data descriptor");
+
+ extra->type = type;
+ extra->totdata = count;
+
+ size_t size = extra->totdata * ptcache_extra_datasize[extra->type];
+
+ extra->data = MEM_mallocN(size, "Point cache: extra data");
+ memcpy(extra->data, data, size);
+
+ BLI_addtail(&pm->extradata, extra);
+}
/* Softbody functions */
static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
{
@@ -467,21 +485,12 @@ static int ptcache_particle_totwrite(void *psys_v, int cfra)
static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
{
ParticleSystem *psys = psys_v;
- PTCacheExtra *extra = NULL;
if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid &&
psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS && psys->tot_fluidsprings &&
psys->fluid_springs) {
- extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data");
-
- extra->type = BPHYS_EXTRA_FLUID_SPRINGS;
- extra->totdata = psys->tot_fluidsprings;
-
- extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type],
- "Point cache: extra data");
- memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]);
-
- BLI_addtail(&pm->extradata, extra);
+ ptcache_add_extra_data(
+ pm, BPHYS_EXTRA_FLUID_SPRINGS, psys->tot_fluidsprings, psys->fluid_springs);
}
}
@@ -575,6 +584,33 @@ static void ptcache_cloth_interpolate(
/* should vert->xconst be interpolated somehow too? - jahka */
}
+static void ptcache_cloth_extra_write(void *cloth_v, PTCacheMem *pm, int UNUSED(cfra))
+{
+ ClothModifierData *clmd = cloth_v;
+ Cloth *cloth = clmd->clothObject;
+
+ if (!is_zero_v3(cloth->average_acceleration)) {
+ ptcache_add_extra_data(pm, BPHYS_EXTRA_CLOTH_ACCELERATION, 1, cloth->average_acceleration);
+ }
+}
+static void ptcache_cloth_extra_read(void *cloth_v, PTCacheMem *pm, float UNUSED(cfra))
+{
+ ClothModifierData *clmd = cloth_v;
+ Cloth *cloth = clmd->clothObject;
+ PTCacheExtra *extra = pm->extradata.first;
+
+ zero_v3(cloth->average_acceleration);
+
+ for (; extra; extra = extra->next) {
+ switch (extra->type) {
+ case BPHYS_EXTRA_CLOTH_ACCELERATION: {
+ copy_v3_v3(cloth->average_acceleration, extra->data);
+ break;
+ }
+ }
+ }
+}
+
static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
{
ClothModifierData *clmd = cloth_v;
@@ -1681,8 +1717,8 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->write_stream = NULL;
pid->read_stream = NULL;
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
+ pid->write_extra_data = ptcache_cloth_extra_write;
+ pid->read_extra_data = ptcache_cloth_extra_read;
pid->interpolate_extra_data = NULL;
pid->write_header = ptcache_basic_header_write;
diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh
index b929d1220da..07155439170 100644
--- a/source/blender/blenlib/BLI_array.hh
+++ b/source/blender/blenlib/BLI_array.hh
@@ -55,7 +55,7 @@ template<
* The number of values that can be stored in the array, without doing a heap allocation.
*
* When T is large, the small buffer optimization is disabled by default to avoid large
- * unexpected allocations on the stack. It can still be enabled explicitely though.
+ * unexpected allocations on the stack. It can still be enabled explicitly though.
*/
uint InlineBufferCapacity = (sizeof(T) < 100) ? 4 : 0,
/**
diff --git a/source/blender/blenlib/BLI_hash.hh b/source/blender/blenlib/BLI_hash.hh
index 57d5f7f9d8a..5490c953756 100644
--- a/source/blender/blenlib/BLI_hash.hh
+++ b/source/blender/blenlib/BLI_hash.hh
@@ -65,7 +65,7 @@
*
* - When you want to provide a different hash function for a type that already has a default hash
* function: Implement a struct like the one below and pass it as template parameter to the hash
- * table explicitely.
+ * table explicitly.
*
* struct MyCustomHash {
* uint32_t operator()(const TheType &value) const {
@@ -97,6 +97,16 @@ template<typename T> struct DefaultHash {
}
};
+/**
+ * Use the same hash function for const and non const variants of a type.
+ */
+template<typename T> struct DefaultHash<const T> {
+ uint32_t operator()(const T &value) const
+ {
+ return DefaultHash<T>{}(value);
+ }
+};
+
#define TRIVIAL_DEFAULT_INT_HASH(TYPE) \
template<> struct DefaultHash<TYPE> { \
uint32_t operator()(TYPE value) const \
diff --git a/source/blender/blenlib/BLI_linear_allocator.hh b/source/blender/blenlib/BLI_linear_allocator.hh
index f968f9f15ce..2a0dc939cb9 100644
--- a/source/blender/blenlib/BLI_linear_allocator.hh
+++ b/source/blender/blenlib/BLI_linear_allocator.hh
@@ -171,7 +171,7 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya
MutableSpan<T *> pointers = void_pointers.cast<T *>();
for (uint i : IndexRange(n)) {
- new (pointers[i]) T(std::forward<Args>(args)...);
+ new ((void *)pointers[i]) T(std::forward<Args>(args)...);
}
return pointers;
diff --git a/source/blender/blenlib/BLI_map.hh b/source/blender/blenlib/BLI_map.hh
index 4fc9f98d835..a4c3ee76ca1 100644
--- a/source/blender/blenlib/BLI_map.hh
+++ b/source/blender/blenlib/BLI_map.hh
@@ -94,7 +94,7 @@ template<
* that (unlike vector) initializing a map has a O(n) cost in the number of slots.
*
* When Key or Value are large, the small buffer optimization is disabled by default to avoid
- * large unexpected allocations on the stack. It can still be enabled explicitely though.
+ * large unexpected allocations on the stack. It can still be enabled explicitly though.
*/
uint32_t InlineBufferCapacity = (sizeof(Key) + sizeof(Value) < 100) ? 4 : 0,
/**
@@ -470,7 +470,7 @@ class Map {
const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
{
return this->add_or_modify__impl(
- std::forward<Key>(key), create_value, modify_value, m_hash(key));
+ std::forward<ForwardKey>(key), create_value, modify_value, m_hash(key));
}
/**
@@ -1175,7 +1175,7 @@ class Map {
bool add_overwrite__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash)
{
auto create_func = [&](Value *ptr) {
- new (ptr) Value(std::forward<ForwardValue>(value));
+ new ((void *)ptr) Value(std::forward<ForwardValue>(value));
return true;
};
auto modify_func = [&](Value *ptr) {
diff --git a/source/blender/blenlib/BLI_map_slots.hh b/source/blender/blenlib/BLI_map_slots.hh
index 9ea2c4cad89..f12eefcaf0b 100644
--- a/source/blender/blenlib/BLI_map_slots.hh
+++ b/source/blender/blenlib/BLI_map_slots.hh
@@ -84,13 +84,13 @@ template<typename Key, typename Value> class SimpleMapSlot {
{
m_state = other.m_state;
if (other.m_state == Occupied) {
- new (this->key()) Key(*other.key());
- new (this->value()) Value(*other.value());
+ new ((void *)this->key()) Key(*other.key());
+ new ((void *)this->value()) Value(*other.value());
}
}
/**
- * The move construtor has to copy the state. If the other slot was occupied, the key and value
+ * The move constructor has to copy the state. If the other slot was occupied, the key and value
* from the other have to moved as well. The other slot stays in the state it was in before. Its
* optionally stored key and value remain in a moved-from state.
*/
@@ -98,8 +98,8 @@ template<typename Key, typename Value> class SimpleMapSlot {
{
m_state = other.m_state;
if (other.m_state == Occupied) {
- new (this->key()) Key(std::move(*other.key()));
- new (this->value()) Value(std::move(*other.value()));
+ new ((void *)this->key()) Key(std::move(*other.key()));
+ new ((void *)this->value()) Value(std::move(*other.value()));
}
}
@@ -170,8 +170,8 @@ template<typename Key, typename Value> class SimpleMapSlot {
BLI_assert(!this->is_occupied());
BLI_assert(other.is_occupied());
m_state = Occupied;
- new (this->key()) Key(std::move(*other.key()));
- new (this->value()) Value(std::move(*other.value()));
+ new ((void *)this->key()) Key(std::move(*other.key()));
+ new ((void *)this->value()) Value(std::move(*other.value()));
other.key()->~Key();
other.value()->~Value();
}
@@ -198,7 +198,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
{
BLI_assert(!this->is_occupied());
this->occupy_without_value(std::forward<ForwardKey>(key), hash);
- new (this->value()) Value(std::forward<ForwardValue>(value));
+ new ((void *)this->value()) Value(std::forward<ForwardValue>(value));
}
/**
@@ -209,7 +209,7 @@ template<typename Key, typename Value> class SimpleMapSlot {
{
BLI_assert(!this->is_occupied());
m_state = Occupied;
- new (this->key()) Key(std::forward<ForwardKey>(key));
+ new ((void *)this->key()) Key(std::forward<ForwardKey>(key));
}
/**
@@ -251,14 +251,14 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
IntrusiveMapSlot(const IntrusiveMapSlot &other) : m_key(other.m_key)
{
if (KeyInfo::is_not_empty_or_removed(m_key)) {
- new (this->value()) Value(*other.value());
+ new ((void *)this->value()) Value(*other.value());
}
}
IntrusiveMapSlot(IntrusiveMapSlot &&other) noexcept : m_key(other.m_key)
{
if (KeyInfo::is_not_empty_or_removed(m_key)) {
- new (this->value()) Value(std::move(*other.value()));
+ new ((void *)this->value()) Value(std::move(*other.value()));
}
}
@@ -303,7 +303,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
BLI_assert(!this->is_occupied());
BLI_assert(other.is_occupied());
m_key = std::move(other.m_key);
- new (this->value()) Value(std::move(*other.value()));
+ new ((void *)this->value()) Value(std::move(*other.value()));
other.m_key.~Key();
other.value()->~Value();
}
@@ -321,7 +321,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
BLI_assert(!this->is_occupied());
BLI_assert(KeyInfo::is_not_empty_or_removed(key));
this->occupy_without_value(std::forward<ForwardKey>(key), hash);
- new (this->value()) Value(std::forward<ForwardValue>(value));
+ new ((void *)this->value()) Value(std::forward<ForwardValue>(value));
}
template<typename ForwardKey> void occupy_without_value(ForwardKey &&key, uint32_t UNUSED(hash))
diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh
index de9fc956bfb..81792e2101c 100644
--- a/source/blender/blenlib/BLI_memory_utils.hh
+++ b/source/blender/blenlib/BLI_memory_utils.hh
@@ -22,6 +22,7 @@
*/
#include <memory>
+#include <new>
#include "BLI_utildefines.h"
@@ -39,13 +40,13 @@ namespace blender {
template<typename T> void default_construct_n(T *ptr, uint n)
{
/* This is not strictly necessary, because the loop below will be optimized away anyway. It is
- * nice to make behavior this explicitely, though. */
+ * nice to make behavior this explicitly, though. */
if (std::is_trivially_constructible<T>::value) {
return;
}
for (uint i = 0; i < n; i++) {
- new (ptr + i) T;
+ new ((void *)(ptr + i)) T;
}
}
@@ -61,7 +62,7 @@ template<typename T> void default_construct_n(T *ptr, uint n)
template<typename T> void destruct_n(T *ptr, uint n)
{
/* This is not strictly necessary, because the loop below will be optimized away anyway. It is
- * nice to make behavior this explicitely, though. */
+ * nice to make behavior this explicitly, though. */
if (std::is_trivially_destructible<T>::value) {
return;
}
@@ -101,7 +102,7 @@ template<typename T> void initialized_copy_n(const T *src, uint n, T *dst)
template<typename T> void uninitialized_copy_n(const T *src, uint n, T *dst)
{
for (uint i = 0; i < n; i++) {
- new (dst + i) T(src[i]);
+ new ((void *)(dst + i)) T(src[i]);
}
}
@@ -135,7 +136,7 @@ template<typename T> void initialized_move_n(T *src, uint n, T *dst)
template<typename T> void uninitialized_move_n(T *src, uint n, T *dst)
{
for (uint i = 0; i < n; i++) {
- new (dst + i) T(std::move(src[i]));
+ new ((void *)(dst + i)) T(std::move(src[i]));
}
}
@@ -162,7 +163,7 @@ template<typename T> void initialized_relocate_n(T *src, uint n, T *dst)
*
* Before:
* src: initialized
- * dst: uinitialized
+ * dst: uninitialized
* After:
* src: uninitialized
* dst: initialized
@@ -199,7 +200,7 @@ template<typename T> void initialized_fill_n(T *dst, uint n, const T &value)
template<typename T> void uninitialized_fill_n(T *dst, uint n, const T &value)
{
for (uint i = 0; i < n; i++) {
- new (dst + i) T(value);
+ new ((void *)(dst + i)) T(value);
}
}
diff --git a/source/blender/blenlib/BLI_optional.hh b/source/blender/blenlib/BLI_optional.hh
index b5f98d6fa97..2e6b66d0eac 100644
--- a/source/blender/blenlib/BLI_optional.hh
+++ b/source/blender/blenlib/BLI_optional.hh
@@ -121,7 +121,7 @@ template<typename T> class Optional {
this->value() = value;
}
else {
- new (this->value_ptr()) T(value);
+ new ((void *)this->value_ptr()) T(value);
m_set = true;
}
}
@@ -132,7 +132,7 @@ template<typename T> class Optional {
this->value() = std::move(value);
}
else {
- new (this->value_ptr()) T(std::move(value));
+ new ((void *)this->value_ptr()) T(std::move(value));
m_set = true;
}
}
@@ -140,14 +140,14 @@ template<typename T> class Optional {
void set_new(const T &value)
{
BLI_assert(!m_set);
- new (this->value_ptr()) T(value);
+ new ((void *)this->value_ptr()) T(value);
m_set = true;
}
void set_new(T &&value)
{
BLI_assert(!m_set);
- new (this->value_ptr()) T(std::move(value));
+ new ((void *)this->value_ptr()) T(std::move(value));
m_set = true;
}
diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh
index af0c3424f5a..d23aa96e434 100644
--- a/source/blender/blenlib/BLI_set.hh
+++ b/source/blender/blenlib/BLI_set.hh
@@ -91,7 +91,7 @@ template<
* that (unlike vector) initializing a set has a O(n) cost in the number of slots.
*
* When Key is large, the small buffer optimization is disabled by default to avoid large
- * unexpected allocations on the stack. It can still be enabled explicitely though.
+ * unexpected allocations on the stack. It can still be enabled explicitly though.
*/
uint32_t InlineBufferCapacity = (sizeof(Key) < 100) ? 4 : 0,
/**
@@ -433,7 +433,7 @@ class Set {
/**
* Creates a new slot array and reinserts all keys inside of that. This method can be used to get
- * rid of dummy slots. Also this is useful for benchmarking the grow function.
+ * rid of removed slots. Also this is useful for benchmarking the grow function.
*/
void rehash()
{
diff --git a/source/blender/blenlib/BLI_set_slots.hh b/source/blender/blenlib/BLI_set_slots.hh
index 15f56f2450e..581e70ce628 100644
--- a/source/blender/blenlib/BLI_set_slots.hh
+++ b/source/blender/blenlib/BLI_set_slots.hh
@@ -80,7 +80,7 @@ template<typename Key> class SimpleSetSlot {
{
m_state = other.m_state;
if (other.m_state == Occupied) {
- new (this->key()) Key(*other.key());
+ new ((void *)this->key()) Key(*other.key());
}
}
@@ -93,7 +93,7 @@ template<typename Key> class SimpleSetSlot {
{
m_state = other.m_state;
if (other.m_state == Occupied) {
- new (this->key()) Key(std::move(*other.key()));
+ new ((void *)this->key()) Key(std::move(*other.key()));
}
}
@@ -148,7 +148,7 @@ template<typename Key> class SimpleSetSlot {
BLI_assert(!this->is_occupied());
BLI_assert(other.is_occupied());
m_state = Occupied;
- new (this->key()) Key(std::move(*other.key()));
+ new ((void *)this->key()) Key(std::move(*other.key()));
other.key()->~Key();
}
@@ -173,7 +173,7 @@ template<typename Key> class SimpleSetSlot {
{
BLI_assert(!this->is_occupied());
m_state = Occupied;
- new (this->key()) Key(std::forward<ForwardKey>(key));
+ new ((void *)this->key()) Key(std::forward<ForwardKey>(key));
}
/**
@@ -221,7 +221,7 @@ template<typename Key> class HashedSetSlot {
m_state = other.m_state;
if (other.m_state == Occupied) {
m_hash = other.m_hash;
- new (this->key()) Key(*other.key());
+ new ((void *)this->key()) Key(*other.key());
}
}
@@ -230,7 +230,7 @@ template<typename Key> class HashedSetSlot {
m_state = other.m_state;
if (other.m_state == Occupied) {
m_hash = other.m_hash;
- new (this->key()) Key(std::move(*other.key()));
+ new ((void *)this->key()) Key(std::move(*other.key()));
}
}
@@ -266,7 +266,7 @@ template<typename Key> class HashedSetSlot {
BLI_assert(other.is_occupied());
m_state = Occupied;
m_hash = hash;
- new (this->key()) Key(std::move(*other.key()));
+ new ((void *)this->key()) Key(std::move(*other.key()));
other.key()->~Key();
}
@@ -287,7 +287,7 @@ template<typename Key> class HashedSetSlot {
BLI_assert(!this->is_occupied());
m_state = Occupied;
m_hash = hash;
- new (this->key()) Key(std::forward<ForwardKey>(key));
+ new ((void *)this->key()) Key(std::forward<ForwardKey>(key));
}
void remove()
diff --git a/source/blender/blenlib/BLI_stack.hh b/source/blender/blenlib/BLI_stack.hh
index 030d9c84c8e..2170b8b23bc 100644
--- a/source/blender/blenlib/BLI_stack.hh
+++ b/source/blender/blenlib/BLI_stack.hh
@@ -75,7 +75,7 @@ template<
* not initialized when it is not needed.
*
* When T is large, the small buffer optimization is disabled by default to avoid large
- * unexpected allocations on the stack. It can still be enabled explicitely though.
+ * unexpected allocations on the stack. It can still be enabled explicitly though.
*/
uint InlineBufferCapacity = (sizeof(T) < 100) ? 4 : 0,
/**
diff --git a/source/blender/blenlib/BLI_string_ref.hh b/source/blender/blenlib/BLI_string_ref.hh
index 073137fe175..bb8479efe95 100644
--- a/source/blender/blenlib/BLI_string_ref.hh
+++ b/source/blender/blenlib/BLI_string_ref.hh
@@ -292,8 +292,8 @@ inline std::ostream &operator<<(std::ostream &stream, StringRefNull ref)
}
/**
- * Adding two StringRefs will allocate an std::string. This is not efficient, but convenient in
- * most cases.
+ * Adding two #StringRefs will allocate an std::string.
+ * This is not efficient, but convenient in most cases.
*/
inline std::string operator+(StringRef a, StringRef b)
{
@@ -347,7 +347,7 @@ inline bool StringRefBase::endswith(StringRef suffix) const
}
/**
- * Return a new StringRef containing only a substring of the original string.
+ * Return a new #StringRef containing only a sub-string of the original string.
*/
inline StringRef StringRefBase::substr(uint start, uint size) const
{
diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh
index b2b2da0a4b0..f61a3d4282b 100644
--- a/source/blender/blenlib/BLI_vector.hh
+++ b/source/blender/blenlib/BLI_vector.hh
@@ -68,7 +68,7 @@ template<
* not initialized when it is not needed.
*
* When T is large, the small buffer optimization is disabled by default to avoid large
- * unexpected allocations on the stack. It can still be enabled explicitely though.
+ * unexpected allocations on the stack. It can still be enabled explicitly though.
*/
uint InlineBufferCapacity = (sizeof(T) < 100) ? 4 : 0,
/**
@@ -79,7 +79,7 @@ template<
class Vector {
private:
/**
- * Use pointers instead of storing the size explicitely. This reduces the number of instructions
+ * Use pointers instead of storing the size explicitly. This reduces the number of instructions
* in `append`.
*
* The pointers might point to the memory in the inline buffer.
@@ -95,7 +95,7 @@ class Vector {
AlignedBuffer<(uint)sizeof(T) * InlineBufferCapacity, (uint)alignof(T)> m_inline_buffer;
/**
- * Store the size of the vector explicitely in debug builds. Otherwise you'd always have to call
+ * Store the size of the vector explicitly in debug builds. Otherwise you'd always have to call
* the `size` function or do the math to compute it from the pointers manually. This is rather
* annoying. Knowing the size of a vector is often quite essential when debugging some code.
*/
diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh
index dcd4927aed2..03f25a68cd8 100644
--- a/source/blender/blenlib/BLI_vector_set.hh
+++ b/source/blender/blenlib/BLI_vector_set.hh
@@ -27,7 +27,7 @@
*
* All core operations (add, remove and contains) can be done in O(1) amortized expected time.
*
- * Using a VectorSet instead of a normal Set can be benefitial in any of the following
+ * Using a VectorSet instead of a normal Set can be beneficial in any of the following
* circumstances:
* - The insertion order is important.
* - Iteration over all keys has to be fast.
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index a88b804d5b2..2bf4921f8df 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5604,7 +5604,7 @@ static void direct_link_modifiers(BlendDataReader *reader, ListBase *lb, Object
else if (md->type == eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
- amd->prevCos = NULL;
+ amd->vert_coords_prev = NULL;
}
else if (md->type == eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData *)md;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 84c17a7ceb7..c6257738cf7 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1379,6 +1379,7 @@ static const char *ptcache_data_struct[] = {
static const char *ptcache_extra_struct[] = {
"",
"ParticleSpring",
+ "vec3f",
};
static void write_pointcaches(BlendWriter *writer, ListBase *ptcaches)
{
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index ee543dcf25d..df6c139e916 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -251,8 +251,7 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd
if (graph->is_active && id_node->is_user_modified) {
deg_editors_id_update(update_ctx, id_orig);
}
- /* ID may need to get its auto-override operations refreshed. */
- if (ID_IS_OVERRIDE_LIBRARY_AUTO(id_orig)) {
+ if (ID_IS_OVERRIDE_LIBRARY(id_orig)) {
id_orig->tag |= LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH;
}
/* Inform draw engines that something was changed. */
diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c
index bb313b31deb..66a67d6b8fe 100644
--- a/source/blender/draw/intern/draw_cache_impl_lattice.c
+++ b/source/blender/draw/intern/draw_cache_impl_lattice.c
@@ -127,7 +127,7 @@ typedef struct LatticeRenderData {
int actbp;
- struct MDeformVert *dvert;
+ const struct MDeformVert *dvert;
} LatticeRenderData;
enum {
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index e7dff422105..2ba766f4729 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1467,6 +1467,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
/* Only iterate over objects for internal engines or when overlays are enabled */
if (do_populate_loop) {
+ DST.dupli_origin = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
continue;
@@ -1864,6 +1865,7 @@ void DRW_render_object_iter(
const int object_type_exclude_viewport = draw_ctx->v3d ?
draw_ctx->v3d->object_type_exclude_viewport :
0;
+ DST.dupli_origin = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
DST.dupli_parent = data_.dupli_parent;
@@ -2121,6 +2123,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
const int object_type_exclude_select = (v3d->object_type_exclude_viewport |
v3d->object_type_exclude_select);
bool filter_exclude = false;
+ DST.dupli_origin = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
if (!BKE_object_is_visible_in_viewport(v3d, ob)) {
continue;
@@ -2271,6 +2274,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
drw_engines_world_update(DST.draw_ctx.scene);
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
+ DST.dupli_origin = NULL;
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (DST.draw_ctx.depsgraph, ob) {
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
continue;
diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c
index 365c5b5d264..635fc6279ea 100644
--- a/source/blender/editors/mesh/editmesh_select_similar.c
+++ b/source/blender/editors/mesh/editmesh_select_similar.c
@@ -23,6 +23,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_kdtree.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -1007,7 +1008,9 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em->bm;
int cd_dvert_offset = -1;
- int dvert_selected = 0;
+ BLI_bitmap *defbase_selected = NULL;
+ int defbase_len = 0;
+
invert_m4_m4(ob->imat, ob->obmat);
if (bm->totvertsel == 0) {
@@ -1019,6 +1022,11 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
if (cd_dvert_offset == -1) {
continue;
}
+ defbase_len = BLI_listbase_count(&ob->defbase);
+ if (defbase_len == 0) {
+ continue;
+ }
+ defbase_selected = BLI_BITMAP_NEW(defbase_len, __func__);
}
BMVert *vert; /* Mesh vertex. */
@@ -1048,7 +1056,9 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
for (int i = 0; i < dvert->totweight; i++, dw++) {
if (dw->weight > 0.0f) {
- dvert_selected |= (1 << dw->def_nr);
+ if (LIKELY(dw->def_nr < defbase_len)) {
+ BLI_BITMAP_ENABLE(defbase_selected, dw->def_nr);
+ }
}
}
break;
@@ -1060,13 +1070,15 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
if (type == SIMVERT_VGROUP) {
/* We store the names of the vertex groups, so we can select
* vertex groups with the same name in different objects. */
- const int dvert_tot = BLI_listbase_count(&ob->defbase);
- for (int i = 0; i < dvert_tot; i++) {
- if (dvert_selected & (1 << i)) {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, i);
+
+ int i = 0;
+ LISTBASE_FOREACH (bDeformGroup *, dg, &ob->defbase) {
+ if (BLI_BITMAP_TEST(defbase_selected, i)) {
BLI_gset_add(gset, dg->name);
}
+ i += 1;
}
+ MEM_freeN(defbase_selected);
}
}
@@ -1082,32 +1094,42 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
BLI_kdtree_3d_balance(tree_3d);
}
- /* Run .the BM operators. */
+ /* Run the matching operations. */
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em->bm;
bool changed = false;
int cd_dvert_offset = -1;
- int dvert_selected = 0;
+ BLI_bitmap *defbase_selected = NULL;
+ int defbase_len = 0;
if (type == SIMVERT_VGROUP) {
cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
if (cd_dvert_offset == -1) {
continue;
}
+ defbase_len = BLI_listbase_count(&ob->defbase);
+ if (defbase_len == 0) {
+ continue;
+ }
/* We map back the names of the vertex groups to their corresponding indices
* for this object. This is fast, and keep the logic for each vertex very simple. */
+
+ defbase_selected = BLI_BITMAP_NEW(defbase_len, __func__);
+ bool found_any = false;
GSetIterator gs_iter;
GSET_ITER (gs_iter, gset) {
const char *name = BLI_gsetIterator_getKey(&gs_iter);
int vgroup_id = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
if (vgroup_id != -1) {
- dvert_selected |= (1 << vgroup_id);
+ BLI_BITMAP_ENABLE(defbase_selected, vgroup_id);
+ found_any = true;
}
}
- if (dvert_selected == 0) {
+ if (found_any == false) {
+ MEM_freeN(defbase_selected);
continue;
}
}
@@ -1167,9 +1189,11 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
for (int i = 0; i < dvert->totweight; i++, dw++) {
if (dw->weight > 0.0f) {
- if (dvert_selected & (1 << dw->def_nr)) {
- select = true;
- break;
+ if (LIKELY(dw->def_nr < defbase_len)) {
+ if (BLI_BITMAP_TEST(defbase_selected, dw->def_nr)) {
+ select = true;
+ break;
+ }
}
}
}
@@ -1184,6 +1208,10 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
}
}
+ if (type == SIMVERT_VGROUP) {
+ MEM_freeN(defbase_selected);
+ }
+
if (changed) {
EDBM_selectmode_flush(em);
EDBM_update_generic(ob->data, false, false);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 1e04355c9a7..a2d33ffe413 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -678,7 +678,7 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
return 0;
}
- if (ID_IS_OVERRIDE_LIBRARY(ob)) {
+ if (ID_IS_OVERRIDE_LIBRARY(ob) && ptr.data != NULL) {
CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override");
return (((bConstraint *)ptr.data)->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) != 0;
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index eed3f2ea90c..fd2fcb11635 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2400,10 +2400,6 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
/* TODO: is setting active needed? */
BKE_view_layer_base_select_and_set_active(view_layer, base);
}
- else {
- /* Disable auto-override tags for non-active objects, will help with performaces... */
- new_ob->id.override_library->flag &= ~OVERRIDE_LIBRARY_AUTO;
- }
/* We still want to store all objects' current override status (i.e. change of parent). */
BKE_lib_override_library_operations_create(bmain, &new_ob->id, true);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 3203282c30c..7776af11a77 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -106,6 +106,27 @@
#define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024
#define CLOTH_SIMULATION_TIME_STEP 0.01f
+static void cloth_brush_constraint_key_get(int r_key[2], const int v1, const int v2)
+{
+ if (v1 < v2) {
+ r_key[0] = v1;
+ r_key[1] = v2;
+ }
+ else {
+ r_key[0] = v2;
+ r_key[1] = v1;
+ }
+}
+
+static bool cloth_brush_sim_has_length_constraint(SculptClothSimulation *cloth_sim,
+ const int v1,
+ const int v2)
+{
+ int constraint[2];
+ cloth_brush_constraint_key_get(constraint, v1, v2);
+ return BLI_gset_haskey(cloth_sim->created_length_constraints, constraint);
+}
+
static void cloth_brush_add_length_constraint(SculptSession *ss,
SculptClothSimulation *cloth_sim,
const int v1,
@@ -126,6 +147,11 @@ static void cloth_brush_add_length_constraint(SculptSession *ss,
sizeof(SculptClothLengthConstraint),
"length constraints");
}
+
+ /* Add the constraint to the GSet to avoid creating it again. */
+ int constraint[2];
+ cloth_brush_constraint_key_get(constraint, v1, v2);
+ BLI_gset_add(cloth_sim->created_length_constraints, constraint);
}
static void do_cloth_brush_build_constraints_task_cb_ex(
@@ -159,7 +185,8 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
for (int c_i = 0; c_i < tot_indices; c_i++) {
for (int c_j = 0; c_j < tot_indices; c_j++) {
- if (c_i != c_j) {
+ if (c_i != c_j && !cloth_brush_sim_has_length_constraint(
+ data->cloth_sim, build_indices[c_i], build_indices[c_j])) {
cloth_brush_add_length_constraint(
ss, data->cloth_sim, build_indices[c_i], build_indices[c_j]);
}
@@ -445,6 +472,9 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd,
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, false, totnode);
+ cloth_sim->created_length_constraints = BLI_gset_new(
+ BLI_ghashutil_inthash_v2_p, BLI_ghashutil_inthash_v2_cmp, "created length constraints");
+
SculptThreadedTaskData build_constraints_data = {
.sd = sd,
.ob = ob,
@@ -456,6 +486,8 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd,
};
BLI_task_parallel_range(
0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
+
+ BLI_gset_free(cloth_sim->created_length_constraints, NULL);
}
static void cloth_brush_satisfy_constraints(SculptSession *ss,
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index 03ed8870d67..6d08fd00cab 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -52,7 +52,7 @@
/* Set Up Drivers Editor */
/* Set up UI configuration for Drivers Editor */
-/* NOTE: Currently called from windowmanager
+/* NOTE: Currently called from window-manager
* (new drivers editor window) and RNA (mode switching) */
void ED_drivers_editor_init(bContext *C, ScrArea *area)
{
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index fa378954a30..e50b25de412 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -3667,7 +3667,7 @@ static int text_find_set_selected_exec(bContext *C, wmOperator *op)
void TEXT_OT_find_set_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Find Set Selected";
+ ot->name = "Find & Set Selection";
ot->idname = "TEXT_OT_find_set_selected";
ot->description = "Find specified text and set as selected";
@@ -3698,7 +3698,7 @@ static int text_replace_set_selected_exec(bContext *C, wmOperator *UNUSED(op))
void TEXT_OT_replace_set_selected(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Replace Set Selected";
+ ot->name = "Replace & Set Selection";
ot->idname = "TEXT_OT_replace_set_selected";
ot->description = "Replace text with specified text and set as selected";
diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c
index 2bfce9f8418..22261b9bbd8 100644
--- a/source/blender/editors/transform/transform_convert_gpencil.c
+++ b/source/blender/editors/transform/transform_convert_gpencil.c
@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_ghash.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BKE_colortools.h"
@@ -76,7 +77,6 @@ void createTransGPencil(bContext *C, TransInfo *t)
bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
Object *obact = CTX_data_active_object(C);
- bGPDlayer *gpl;
TransData *td = NULL;
float mtx[3][3], smtx[3][3];
@@ -110,15 +110,12 @@ void createTransGPencil(bContext *C, TransInfo *t)
/* First Pass: Count the number of data-points required for the strokes,
* (and additional info about the configuration - e.g. 2D/3D?).
*/
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* Only editable and visible layers are considered. */
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
bGPDframe *gpf;
bGPDstroke *gps;
- bGPDframe *init_gpf = gpl->actframe;
- if (is_multiedit) {
- init_gpf = gpl->frames.first;
- }
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
for (gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
@@ -127,7 +124,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
- /* check if the color is editable */
+ /* Check if the color is editable. */
if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
continue;
}
@@ -135,23 +132,22 @@ void createTransGPencil(bContext *C, TransInfo *t)
if (is_prop_edit) {
/* Proportional Editing... */
if (is_prop_edit_connected) {
- /* connected only - so only if selected */
+ /* Connected only - so only if selected. */
if (gps->flag & GP_STROKE_SELECT) {
tc->data_len += gps->totpoints;
}
}
else {
- /* everything goes - connection status doesn't matter */
+ /* Everything goes - connection status doesn't matter. */
tc->data_len += gps->totpoints;
}
}
else {
- /* only selected stroke points are considered */
+ /* Only selected stroke points are considered. */
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
int i;
- // TODO: 2D vs 3D?
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
tc->data_len++;
@@ -161,7 +157,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
}
}
}
- /* if not multiedit out of loop */
+ /* If not multiedit out of loop. */
if (!is_multiedit) {
break;
}
@@ -169,7 +165,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
}
}
- /* Stop trying if nothing selected */
+ /* Stop trying if nothing selected. */
if (tc->data_len == 0) {
return;
}
@@ -181,21 +177,17 @@ void createTransGPencil(bContext *C, TransInfo *t)
unit_m3(smtx);
unit_m3(mtx);
- /* Second Pass: Build transdata array */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* Second Pass: Build transdata array. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps;
float diff_mat[4][4];
float inverse_diff_mat[4][4];
- bGPDframe *init_gpf = gpl->actframe;
- if (is_multiedit) {
- init_gpf = gpl->frames.first;
- }
- /* init multiframe falloff options */
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+ /* Init multiframe falloff options. */
int f_init = 0;
int f_end = 0;
@@ -203,9 +195,9 @@ void createTransGPencil(bContext *C, TransInfo *t)
BKE_gpencil_frame_range_selected(gpl, &f_init, &f_end);
}
- /* calculate difference matrix */
+ /* Calculate difference matrix. */
BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat);
- /* undo matrix */
+ /* Undo matrix. */
invert_m4_m4(inverse_diff_mat, diff_mat);
/* Make a new frame to work on if the layer's frame
@@ -214,7 +206,6 @@ void createTransGPencil(bContext *C, TransInfo *t)
* - This is useful when animating as it saves that "uh-oh" moment when you realize you've
* spent too much time editing the wrong frame...
*/
- // XXX: should this be allowed when framelock is enabled?
if ((gpf->framenum != cfra) && (!is_multiedit)) {
gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
/* in some weird situations (framelock enabled) return NULL */
@@ -239,7 +230,7 @@ void createTransGPencil(bContext *C, TransInfo *t)
gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
}
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
TransData *head = td;
TransData *tail = td;
bool stroke_ok;
@@ -286,20 +277,20 @@ void createTransGPencil(bContext *C, TransInfo *t)
/* include point? */
if (is_prop_edit) {
- /* Always all points in strokes that get included */
+ /* Always all points in strokes that get included. */
point_ok = true;
}
else {
- /* Only selected points in selected strokes */
+ /* Only selected points in selected strokes. */
point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
}
/* do point... */
if (point_ok) {
copy_v3_v3(td->iloc, &pt->x);
- /* only copy center in local origins.
+ /* Only copy center in local origins.
* This allows get interesting effects also when move
- * using proportional editing */
+ * using proportional editing. */
if ((gps->flag & GP_STROKE_SELECT) &&
(ts->transform_pivot_point == V3D_AROUND_LOCAL_ORIGINS)) {
copy_v3_v3(td->center, center);
@@ -316,8 +307,8 @@ void createTransGPencil(bContext *C, TransInfo *t)
td->flag |= TD_SELECTED;
}
- /* for other transform modes (e.g. shrink-fatten), need to additional data
- * but never for mirror
+ /* For other transform modes (e.g. shrink-fatten), need to additional data
+ * but never for mirror.
*/
if (t->mode != TFM_MIRROR) {
if (t->mode != TFM_GPENCIL_OPACITY) {
@@ -363,7 +354,6 @@ void createTransGPencil(bContext *C, TransInfo *t)
/* March over these points, and calculate the proportional editing distances */
if (is_prop_edit && (head != tail)) {
- /* XXX: for now, we are similar enough that this works... */
calc_distanceCurveVerts(head, tail - 1);
}
}
diff --git a/source/blender/editors/transform/transform_convert_particle.c b/source/blender/editors/transform/transform_convert_particle.c
index 5feaa70ba19..3fa722d14cf 100644
--- a/source/blender/editors/transform/transform_convert_particle.c
+++ b/source/blender/editors/transform/transform_convert_particle.c
@@ -250,7 +250,7 @@ static void flushTransParticles(TransInfo *t)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Recalc Trasform Particles Data
+/** \name Recalc Transform Particles Data
*
* \{ */
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index c6d7b92fb42..4f942221f79 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -634,12 +634,15 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
t->scene, 0, t->region, t->view);
- ED_transform_snap_object_context_set_editmesh_callbacks(
- t->tsnap.object_context,
- (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
- bm_edge_is_snap_target,
- bm_face_is_snap_target,
- POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
+ if (t->data_type == TC_MESH_VERTS) {
+ /* Ignore elements being transformed. */
+ ED_transform_snap_object_context_set_editmesh_callbacks(
+ t->tsnap.object_context,
+ (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
+ bm_edge_is_snap_target,
+ bm_face_is_snap_target,
+ POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
+ }
}
}
}
diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh
index d580ce54f1d..1dc72e16e77 100644
--- a/source/blender/functions/FN_cpp_type.hh
+++ b/source/blender/functions/FN_cpp_type.hh
@@ -70,6 +70,7 @@
#include "BLI_math_base.h"
#include "BLI_string_ref.hh"
+namespace blender {
namespace FN {
using blender::IndexMask;
@@ -211,7 +212,7 @@ class CPPType {
}
/**
- * Returns true, when the given pointer fullfills the alignment requirement of this type.
+ * Returns true, when the given pointer fulfills the alignment requirement of this type.
*/
bool pointer_has_valid_alignment(const void *ptr) const
{
@@ -719,13 +720,14 @@ static std::unique_ptr<const CPPType> create_cpp_type(StringRef name, const T &d
}
} // namespace FN
+} // namespace blender
#define MAKE_CPP_TYPE(IDENTIFIER, TYPE_NAME) \
static TYPE_NAME default_value_##IDENTIFIER; \
- static std::unique_ptr<const FN::CPPType> CPPTYPE_##IDENTIFIER##_owner = \
- FN::create_cpp_type<TYPE_NAME>(STRINGIFY(IDENTIFIER), default_value_##IDENTIFIER); \
- const FN::CPPType &CPPType_##IDENTIFIER = *CPPTYPE_##IDENTIFIER##_owner; \
- template<> const FN::CPPType &FN::CPPType::get<TYPE_NAME>() \
+ static std::unique_ptr<const blender::FN::CPPType> CPPTYPE_##IDENTIFIER##_owner = \
+ blender::FN::create_cpp_type<TYPE_NAME>(STRINGIFY(IDENTIFIER), default_value_##IDENTIFIER); \
+ const blender::FN::CPPType &CPPType_##IDENTIFIER = *CPPTYPE_##IDENTIFIER##_owner; \
+ template<> const blender::FN::CPPType &blender::FN::CPPType::get<TYPE_NAME>() \
{ \
return CPPType_##IDENTIFIER; \
}
diff --git a/source/blender/functions/FN_cpp_types.hh b/source/blender/functions/FN_cpp_types.hh
index eceb43beb9d..6ee8788cd52 100644
--- a/source/blender/functions/FN_cpp_types.hh
+++ b/source/blender/functions/FN_cpp_types.hh
@@ -26,6 +26,7 @@
#include "FN_cpp_type.hh"
+namespace blender {
namespace FN {
extern const CPPType &CPPType_bool;
@@ -44,5 +45,6 @@ extern const CPPType &CPPType_Color4b;
extern const CPPType &CPPType_string;
} // namespace FN
+} // namespace blender
#endif /* __FN_CPP_TYPES_HH__ */
diff --git a/source/blender/functions/intern/cpp_types.cc b/source/blender/functions/intern/cpp_types.cc
index 6e548d65192..6339250caa5 100644
--- a/source/blender/functions/intern/cpp_types.cc
+++ b/source/blender/functions/intern/cpp_types.cc
@@ -21,6 +21,7 @@
#include "BLI_float3.hh"
#include "BLI_float4x4.hh"
+namespace blender {
namespace FN {
MAKE_CPP_TYPE(bool, bool)
@@ -39,3 +40,4 @@ MAKE_CPP_TYPE(Color4b, blender::Color4b)
MAKE_CPP_TYPE(string, std::string)
} // namespace FN
+} // namespace blender
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index 2d5e01ced94..776e5521179 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -36,10 +36,10 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_armature.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_lattice.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -69,39 +69,34 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
static void gpencil_deform_verts(ArmatureGpencilModifierData *mmd, Object *target, bGPDstroke *gps)
{
bGPDspoint *pt = gps->points;
- float *all_vert_coords = MEM_callocN(sizeof(float) * 3 * gps->totpoints, __func__);
+ float(*vert_coords)[3] = MEM_mallocN(sizeof(float[3]) * gps->totpoints, __func__);
int i;
BKE_gpencil_dvert_ensure(gps);
/* prepare array of points */
for (i = 0; i < gps->totpoints; i++, pt++) {
- float *pt_coords = &all_vert_coords[3 * i];
- float co[3];
- copy_v3_v3(co, &pt->x);
- copy_v3_v3(pt_coords, co);
+ copy_v3_v3(vert_coords[i], &pt->x);
}
/* deform verts */
- armature_deform_verts(mmd->object,
- target,
- NULL,
- (float(*)[3])all_vert_coords,
- NULL,
- gps->totpoints,
- mmd->deformflag,
- (float(*)[3])mmd->prevCos,
- mmd->vgname,
- gps);
+ BKE_armature_deform_coords_with_gpencil_stroke(mmd->object,
+ target,
+ vert_coords,
+ NULL,
+ gps->totpoints,
+ mmd->deformflag,
+ mmd->vert_coords_prev,
+ mmd->vgname,
+ gps);
/* Apply deformed coordinates */
pt = gps->points;
for (i = 0; i < gps->totpoints; i++, pt++) {
- float *pt_coords = &all_vert_coords[3 * i];
- copy_v3_v3(&pt->x, pt_coords);
+ copy_v3_v3(&pt->x, vert_coords[i]);
}
- MEM_SAFE_FREE(all_vert_coords);
+ MEM_freeN(vert_coords);
}
/* deform stroke */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index 5d5d673ca55..92b35f390f8 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -105,7 +105,8 @@ static void deformStroke(GpencilModifierData *md,
if (weight < 0.0f) {
continue;
}
- calc_latt_deform((struct LatticeDeformData *)mmd->cache_data, &pt->x, mmd->strength * weight);
+ BKE_lattice_deform_data_eval_co(
+ (struct LatticeDeformData *)mmd->cache_data, &pt->x, mmd->strength * weight);
}
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gps);
@@ -147,7 +148,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
/* free lingering data */
ldata = (struct LatticeDeformData *)mmd->cache_data;
if (ldata) {
- end_latt_deform(ldata);
+ BKE_lattice_deform_data_destroy(ldata);
mmd->cache_data = NULL;
}
@@ -162,7 +163,7 @@ static void freeData(GpencilModifierData *md)
struct LatticeDeformData *ldata = (struct LatticeDeformData *)mmd->cache_data;
/* free deform data */
if (ldata) {
- end_latt_deform(ldata);
+ BKE_lattice_deform_data_destroy(ldata);
}
}
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 1c346217e9f..b03b0fc0b1e 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -912,6 +912,11 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf,
GPU_texture_orig_size_set(*tex, ibuf_intern->x, ibuf_intern->y);
+ if (textarget == GL_TEXTURE_1D_ARRAY) {
+ /* Special for tile mapping. */
+ GPU_texture_mipmap_mode(*tex, false, false);
+ }
+
return *tex;
#endif
return NULL;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 469abefca68..ab55fcfb1e0 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -304,7 +304,14 @@ void gpu_extensions_init(void)
}
}
- GG.glew_arb_base_instance_is_supported = GLEW_ARB_base_instance;
+ /* Limit support for GLEW_ARB_base_instance to OpenGL 4.0 and higher. NVIDIA Quadro FX 4800
+ * (TeraScale) report that they support GLEW_ARB_base_instance, but the driver does not support
+ * GLEW_ARB_draw_indirect as it has an OpenGL3 context what also matches the minimum needed
+ * requirements.
+ *
+ * We use it as a target for glMapBuffer(Range) what is part of the OpenGL 4 API. So better
+ * disable it when we don't have an OpenGL4 context (See T77657) */
+ GG.glew_arb_base_instance_is_supported = GLEW_ARB_base_instance && GLEW_VERSION_4_0;
GG.glew_arb_texture_cube_map_array_is_supported = GLEW_ARB_texture_cube_map_array;
gpu_detect_mip_render_workaround();
diff --git a/source/blender/io/alembic/intern/abc_writer_points.cc b/source/blender/io/alembic/intern/abc_writer_points.cc
index d45af2eed4c..ac663b62693 100644
--- a/source/blender/io/alembic/intern/abc_writer_points.cc
+++ b/source/blender/io/alembic/intern/abc_writer_points.cc
@@ -104,7 +104,7 @@ void AbcPointsWriter::do_write()
}
if (m_psys->lattice_deform_data) {
- end_latt_deform(m_psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(m_psys->lattice_deform_data);
m_psys->lattice_deform_data = NULL;
}
diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc
index 841501bcf42..61337beff20 100644
--- a/source/blender/io/usd/intern/usd_writer_mesh.cc
+++ b/source/blender/io/usd/intern/usd_writer_mesh.cc
@@ -335,6 +335,7 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context,
* which is why we always bind the first material to the entire mesh. See
* https://github.com/PixarAnimationStudios/USD/issues/542 for more info. */
bool mesh_material_bound = false;
+ pxr::UsdShadeMaterialBindingAPI material_binding_api(usd_mesh.GetPrim());
for (short mat_num = 0; mat_num < context.object->totcol; mat_num++) {
Material *material = BKE_object_material_get(context.object, mat_num + 1);
if (material == nullptr) {
@@ -342,7 +343,7 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context,
}
pxr::UsdShadeMaterial usd_material = ensure_usd_material(material);
- usd_material.Bind(usd_mesh.GetPrim());
+ material_binding_api.Bind(usd_material);
/* USD seems to support neither per-material nor per-face-group double-sidedness, so we just
* use the flag from the first non-empty material slot. */
@@ -378,9 +379,9 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context,
pxr::UsdShadeMaterial usd_material = ensure_usd_material(material);
pxr::TfToken material_name = usd_material.GetPath().GetNameToken();
- pxr::UsdShadeMaterialBindingAPI api = pxr::UsdShadeMaterialBindingAPI(usd_mesh);
- pxr::UsdGeomSubset usd_face_subset = api.CreateMaterialBindSubset(material_name, face_indices);
- usd_material.Bind(usd_face_subset.GetPrim());
+ pxr::UsdGeomSubset usd_face_subset = material_binding_api.CreateMaterialBindSubset(
+ material_name, face_indices);
+ pxr::UsdShadeMaterialBindingAPI(usd_face_subset.GetPrim()).Bind(usd_material);
}
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 265b16992d8..eb02352f49b 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -225,9 +225,6 @@ typedef struct IDOverrideLibrary {
/** List of IDOverrideProperty structs. */
ListBase properties;
- short flag;
- char _pad[6];
-
/* Read/write data. */
/* Temp ID storing extra override data (used for differential operations only currently).
* Always NULL outside of read/write context. */
@@ -236,10 +233,6 @@ typedef struct IDOverrideLibrary {
IDOverrideLibraryRuntime *runtime;
} IDOverrideLibrary;
-enum eOverrideLibrary_Flag {
- OVERRIDE_LIBRARY_AUTO = 1 << 0, /* Allow automatic generation of overriding rules. */
-};
-
/**
* About Unique identifier.
*
@@ -540,10 +533,6 @@ typedef enum ID_Type {
#define ID_IS_OVERRIDE_LIBRARY_TEMPLATE(_id) \
(((ID *)(_id))->override_library != NULL && ((ID *)(_id))->override_library->reference == NULL)
-#define ID_IS_OVERRIDE_LIBRARY_AUTO(_id) \
- (!ID_IS_LINKED((_id)) && ID_IS_OVERRIDE_LIBRARY((_id)) && \
- (((ID *)(_id))->override_library->flag & OVERRIDE_LIBRARY_AUTO))
-
/* Check whether datablock type is covered by copy-on-write. */
#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_PAL, ID_IM))
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 8f3a26cf9c0..9d9ee711339 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -109,8 +109,11 @@ typedef struct ClothSimSettings {
pressure=( (current_volume/target_volume) - 1 + uniform_pressure_force) *
pressure_factor */
float pressure_factor;
+ /* Density of the fluid inside or outside the object for use in the hydrostatic pressure
+ * gradient. */
+ float fluid_density;
short vgroup_pressure;
- char _pad7[2];
+ char _pad7[6];
/* XXX various hair stuff
* should really be separate, this struct is a horrible mess already
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 125423cd061..674999ab465 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -24,6 +24,8 @@
#include "DNA_defs.h"
#include "DNA_listBase.h"
+struct LatticeDeformData;
+
/* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE!
* (ONLY ADD NEW ITEMS AT THE END)
*/
@@ -445,8 +447,8 @@ typedef struct LatticeGpencilModifierData {
float strength;
/** Custom index for passes. */
int layer_pass;
- /** Runtime only (LatticeDeformData). */
- void *cache_data;
+ /** Runtime only. */
+ struct LatticeDeformData *cache_data;
} LatticeGpencilModifierData;
typedef enum eLatticeGpencil_Flag {
@@ -655,12 +657,12 @@ typedef enum eSmoothGpencil_Flag {
typedef struct ArmatureGpencilModifierData {
GpencilModifierData modifier;
- /** Deformflag replaces armature->deformflag. */
+ /** #eArmature_DeformFlag use instead of #bArmature.deformflag. */
short deformflag, multi;
int _pad;
struct Object *object;
- /** Stored input of previous modifier, for vertexgroup blending. */
- float *prevCos;
+ /** Stored input of previous modifier, for vertex-group blending. */
+ float (*vert_coords_prev)[3];
/** MAX_VGROUP_NAME. */
char vgname[64];
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index a2b96ac2772..1413db4baea 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -693,12 +693,12 @@ enum {
typedef struct ArmatureModifierData {
ModifierData modifier;
- /** Deformflag replaces armature->deformflag. */
+ /** #eArmature_DeformFlag use instead of #bArmature.deformflag. */
short deformflag, multi;
char _pad2[4];
struct Object *object;
- /** Stored input of previous modifier, for vertexgroup blending. */
- float *prevCos;
+ /** Stored input of previous modifier, for vertex-group blending. */
+ float (*vert_coords_prev)[3];
/** MAX_VGROUP_NAME. */
char defgrp_name[64];
} ArmatureModifierData;
diff --git a/source/blender/makesdna/DNA_pointcache_types.h b/source/blender/makesdna/DNA_pointcache_types.h
index fcdc22ca56d..3c7fc9031de 100644
--- a/source/blender/makesdna/DNA_pointcache_types.h
+++ b/source/blender/makesdna/DNA_pointcache_types.h
@@ -50,6 +50,7 @@ extern "C" {
#define BPHYS_TOT_DATA 8
#define BPHYS_EXTRA_FLUID_SPRINGS 1
+#define BPHYS_EXTRA_CLOTH_ACCELERATION 2
typedef struct PTCacheExtra {
struct PTCacheExtra *next, *prev;
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index e1e8d808c60..a07b8f81d96 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -265,7 +265,7 @@ typedef struct wmWindow {
short modalcursor;
/** Cursor grab mode. */
short grabcursor;
- /** Internal: tag this for extra mousemove event,
+ /** Internal: tag this for extra mouse-move event,
* makes cursors/buttons active on UI switching. */
char addmousemove;
char tag_cursor_refresh;
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 56e3cc3cc9e..50658ef412b 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -1441,7 +1441,6 @@ static void rna_def_ID_override_library_property(BlenderRNA *brna)
static void rna_def_ID_override_library(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
srna = RNA_def_struct(brna, "IDOverrideLibrary", NULL);
RNA_def_struct_ui_text(
@@ -1450,14 +1449,6 @@ static void rna_def_ID_override_library(BlenderRNA *brna)
RNA_def_pointer(
srna, "reference", "ID", "Reference ID", "Linked ID used as reference by this override");
- prop = RNA_def_boolean(
- srna,
- "auto_generate",
- true,
- "Auto Generate Override",
- "Automatically generate overriding operations by detecting changes in properties");
- RNA_def_property_boolean_sdna(prop, NULL, "flag", OVERRIDE_LIBRARY_AUTO);
-
RNA_def_collection(srna,
"properties",
"IDOverrideLibraryProperty",
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 70f219259ef..594b77ea1ad 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -975,8 +975,10 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_pressure_volume", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL);
- RNA_def_property_ui_text(
- prop, "Use Custom Volume", "Use the Volume parameter as the initial volume");
+ RNA_def_property_ui_text(prop,
+ "Use Custom Volume",
+ "Use the Target Volume parameter as the initial volume, instead "
+ "of calculating it from the mesh itself");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, 0, "rna_cloth_update");
@@ -984,10 +986,10 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "uniform_pressure_force");
RNA_def_property_range(prop, -10000.0f, 10000.0f);
RNA_def_property_float_default(prop, 0.0f);
- RNA_def_property_ui_text(
- prop,
- "Pressure",
- "The uniform pressure that is constantly applied to the mesh. Can be negative");
+ RNA_def_property_ui_text(prop,
+ "Pressure",
+ "The uniform pressure that is constantly applied to the mesh, in units "
+ "of Pressure Scale. Can be negative");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "target_volume", PROP_FLOAT, PROP_NONE);
@@ -997,14 +999,28 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop,
"Target Volume",
"The mesh volume where the inner/outer pressure will be the same. If "
- "set to zero the volume will not contribute to the total pressure");
+ "set to zero the change in volume will not affect pressure");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "pressure_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "pressure_factor");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_default(prop, 1.0f);
- RNA_def_property_ui_text(prop, "Pressure Scale", "Air pressure scaling factor");
+ RNA_def_property_ui_text(prop,
+ "Pressure Scale",
+ "Ambient pressure (kPa) that balances out between the inside and "
+ "outside of the object when it has the target volume");
+ RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+ prop = RNA_def_property(srna, "fluid_density", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "fluid_density");
+ RNA_def_property_ui_range(prop, -2.0f, 2.0f, 0.05f, 4);
+ RNA_def_property_ui_text(
+ prop,
+ "Fluid Density",
+ "Density (kg/l) of the fluid contained inside the object, used to create "
+ "a hydrostatic pressure gradient simulating the weight of the internal fluid, "
+ "or buoyancy from the surrounding fluid if negative");
RNA_def_property_update(prop, 0, "rna_cloth_update");
prop = RNA_def_property(srna, "vertex_group_pressure", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index a52811a9a9a..c707ad9b84e 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -76,6 +76,35 @@ static EnumPropertyItem rna_enum_gpencil_onion_modes_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem rna_enum_keyframe_type_items[] = {
+ {BEZT_KEYTYPE_KEYFRAME,
+ "KEYFRAME",
+ ICON_KEYTYPE_KEYFRAME_VEC,
+ "Keyframe",
+ "Normal keyframe - e.g. for key poses"},
+ {BEZT_KEYTYPE_BREAKDOWN,
+ "BREAKDOWN",
+ ICON_KEYTYPE_BREAKDOWN_VEC,
+ "Breakdown",
+ "A breakdown pose - e.g. for transitions between key poses"},
+ {BEZT_KEYTYPE_MOVEHOLD,
+ "MOVING_HOLD",
+ ICON_KEYTYPE_MOVING_HOLD_VEC,
+ "Moving Hold",
+ "A keyframe that is part of a moving hold"},
+ {BEZT_KEYTYPE_EXTREME,
+ "EXTREME",
+ ICON_KEYTYPE_EXTREME_VEC,
+ "Extreme",
+ "An 'extreme' pose, or some other purpose as needed"},
+ {BEZT_KEYTYPE_JITTER,
+ "JITTER",
+ ICON_KEYTYPE_JITTER_VEC,
+ "Jitter",
+ "A filler or baked keyframe for keying on ones, or some other purpose as needed"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static const EnumPropertyItem rna_enum_onion_keyframe_type_items[] = {
{-1, "ALL", ICON_ACTION, "All Types", "Include all Keyframe types"},
{BEZT_KEYTYPE_KEYFRAME,
@@ -1324,6 +1353,13 @@ static void rna_def_gpencil_frame(BlenderRNA *brna)
RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears");
+ prop = RNA_def_property(srna, "keyframe_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "key_type");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_enum_items(prop, rna_enum_keyframe_type_items);
+ RNA_def_property_ui_text(prop, "Keyframe Type", "Type of keyframe");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
/* Flags */
prop = RNA_def_property(srna, "is_edited", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index c5781175d65..093fd8b3bd5 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -1174,6 +1174,22 @@ void RNA_def_main_libraries(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "tag", "rna_Main_libraries_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a camera from the current blendfile");
+ parm = RNA_def_pointer(func, "library", "Library", "", "Library to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+ RNA_def_boolean(
+ func, "do_unlink", true, "", "Unlink all usages of this library before deleting it");
+ RNA_def_boolean(func,
+ "do_id_user",
+ true,
+ "",
+ "Decrement user counter of all datablocks used by this object");
+ RNA_def_boolean(
+ func, "do_ui_user", true, "", "Make sure interface does not reference this object");
}
void RNA_def_main_screens(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index ad8d6ac8b8a..0cc0680804e 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -34,9 +34,9 @@
#include "DNA_screen_types.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_mesh.h"
@@ -74,7 +74,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
ArmatureModifierData *tamd = (ArmatureModifierData *)target;
BKE_modifier_copydata_generic(md, target, flag);
- tamd->prevCos = NULL;
+ tamd->vert_coords_prev = NULL;
}
static void requiredDataMask(Object *UNUSED(ob),
@@ -146,88 +146,64 @@ static void deformVerts(ModifierData *md,
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
- armature_deform_verts(amd->object,
- ctx->object,
- mesh,
- vertexCos,
- NULL,
- numVerts,
- amd->deformflag,
- (float(*)[3])amd->prevCos,
- amd->defgrp_name,
- NULL);
+ BKE_armature_deform_coords_with_mesh(amd->object,
+ ctx->object,
+ vertexCos,
+ NULL,
+ numVerts,
+ amd->deformflag,
+ amd->vert_coords_prev,
+ amd->defgrp_name,
+ mesh);
/* free cache */
- if (amd->prevCos) {
- MEM_freeN(amd->prevCos);
- amd->prevCos = NULL;
- }
+ MEM_SAFE_FREE(amd->vert_coords_prev);
}
static void deformVertsEM(ModifierData *md,
const ModifierEvalContext *ctx,
struct BMEditMesh *em,
- Mesh *mesh,
+ Mesh *UNUSED(mesh),
float (*vertexCos)[3],
int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData *)md;
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
-
- /* TODO(Campbell): use edit-mode data only (remove this line). */
- if (mesh_src != NULL) {
- BKE_mesh_wrapper_ensure_mdata(mesh_src);
- }
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
- armature_deform_verts(amd->object,
- ctx->object,
- mesh_src,
- vertexCos,
- NULL,
- numVerts,
- amd->deformflag,
- (float(*)[3])amd->prevCos,
- amd->defgrp_name,
- NULL);
+ BKE_armature_deform_coords_with_editmesh(amd->object,
+ ctx->object,
+ vertexCos,
+ NULL,
+ numVerts,
+ amd->deformflag,
+ amd->vert_coords_prev,
+ amd->defgrp_name,
+ em);
/* free cache */
- if (amd->prevCos) {
- MEM_freeN(amd->prevCos);
- amd->prevCos = NULL;
- }
-
- if (mesh_src != mesh) {
- BKE_id_free(NULL, mesh_src);
- }
+ MEM_SAFE_FREE(amd->vert_coords_prev);
}
static void deformMatricesEM(ModifierData *md,
const ModifierEvalContext *ctx,
struct BMEditMesh *em,
- Mesh *mesh,
+ Mesh *UNUSED(mesh),
float (*vertexCos)[3],
float (*defMats)[3][3],
int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData *)md;
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
-
- armature_deform_verts(amd->object,
- ctx->object,
- mesh_src,
- vertexCos,
- defMats,
- numVerts,
- amd->deformflag,
- NULL,
- amd->defgrp_name,
- NULL);
-
- if (mesh_src != mesh) {
- BKE_id_free(NULL, mesh_src);
- }
+
+ BKE_armature_deform_coords_with_editmesh(amd->object,
+ ctx->object,
+ vertexCos,
+ defMats,
+ numVerts,
+ amd->deformflag,
+ NULL,
+ amd->defgrp_name,
+ em);
}
static void deformMatrices(ModifierData *md,
@@ -240,16 +216,15 @@ static void deformMatrices(ModifierData *md,
ArmatureModifierData *amd = (ArmatureModifierData *)md;
Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
- armature_deform_verts(amd->object,
- ctx->object,
- mesh_src,
- vertexCos,
- defMats,
- numVerts,
- amd->deformflag,
- NULL,
- amd->defgrp_name,
- NULL);
+ BKE_armature_deform_coords_with_mesh(amd->object,
+ ctx->object,
+ vertexCos,
+ defMats,
+ numVerts,
+ amd->deformflag,
+ NULL,
+ amd->defgrp_name,
+ mesh_src);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index a2348539779..a13bb07f678 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -33,8 +33,9 @@
#include "DNA_screen_types.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_mesh.h"
@@ -129,16 +130,17 @@ static void deformVerts(ModifierData *md,
int defgrp_index = -1;
MOD_get_vgroup(ctx->object, mesh_src, cmd->name, &dvert, &defgrp_index);
- /* silly that defaxis and curve_deform_verts are off by 1
+ /* Silly that defaxis and BKE_curve_deform_coords are off by 1
* but leave for now to save having to call do_versions */
- curve_deform_verts(cmd->object,
- ctx->object,
- vertexCos,
- numVerts,
- dvert,
- defgrp_index,
- cmd->flag,
- cmd->defaxis - 1);
+
+ BKE_curve_deform_coords(cmd->object,
+ ctx->object,
+ vertexCos,
+ numVerts,
+ dvert,
+ defgrp_index,
+ cmd->flag,
+ cmd->defaxis - 1);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -147,22 +149,41 @@ static void deformVerts(ModifierData *md,
static void deformVertsEM(ModifierData *md,
const ModifierEvalContext *ctx,
- struct BMEditMesh *em,
- Mesh *mesh,
+ BMEditMesh *em,
+ Mesh *UNUSED(mesh),
float (*vertexCos)[3],
int numVerts)
{
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ CurveModifierData *cmd = (CurveModifierData *)md;
+ bool use_dverts = false;
+ int defgrp_index = -1;
- /* TODO(Campbell): use edit-mode data only (remove this line). */
- if (mesh_src != NULL) {
- BKE_mesh_wrapper_ensure_mdata(mesh_src);
+ if (ctx->object->type == OB_MESH && cmd->name[0] != '\0') {
+ defgrp_index = BKE_object_defgroup_name_index(ctx->object, cmd->name);
+ if (defgrp_index != -1) {
+ use_dverts = true;
+ }
}
- deformVerts(md, ctx, mesh_src, vertexCos, numVerts);
-
- if (!ELEM(mesh_src, NULL, mesh)) {
- BKE_id_free(NULL, mesh_src);
+ if (use_dverts) {
+ BKE_curve_deform_coords_with_editmesh(cmd->object,
+ ctx->object,
+ vertexCos,
+ numVerts,
+ defgrp_index,
+ cmd->flag,
+ cmd->defaxis - 1,
+ em);
+ }
+ else {
+ BKE_curve_deform_coords(cmd->object,
+ ctx->object,
+ vertexCos,
+ numVerts,
+ NULL,
+ defgrp_index,
+ cmd->flag,
+ cmd->defaxis - 1);
}
}
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 0c1eedd429a..f2e476f85aa 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -1115,7 +1115,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd,
explode->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
if (psmd->psys->lattice_deform_data) {
- end_latt_deform(psmd->psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psmd->psys->lattice_deform_data);
psmd->psys->lattice_deform_data = NULL;
}
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 4d96638fc83..574ea969be4 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -113,14 +113,14 @@ static void deformVerts(ModifierData *md,
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
- lattice_deform_verts(lmd->object,
- ctx->object,
- mesh_src,
- vertexCos,
- numVerts,
- lmd->flag,
- lmd->name,
- lmd->strength);
+ BKE_lattice_deform_coords_with_mesh(lmd->object,
+ ctx->object,
+ vertexCos,
+ numVerts,
+ lmd->flag,
+ lmd->name,
+ lmd->strength,
+ mesh_src);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -130,23 +130,16 @@ static void deformVerts(ModifierData *md,
static void deformVertsEM(ModifierData *md,
const ModifierEvalContext *ctx,
struct BMEditMesh *em,
- struct Mesh *mesh,
+ struct Mesh *UNUSED(mesh),
float (*vertexCos)[3],
int numVerts)
{
- struct Mesh *mesh_src = MOD_deform_mesh_eval_get(
- ctx->object, em, mesh, NULL, numVerts, false, false);
-
- /* TODO(Campbell): use edit-mode data only (remove this line). */
- if (mesh_src != NULL) {
- BKE_mesh_wrapper_ensure_mdata(mesh_src);
- }
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
- deformVerts(md, ctx, mesh_src, vertexCos, numVerts);
+ MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
- if (!ELEM(mesh_src, NULL, mesh)) {
- BKE_id_free(NULL, mesh_src);
- }
+ BKE_lattice_deform_coords_with_editmesh(
+ lmd->object, ctx->object, vertexCos, numVerts, lmd->flag, lmd->name, lmd->strength, em);
}
static void panel_draw(const bContext *C, Panel *panel)
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 0a9fb964281..62b28f22c17 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -542,7 +542,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 1aee545aa43..c6dff375109 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -169,12 +169,12 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd,
}
}
-void MOD_previous_vcos_store(ModifierData *md, float (*vertexCos)[3])
+void MOD_previous_vcos_store(ModifierData *md, const float (*vert_coords)[3])
{
while ((md = md->next) && md->type == eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
- if (amd->multi && amd->prevCos == NULL) {
- amd->prevCos = MEM_dupallocN(vertexCos);
+ if (amd->multi && amd->vert_coords_prev == NULL) {
+ amd->vert_coords_prev = MEM_dupallocN(vert_coords);
}
else {
break;
@@ -187,7 +187,7 @@ void MOD_previous_vcos_store(ModifierData *md, float (*vertexCos)[3])
Mesh *MOD_deform_mesh_eval_get(Object *ob,
struct BMEditMesh *em,
Mesh *mesh,
- float (*vertexCos)[3],
+ const float (*vertexCos)[3],
const int num_verts,
const bool use_normals,
const bool use_orco)
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
index 38e2083082d..a05e25d204c 100644
--- a/source/blender/modifiers/intern/MOD_util.h
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -40,12 +40,12 @@ void MOD_get_texture_coords(struct MappingInfoModifierData *dmd,
float (*cos)[3],
float (*r_texco)[3]);
-void MOD_previous_vcos_store(struct ModifierData *md, float (*vertexCos)[3]);
+void MOD_previous_vcos_store(struct ModifierData *md, const float (*vertexCos)[3]);
struct Mesh *MOD_deform_mesh_eval_get(struct Object *ob,
struct BMEditMesh *em,
struct Mesh *mesh,
- float (*vertexCos)[3],
+ const float (*vertexCos)[3],
const int num_verts,
const bool use_normals,
const bool use_orco);
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 6a951519730..18fab5215a6 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -72,12 +72,50 @@ static int cloth_count_nondiag_blocks(Cloth *cloth)
return nondiag;
}
+static bool cloth_get_pressure_weights(ClothModifierData *clmd,
+ const MVertTri *vt,
+ float *r_weights)
+{
+ /* We have custom vertex weights for pressure. */
+ if (clmd->sim_parms->vgroup_pressure > 0) {
+ Cloth *cloth = clmd->clothObject;
+ ClothVertex *verts = cloth->verts;
+
+ for (unsigned int j = 0; j < 3; j++) {
+ r_weights[j] = verts[vt->tri[j]].pressure_factor;
+
+ /* Skip the entire triangle if it has a zero weight. */
+ if (r_weights[j] == 0.0f) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static void cloth_calc_pressure_gradient(ClothModifierData *clmd,
+ const float gradient_vector[3],
+ float *r_vertex_pressure)
+{
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ unsigned int mvert_num = cloth->mvert_num;
+ float pt[3];
+
+ for (unsigned int i = 0; i < mvert_num; i++) {
+ BPH_mass_spring_get_position(data, i, pt);
+ r_vertex_pressure[i] = dot_v3v3(pt, gradient_vector);
+ }
+}
+
static float cloth_calc_volume(ClothModifierData *clmd)
{
/* Calculate the (closed) cloth volume. */
Cloth *cloth = clmd->clothObject;
const MVertTri *tri = cloth->tri;
Implicit_Data *data = cloth->implicit;
+ float weights[3] = {1.0f, 1.0f, 1.0f};
float vol = 0;
/* Early exit for hair, as it never has volume. */
@@ -85,38 +123,45 @@ static float cloth_calc_volume(ClothModifierData *clmd)
return 0.0f;
}
- if (clmd->sim_parms->vgroup_pressure > 0) {
- for (unsigned int i = 0; i < cloth->primitive_num; i++) {
- bool skip_face = false;
- /* We have custom vertex weights for pressure. */
- const MVertTri *vt = &tri[i];
- for (unsigned int j = 0; j < 3; j++) {
- /* If any weight is zero, don't take this face into account for volume calculation. */
- ClothVertex *verts = clmd->clothObject->verts;
-
- if (verts[vt->tri[j]].pressure_factor == 0.0f) {
- skip_face = true;
- }
- }
- if (skip_face) {
- continue;
- }
+ for (unsigned int i = 0; i < cloth->primitive_num; i++) {
+ const MVertTri *vt = &tri[i];
+ if (cloth_get_pressure_weights(clmd, vt, weights)) {
vol += BPH_tri_tetra_volume_signed_6x(data, vt->tri[0], vt->tri[1], vt->tri[2]);
}
}
- else {
- for (unsigned int i = 0; i < cloth->primitive_num; i++) {
- const MVertTri *vt = &tri[i];
- vol += BPH_tri_tetra_volume_signed_6x(data, vt->tri[0], vt->tri[1], vt->tri[2]);
- }
- }
+
/* We need to divide by 6 to get the actual volume. */
vol = vol / 6.0f;
return vol;
}
+static float cloth_calc_average_pressure(ClothModifierData *clmd, const float *vertex_pressure)
+{
+ Cloth *cloth = clmd->clothObject;
+ const MVertTri *tri = cloth->tri;
+ Implicit_Data *data = cloth->implicit;
+ float weights[3] = {1.0f, 1.0f, 1.0f};
+ float total_force = 0;
+ float total_area = 0;
+
+ for (unsigned int i = 0; i < cloth->primitive_num; i++) {
+ const MVertTri *vt = &tri[i];
+
+ if (cloth_get_pressure_weights(clmd, vt, weights)) {
+ float area = BPH_tri_area(data, vt->tri[0], vt->tri[1], vt->tri[2]);
+
+ total_force += (vertex_pressure[vt->tri[0]] + vertex_pressure[vt->tri[1]] +
+ vertex_pressure[vt->tri[2]]) *
+ area / 3.0f;
+ total_area += area;
+ }
+ }
+
+ return total_force / total_area;
+}
+
int BPH_cloth_solver_init(Object *UNUSED(ob), ClothModifierData *clmd)
{
Cloth *cloth = clmd->clothObject;
@@ -554,6 +599,7 @@ static void cloth_calc_force(
if ((parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE) && (clmd->hairdata == NULL)) {
/* The difference in pressure between the inside and outside of the mesh.*/
float pressure_difference = 0.0f;
+ float volume_factor = 1.0f;
float init_vol;
if (parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL) {
@@ -568,59 +614,71 @@ static void cloth_calc_force(
float f;
float vol = cloth_calc_volume(clmd);
+ /* If the volume is the same don't apply any pressure. */
+ volume_factor = init_vol / vol;
+ pressure_difference = volume_factor - 1;
+
/* Calculate an artificial maximum value for cloth pressure. */
f = fabs(clmd->sim_parms->uniform_pressure_force) + 200.0f;
/* Clamp the cloth pressure to the calculated maximum value. */
- if (vol * f < init_vol) {
- pressure_difference = f;
- }
- else {
- /* If the volume is the same don't apply any pressure. */
- pressure_difference = (init_vol / vol) - 1;
- }
+ CLAMP_MAX(pressure_difference, f);
}
- pressure_difference += clmd->sim_parms->uniform_pressure_force;
+ pressure_difference += clmd->sim_parms->uniform_pressure_force;
pressure_difference *= clmd->sim_parms->pressure_factor;
- for (i = 0; i < cloth->primitive_num; i++) {
- const MVertTri *vt = &tri[i];
- if (fabs(pressure_difference) > 1E-6f) {
- if (clmd->sim_parms->vgroup_pressure > 0) {
- /* We have custom vertex weights for pressure. */
- ClothVertex *verts = clmd->clothObject->verts;
- int v1, v2, v3;
- v1 = vt->tri[0];
- v2 = vt->tri[1];
- v3 = vt->tri[2];
-
- float weights[3];
- bool skip_face = false;
-
- weights[0] = verts[v1].pressure_factor;
- weights[1] = verts[v2].pressure_factor;
- weights[2] = verts[v3].pressure_factor;
- for (unsigned int j = 0; j < 3; j++) {
- if (weights[j] == 0.0f) {
- /* Exclude faces which has a zero weight vert. */
- skip_face = true;
- break;
- }
- }
- if (skip_face) {
- continue;
- }
+ /* Compute the hydrostatic pressure gradient if enabled. */
+ float fluid_density = clmd->sim_parms->fluid_density * 1000; /* kg/l -> kg/m3 */
+ float *hydrostatic_pressure = NULL;
- BPH_mass_spring_force_pressure(data, v1, v2, v3, pressure_difference, weights);
- }
- else {
- float weights[3] = {1.0f, 1.0f, 1.0f};
- BPH_mass_spring_force_pressure(
- data, vt->tri[0], vt->tri[1], vt->tri[2], pressure_difference, weights);
+ if (fabs(fluid_density) > 1e-6f) {
+ float hydrostatic_vector[3];
+ copy_v3_v3(hydrostatic_vector, gravity);
+
+ /* When the fluid is inside the object, factor in the acceleration of
+ * the object into the pressure field, as gravity is indistinguishable
+ * from acceleration from the inside. */
+ if (fluid_density > 0) {
+ sub_v3_v3(hydrostatic_vector, cloth->average_acceleration);
+
+ /* Preserve the total mass by scaling density to match the change in volume. */
+ fluid_density *= volume_factor;
+ }
+
+ mul_v3_fl(hydrostatic_vector, fluid_density);
+
+ /* Compute an array of per-vertex hydrostatic pressure, and subtract the average. */
+ hydrostatic_pressure = (float *)MEM_mallocN(sizeof(float) * mvert_num,
+ "hydrostatic pressure gradient");
+
+ cloth_calc_pressure_gradient(clmd, hydrostatic_vector, hydrostatic_pressure);
+
+ pressure_difference -= cloth_calc_average_pressure(clmd, hydrostatic_pressure);
+ }
+
+ /* Apply pressure. */
+ if (hydrostatic_pressure || fabs(pressure_difference) > 1E-6f) {
+ float weights[3] = {1.0f, 1.0f, 1.0f};
+
+ for (i = 0; i < cloth->primitive_num; i++) {
+ const MVertTri *vt = &tri[i];
+
+ if (cloth_get_pressure_weights(clmd, vt, weights)) {
+ BPH_mass_spring_force_pressure(data,
+ vt->tri[0],
+ vt->tri[1],
+ vt->tri[2],
+ pressure_difference,
+ hydrostatic_pressure,
+ weights);
}
}
}
+
+ if (hydrostatic_pressure) {
+ MEM_freeN(hydrostatic_pressure);
+ }
}
/* handle external forces like wind */
@@ -1032,6 +1090,30 @@ static void cloth_calc_volume_force(ClothModifierData *clmd)
}
#endif
+static void cloth_calc_average_acceleration(ClothModifierData *clmd, float dt)
+{
+ Cloth *cloth = clmd->clothObject;
+ Implicit_Data *data = cloth->implicit;
+ int i, mvert_num = cloth->mvert_num;
+ float total[3] = {0.0f, 0.0f, 0.0f};
+
+ for (i = 0; i < mvert_num; i++) {
+ float v[3], nv[3];
+
+ BPH_mass_spring_get_velocity(data, i, v);
+ BPH_mass_spring_get_new_velocity(data, i, nv);
+
+ sub_v3_v3(nv, v);
+ add_v3_v3(total, nv);
+ }
+
+ mul_v3_fl(total, 1.0f / dt / mvert_num);
+
+ /* Smooth the data using a running average to prevent instability.
+ * This is effectively an abstraction of the wave propagation speed in fluid. */
+ interp_v3_v3v3(cloth->average_acceleration, total, cloth->average_acceleration, powf(0.25f, dt));
+}
+
static void cloth_solve_collisions(
Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, float step, float dt)
{
@@ -1136,6 +1218,10 @@ int BPH_cloth_solve(
float dt = clmd->sim_parms->dt * clmd->sim_parms->timescale;
Implicit_Data *id = cloth->implicit;
+ /* Hydrostatic pressure gradient of the fluid inside the object is affected by acceleration. */
+ bool use_acceleration = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE) &&
+ (clmd->sim_parms->fluid_density > 0);
+
BKE_sim_debug_data_clear_category("collision");
if (!clmd->solver_result) {
@@ -1158,6 +1244,10 @@ int BPH_cloth_solve(
}
}
+ if (!use_acceleration) {
+ zero_v3(cloth->average_acceleration);
+ }
+
while (step < tf) {
ImplicitSolverResult result;
@@ -1181,6 +1271,10 @@ int BPH_cloth_solve(
cloth_continuum_step(clmd, dt);
}
+ if (use_acceleration) {
+ cloth_calc_average_acceleration(clmd, dt);
+ }
+
BPH_mass_spring_solve_positions(id, dt);
BPH_mass_spring_apply_result(id);
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
index 490e727b5f2..69b50f7fa48 100644
--- a/source/blender/physics/intern/implicit.h
+++ b/source/blender/physics/intern/implicit.h
@@ -79,6 +79,7 @@ void BPH_mass_spring_get_motion_state(struct Implicit_Data *data,
float x[3],
float v[3]);
void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x[3]);
+void BPH_mass_spring_get_velocity(struct Implicit_Data *data, int index, float v[3]);
/* access to modified motion state during solver step */
void BPH_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3]);
@@ -183,13 +184,15 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data,
float damping);
float BPH_tri_tetra_volume_signed_6x(struct Implicit_Data *data, int v1, int v2, int v3);
+float BPH_tri_area(struct Implicit_Data *data, int v1, int v2, int v3);
void BPH_mass_spring_force_pressure(struct Implicit_Data *data,
int v1,
int v2,
int v3,
- float pressure_difference,
- float weights[3]);
+ float common_pressure,
+ const float *vertex_pressure,
+ const float weights[3]);
/* ======== Hair Volumetric Forces ======== */
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index b1afaa52ef2..063c224f158 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -1246,6 +1246,11 @@ void BPH_mass_spring_get_position(struct Implicit_Data *data, int index, float x
root_to_world_v3(data, index, x, data->X[index]);
}
+void BPH_mass_spring_get_velocity(struct Implicit_Data *data, int index, float v[3])
+{
+ root_to_world_v3(data, index, v, data->V[index]);
+}
+
void BPH_mass_spring_get_new_position(struct Implicit_Data *data, int index, float x[3])
{
root_to_world_v3(data, index, x, data->Xnew[index]);
@@ -1488,21 +1493,54 @@ float BPH_tri_tetra_volume_signed_6x(Implicit_Data *data, int v1, int v2, int v3
return volume_tri_tetrahedron_signed_v3_6x(data->X[v1], data->X[v2], data->X[v3]);
}
-void BPH_mass_spring_force_pressure(
- Implicit_Data *data, int v1, int v2, int v3, float pressure_difference, float weights[3])
+float BPH_tri_area(struct Implicit_Data *data, int v1, int v2, int v3)
+{
+ float nor[3];
+
+ return calc_nor_area_tri(nor, data->X[v1], data->X[v2], data->X[v3]);
+}
+
+void BPH_mass_spring_force_pressure(Implicit_Data *data,
+ int v1,
+ int v2,
+ int v3,
+ float common_pressure,
+ const float *vertex_pressure,
+ const float weights[3])
{
float nor[3], area;
- float factor;
+ float factor, base_force;
+ float force[3];
/* calculate face normal and area */
area = calc_nor_area_tri(nor, data->X[v1], data->X[v2], data->X[v3]);
/* The force is calculated and split up evenly for each of the three face verts */
- factor = pressure_difference * area / 3.0f;
+ factor = area / 3.0f;
+ base_force = common_pressure * factor;
+
+ /* Compute per-vertex force values from local pressures.
+ * From integrating the pressure over the triangle and deriving
+ * equivalent vertex forces, it follows that:
+ *
+ * force[idx] = (sum(pressure) + pressure[idx]) * area / 12
+ *
+ * Effectively, 1/4 of the pressure acts just on its vertex,
+ * while 3/4 is split evenly over all three.
+ */
+ if (vertex_pressure) {
+ copy_v3_fl3(force, vertex_pressure[v1], vertex_pressure[v2], vertex_pressure[v3]);
+ mul_v3_fl(force, factor / 4.0f);
+
+ base_force += force[0] + force[1] + force[2];
+ }
+ else {
+ zero_v3(force);
+ }
/* add pressure to each of the face verts */
- madd_v3_v3fl(data->F[v1], nor, factor * weights[0]);
- madd_v3_v3fl(data->F[v2], nor, factor * weights[1]);
- madd_v3_v3fl(data->F[v3], nor, factor * weights[2]);
+ madd_v3_v3fl(data->F[v1], nor, (base_force + force[0]) * weights[0]);
+ madd_v3_v3fl(data->F[v2], nor, (base_force + force[1]) * weights[1]);
+ madd_v3_v3fl(data->F[v3], nor, (base_force + force[2]) * weights[2]);
}
static void edge_wind_vertex(const float dir[3],
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index edade21fd27..8daad33b477 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -274,7 +274,7 @@ static void pointdensity_cache_psys(
BLI_bvhtree_balance(pd->point_tree);
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
}
@@ -823,7 +823,7 @@ static void particle_system_minmax(Depsgraph *depsgraph,
}
if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
psys->lattice_deform_data = NULL;
}
}
diff --git a/tests/gtests/blenlib/BLI_map_test.cc b/tests/gtests/blenlib/BLI_map_test.cc
index 623055d5032..96e9879abe7 100644
--- a/tests/gtests/blenlib/BLI_map_test.cc
+++ b/tests/gtests/blenlib/BLI_map_test.cc
@@ -449,6 +449,15 @@ TEST(map, PointerKeys)
EXPECT_TRUE(map.is_empty());
}
+TEST(map, ConstKeysAndValues)
+{
+ Map<const std::string, const std::string> map;
+ map.reserve(10);
+ map.add("45", "643");
+ EXPECT_TRUE(map.contains("45"));
+ EXPECT_FALSE(map.contains("54"));
+}
+
/**
* Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
*/
diff --git a/tests/gtests/blenlib/BLI_set_test.cc b/tests/gtests/blenlib/BLI_set_test.cc
index 8e77a446a97..2387242c94b 100644
--- a/tests/gtests/blenlib/BLI_set_test.cc
+++ b/tests/gtests/blenlib/BLI_set_test.cc
@@ -9,7 +9,7 @@
#include "BLI_vector.hh"
#include "testing/testing.h"
-using namespace blender;
+namespace blender {
TEST(set, DefaultConstructor)
{
@@ -290,7 +290,7 @@ bool operator==(const Type2 &a, const Type1 &b)
return a.value == b.value;
}
-template<> struct blender::DefaultHash<Type1> {
+template<> struct DefaultHash<Type1> {
uint32_t operator()(const Type1 &value) const
{
return value.value;
@@ -511,3 +511,5 @@ TEST(set, Benchmark)
*/
#endif /* Benchmark */
+
+} // namespace blender
diff --git a/tests/gtests/functions/FN_cpp_type_test.cc b/tests/gtests/functions/FN_cpp_type_test.cc
index ca8583bdc92..811e1a5d783 100644
--- a/tests/gtests/functions/FN_cpp_type_test.cc
+++ b/tests/gtests/functions/FN_cpp_type_test.cc
@@ -19,6 +19,9 @@
#include "FN_cpp_type.hh"
+namespace blender {
+namespace FN {
+
static const int default_constructed_value = 1;
static const int copy_constructed_value = 2;
static const int move_constructed_value = 3;
@@ -297,3 +300,6 @@ TEST(cpp_type, FillUninitialized)
EXPECT_EQ(buffer2[8], copy_constructed_value);
EXPECT_EQ(buffer2[9], 0);
}
+
+} // namespace FN
+} // namespace blender