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--build_files/build_environment/CMakeLists.txt3
-rw-r--r--build_files/build_environment/cmake/boost.cmake29
-rw-r--r--build_files/build_environment/cmake/options.cmake13
-rw-r--r--build_files/build_environment/cmake/python.cmake2
-rwxr-xr-xbuild_files/build_environment/install_deps.sh2
-rw-r--r--build_files/build_environment/patches/boost.user.jam.in4
-rw-r--r--build_files/cmake/Modules/FindAlembic.cmake8
-rw-r--r--build_files/cmake/Modules/FindAudaspace.cmake7
-rw-r--r--build_files/cmake/Modules/FindBlosc.cmake8
-rw-r--r--build_files/cmake/Modules/FindClangTidy.cmake8
-rw-r--r--build_files/cmake/Modules/FindEigen3.cmake8
-rw-r--r--build_files/cmake/Modules/FindEmbree.cmake8
-rw-r--r--build_files/cmake/Modules/FindFftw3.cmake8
-rw-r--r--build_files/cmake/Modules/FindGLEW.cmake8
-rw-r--r--build_files/cmake/Modules/FindGMP.cmake8
-rw-r--r--build_files/cmake/Modules/FindIcuLinux.cmake8
-rw-r--r--build_files/cmake/Modules/FindJack.cmake8
-rw-r--r--build_files/cmake/Modules/FindJeMalloc.cmake8
-rw-r--r--build_files/cmake/Modules/FindLLVM.cmake8
-rw-r--r--build_files/cmake/Modules/FindLZO.cmake8
-rw-r--r--build_files/cmake/Modules/FindOSL.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenCOLLADA.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenColorIO.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenEXR.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenGLES.cmake7
-rw-r--r--build_files/cmake/Modules/FindOpenImageDenoise.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenImageIO.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenJPEG.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenSubdiv.cmake8
-rw-r--r--build_files/cmake/Modules/FindOpenVDB.cmake8
-rw-r--r--build_files/cmake/Modules/FindOptiX.cmake8
-rw-r--r--build_files/cmake/Modules/FindPCRE.cmake8
-rw-r--r--build_files/cmake/Modules/FindPugiXML.cmake8
-rw-r--r--build_files/cmake/Modules/FindPythonLibsUnix.cmake8
-rw-r--r--build_files/cmake/Modules/FindSDL2.cmake8
-rw-r--r--build_files/cmake/Modules/FindSndFile.cmake8
-rw-r--r--build_files/cmake/Modules/FindSpacenav.cmake8
-rw-r--r--build_files/cmake/Modules/FindTBB.cmake8
-rw-r--r--build_files/cmake/Modules/FindUSD.cmake8
-rw-r--r--build_files/cmake/Modules/FindXML2.cmake8
-rw-r--r--build_files/cmake/Modules/FindXR_OpenXR_SDK.cmake8
-rw-r--r--build_files/cmake/Modules/GTest.cmake4
-rw-r--r--build_files/cmake/Modules/GTestAddTests.cmake4
-rw-r--r--build_files/cmake/Modules/GTestTesting.cmake8
-rw-r--r--doc/license/BSD-3-Clause-license.txt26
-rw-r--r--intern/cycles/render/geometry.cpp10
-rw-r--r--intern/cycles/render/image.cpp31
-rw-r--r--intern/cycles/render/image.h5
-rw-r--r--intern/cycles/render/image_vdb.cpp12
-rw-r--r--intern/cycles/render/image_vdb.h6
-rw-r--r--intern/cycles/render/mesh_volume.cpp514
-rw-r--r--intern/cycles/render/session.cpp9
-rw-r--r--intern/cycles/util/CMakeLists.txt1
-rw-r--r--intern/cycles/util/util_openvdb.h32
-rw-r--r--intern/guardedalloc/tests/guardedalloc_overflow_test.cc2
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py19
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py2
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py18
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h5
-rw-r--r--source/blender/blenkernel/BKE_gpencil_curve.h3
-rw-r--r--source/blender/blenkernel/BKE_subdiv_ccg.h3
-rw-r--r--source/blender/blenkernel/intern/bpath.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c6
-rw-r--r--source/blender/blenkernel/intern/collision.c171
-rw-r--r--source/blender/blenkernel/intern/gpencil.c109
-rw-r--r--source/blender/blenkernel/intern/gpencil_curve.c309
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c63
-rw-r--r--source/blender/blenkernel/intern/subdiv_deform.c2
-rw-r--r--source/blender/blenkernel/intern/subdiv_foreach.c2
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c2
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c2566
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc6
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c69
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c94
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h42
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c9
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_mesh.c16
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h2
-rw-r--r--source/blender/editors/animation/keyframing.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c32
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/interface/interface_anim.c3
-rw-r--r--source/blender/editors/interface/interface_panel.c28
-rw-r--r--source/blender/editors/interface/interface_templates.c9
-rw-r--r--source/blender/editors/object/object_add.c2
-rw-r--r--source/blender/editors/object/object_data_transfer.c2
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c18
-rw-r--r--source/blender/editors/object/object_intern.h4
-rw-r--r--source/blender/editors/object/object_modifier.c50
-rw-r--r--source/blender/editors/object/object_shader_fx.c15
-rw-r--r--source/blender/editors/screen/area.c48
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c149
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_boundary.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_detail.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c15
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c31
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mask.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c15
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_mask_expand.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_color.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_smooth.c10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_transform.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c96
-rw-r--r--source/blender/gpu/intern/gpu_context.cc8
-rw-r--r--source/blender/gpu/intern/gpu_texture.cc7
-rw-r--r--source/blender/makesdna/DNA_brush_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_brush.c1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c3
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c23
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c2
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c5
-rw-r--r--source/blender/windowmanager/intern/wm_keymap_utils.c5
122 files changed, 2738 insertions, 2433 deletions
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index c26b90637c3..6415d270773 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -57,7 +57,6 @@ include(cmake/zlib.cmake)
include(cmake/openal.cmake)
include(cmake/png.cmake)
include(cmake/jpeg.cmake)
-include(cmake/boost.cmake)
include(cmake/blosc.cmake)
include(cmake/pthreads.cmake)
include(cmake/openexr.cmake)
@@ -89,6 +88,8 @@ include(cmake/python_site_packages.cmake)
include(cmake/package_python.cmake)
include(cmake/numpy.cmake)
include(cmake/usd.cmake)
+# Boost needs to be included after python.cmake due to the PYTHON_BINARY variable being needed.
+include(cmake/boost.cmake)
if(UNIX)
# Rely on PugiXML compiled with OpenImageIO
else()
diff --git a/build_files/build_environment/cmake/boost.cmake b/build_files/build_environment/cmake/boost.cmake
index 6e7ee8c66b1..22b5f33e690 100644
--- a/build_files/build_environment/cmake/boost.cmake
+++ b/build_files/build_environment/cmake/boost.cmake
@@ -19,17 +19,6 @@
set(BOOST_ADDRESS_MODEL 64)
if(WIN32)
- if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
- set(PYTHON_ARCH x64)
- set(PYTHON_ARCH2 win-AMD64)
- set(PYTHON_OUTPUTDIR ${BUILD_DIR}/python/src/external_python/pcbuild/amd64/)
- else()
- set(PYTHON_ARCH x86)
- set(PYTHON_ARCH2 win32)
- set(PYTHON_OUTPUTDIR ${BUILD_DIR}/python/src/external_python/pcbuild/win32/)
- set(BOOST_ADDRESS_MODEL 32)
- endif()
-
set(BOOST_TOOLSET toolset=msvc-14.1)
set(BOOST_COMPILER_STRING -vc141)
@@ -60,6 +49,15 @@ else()
endif()
endif()
+if(WITH_BOOST_PYTHON)
+ set(JAM_FILE ${BUILD_DIR}/boost.user-config.jam)
+ configure_file(${PATCH_DIR}/boost.user.jam.in ${JAM_FILE})
+ set(BOOST_PYTHON_OPTIONS
+ --with-python
+ --user-config=${JAM_FILE}
+ )
+endif()
+
set(BOOST_OPTIONS
--with-filesystem
--with-locale
@@ -76,6 +74,7 @@ set(BOOST_OPTIONS
-sNO_LZMA=1
-sNO_ZSTD=1
${BOOST_TOOLSET}
+ ${BOOST_PYTHON_OPTIONS}
)
string(TOLOWER ${BUILD_MODE} BOOST_BUILD_TYPE)
@@ -92,3 +91,11 @@ ExternalProject_Add(external_boost
BUILD_IN_SOURCE 1
INSTALL_COMMAND "${BOOST_HARVEST_CMD}"
)
+
+if(WITH_BOOST_PYTHON)
+ add_dependencies(
+ external_boost
+ external_python
+ external_numpy
+ )
+endif()
diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake
index fe2f1fa34e5..29e2ffc7ed8 100644
--- a/build_files/build_environment/cmake/options.cmake
+++ b/build_files/build_environment/cmake/options.cmake
@@ -20,6 +20,7 @@ if(WIN32)
option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/fftw3 by installing mingw64" ON)
endif()
option(WITH_WEBP "Enable building of oiio with webp support" OFF)
+option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF)
set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
if(NOT BUILD_MODE)
@@ -195,18 +196,6 @@ set(DEFAULT_CMAKE_FLAGS
)
if(WIN32)
- # We need both flavors to build the thumbnail dlls
- if(MSVC12)
- set(GENERATOR_32 "Visual Studio 12 2013")
- set(GENERATOR_64 "Visual Studio 12 2013 Win64")
- elseif(MSVC14)
- set(GENERATOR_32 "Visual Studio 14 2015")
- set(GENERATOR_64 "Visual Studio 14 2015 Win64")
- endif()
-endif()
-
-
-if(WIN32)
if(BUILD_MODE STREQUAL Debug)
set(ZLIB_LIBRARY zlibstaticd${LIBEXT})
else()
diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake
index 9cd56423941..bfb318f9939 100644
--- a/build_files/build_environment/cmake/python.cmake
+++ b/build_files/build_environment/cmake/python.cmake
@@ -42,7 +42,7 @@ if(WIN32)
URL_HASH MD5=${PYTHON_HASH}
PREFIX ${BUILD_DIR}/python
CONFIGURE_COMMAND ""
- BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p ${PYTHON_ARCH} -c ${BUILD_MODE}
+ BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p x64 -c ${BUILD_MODE}
INSTALL_COMMAND ${PYTHON_BINARY_INTERNAL} ${PYTHON_SRC}/PC/layout/main.py -b ${PYTHON_SRC}/PCbuild/amd64 -s ${PYTHON_SRC} -t ${PYTHON_SRC}/tmp/ --include-underpth --include-stable --include-pip --include-dev --include-launchers --include-venv --include-symbols ${PYTHON_EXTRA_INSTLAL_FLAGS} --copy ${LIBDIR}/python
)
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 46f1694ed38..130173d7f01 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -433,7 +433,7 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="2.1.15"
+OIIO_VERSION="2.1.15.0"
OIIO_VERSION_SHORT="2.1"
OIIO_VERSION_MIN="1.8"
OIIO_VERSION_MAX="3.0"
diff --git a/build_files/build_environment/patches/boost.user.jam.in b/build_files/build_environment/patches/boost.user.jam.in
new file mode 100644
index 00000000000..b615b0cafad
--- /dev/null
+++ b/build_files/build_environment/patches/boost.user.jam.in
@@ -0,0 +1,4 @@
+using python : @PYTHON_SHORT_VERSION@ : @PYTHON_BINARY@
+ : @LIBDIR@/python/include @LIBDIR@/python/include/python@PYTHON_SHORT_VERSION@m/
+ : @LIBDIR@/python/libs
+; \ No newline at end of file
diff --git a/build_files/cmake/Modules/FindAlembic.cmake b/build_files/cmake/Modules/FindAlembic.cmake
index 45cda7ae2c5..aba91bb565d 100644
--- a/build_files/cmake/Modules/FindAlembic.cmake
+++ b/build_files/cmake/Modules/FindAlembic.cmake
@@ -12,12 +12,8 @@
#=============================================================================
# Copyright 2016 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If ALEMBIC_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindAudaspace.cmake b/build_files/cmake/Modules/FindAudaspace.cmake
index eeef49af60f..9bf15e05272 100644
--- a/build_files/cmake/Modules/FindAudaspace.cmake
+++ b/build_files/cmake/Modules/FindAudaspace.cmake
@@ -11,6 +11,13 @@
# AUDASPACE_PY_INCLUDE_DIRS - the audaspace's python binding include directories
# AUDASPACE_PY_LIBRARIES - link these to use audaspace's python binding
+#=============================================================================
+# Copyright 2014 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
+#=============================================================================
+
IF(NOT AUDASPACE_ROOT_DIR AND NOT $ENV{AUDASPACE_ROOT_DIR} STREQUAL "")
SET(AUDASPACE_ROOT_DIR $ENV{AUDASPACE_ROOT_DIR})
ENDIF()
diff --git a/build_files/cmake/Modules/FindBlosc.cmake b/build_files/cmake/Modules/FindBlosc.cmake
index e0baa2d3382..d1ac3002c59 100644
--- a/build_files/cmake/Modules/FindBlosc.cmake
+++ b/build_files/cmake/Modules/FindBlosc.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2018 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If BLOSC_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindClangTidy.cmake b/build_files/cmake/Modules/FindClangTidy.cmake
index f556d05a0b9..d576ad8f100 100644
--- a/build_files/cmake/Modules/FindClangTidy.cmake
+++ b/build_files/cmake/Modules/FindClangTidy.cmake
@@ -17,12 +17,8 @@
#=============================================================================
# Copyright 2020 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If CLANG_TIDY_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindEigen3.cmake b/build_files/cmake/Modules/FindEigen3.cmake
index 82261294df2..735f44a04db 100644
--- a/build_files/cmake/Modules/FindEigen3.cmake
+++ b/build_files/cmake/Modules/FindEigen3.cmake
@@ -10,12 +10,8 @@
#=============================================================================
# Copyright 2015 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If EIGEN3_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindEmbree.cmake b/build_files/cmake/Modules/FindEmbree.cmake
index 90cf23d3e13..ccd0d6cd40a 100644
--- a/build_files/cmake/Modules/FindEmbree.cmake
+++ b/build_files/cmake/Modules/FindEmbree.cmake
@@ -11,12 +11,8 @@
#=============================================================================
# Copyright 2018 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If EMBREE_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindFftw3.cmake b/build_files/cmake/Modules/FindFftw3.cmake
index 3da19290b0d..df69c0c2ed4 100644
--- a/build_files/cmake/Modules/FindFftw3.cmake
+++ b/build_files/cmake/Modules/FindFftw3.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If FFTW3_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindGLEW.cmake b/build_files/cmake/Modules/FindGLEW.cmake
index 390e3878d6a..059b1da005d 100644
--- a/build_files/cmake/Modules/FindGLEW.cmake
+++ b/build_files/cmake/Modules/FindGLEW.cmake
@@ -13,12 +13,8 @@
#=============================================================================
# Copyright 2014 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If GLEW_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindGMP.cmake b/build_files/cmake/Modules/FindGMP.cmake
index 4469f32c785..e1795984985 100644
--- a/build_files/cmake/Modules/FindGMP.cmake
+++ b/build_files/cmake/Modules/FindGMP.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If GMP_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindIcuLinux.cmake b/build_files/cmake/Modules/FindIcuLinux.cmake
index 9a467fa0115..e1aaa434533 100644
--- a/build_files/cmake/Modules/FindIcuLinux.cmake
+++ b/build_files/cmake/Modules/FindIcuLinux.cmake
@@ -12,12 +12,8 @@
#=============================================================================
# Copyright 2012 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If ICU_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindJack.cmake b/build_files/cmake/Modules/FindJack.cmake
index 7643e586cad..a790c127c09 100644
--- a/build_files/cmake/Modules/FindJack.cmake
+++ b/build_files/cmake/Modules/FindJack.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If JACK_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindJeMalloc.cmake b/build_files/cmake/Modules/FindJeMalloc.cmake
index e042e7fe43e..72a0bed6f22 100644
--- a/build_files/cmake/Modules/FindJeMalloc.cmake
+++ b/build_files/cmake/Modules/FindJeMalloc.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If JEMALLOC_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindLLVM.cmake b/build_files/cmake/Modules/FindLLVM.cmake
index 141a91c0508..d7269a4281f 100644
--- a/build_files/cmake/Modules/FindLLVM.cmake
+++ b/build_files/cmake/Modules/FindLLVM.cmake
@@ -13,12 +13,8 @@
#=============================================================================
# Copyright 2015 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
if(LLVM_ROOT_DIR)
diff --git a/build_files/cmake/Modules/FindLZO.cmake b/build_files/cmake/Modules/FindLZO.cmake
index 4db5d0f5441..81f8792a803 100644
--- a/build_files/cmake/Modules/FindLZO.cmake
+++ b/build_files/cmake/Modules/FindLZO.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2015 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If LZO_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOSL.cmake b/build_files/cmake/Modules/FindOSL.cmake
index 07ed2c86e19..f22fe32c994 100644
--- a/build_files/cmake/Modules/FindOSL.cmake
+++ b/build_files/cmake/Modules/FindOSL.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2014 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OSL_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOpenCOLLADA.cmake b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
index 239d46499b9..cc940b76382 100644
--- a/build_files/cmake/Modules/FindOpenCOLLADA.cmake
+++ b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
@@ -11,12 +11,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# note about include paths, there are 2 ways includes are set
diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake
index 090032e06ec..559ccaba865 100644
--- a/build_files/cmake/Modules/FindOpenColorIO.cmake
+++ b/build_files/cmake/Modules/FindOpenColorIO.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2012 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPENCOLORIO_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake
index 3cf559a5da1..090f80b8df7 100644
--- a/build_files/cmake/Modules/FindOpenEXR.cmake
+++ b/build_files/cmake/Modules/FindOpenEXR.cmake
@@ -21,12 +21,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPENEXR_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOpenGLES.cmake b/build_files/cmake/Modules/FindOpenGLES.cmake
index daf6db61050..d01d32b71bc 100644
--- a/build_files/cmake/Modules/FindOpenGLES.cmake
+++ b/build_files/cmake/Modules/FindOpenGLES.cmake
@@ -10,6 +10,13 @@
# OPENGLES_LIBRARIES - all libraries needed for OpenGLES
# OPENGLES_INCLUDES - all includes needed for OpenGLES
+#=============================================================================
+# Copyright 2014 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
+#=============================================================================
+
# If OPENGLES_ROOT_DIR was defined in the environment, use it.
IF(NOT OPENGLES_ROOT_DIR AND NOT $ENV{OPENGLES_ROOT_DIR} STREQUAL "")
SET(OPENGLES_ROOT_DIR $ENV{OPENGLES_ROOT_DIR})
diff --git a/build_files/cmake/Modules/FindOpenImageDenoise.cmake b/build_files/cmake/Modules/FindOpenImageDenoise.cmake
index c7215d30e8a..3facadbb9be 100644
--- a/build_files/cmake/Modules/FindOpenImageDenoise.cmake
+++ b/build_files/cmake/Modules/FindOpenImageDenoise.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2019 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPENIMAGEDENOISE_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOpenImageIO.cmake b/build_files/cmake/Modules/FindOpenImageIO.cmake
index 3570c982961..aac5b5ce0a8 100644
--- a/build_files/cmake/Modules/FindOpenImageIO.cmake
+++ b/build_files/cmake/Modules/FindOpenImageIO.cmake
@@ -16,12 +16,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPENIMAGEIO_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOpenJPEG.cmake b/build_files/cmake/Modules/FindOpenJPEG.cmake
index 5774ac2182a..ddd98237dd0 100644
--- a/build_files/cmake/Modules/FindOpenJPEG.cmake
+++ b/build_files/cmake/Modules/FindOpenJPEG.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPENJPEG_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake
index 2c9fbf0ba60..312540645dc 100644
--- a/build_files/cmake/Modules/FindOpenSubdiv.cmake
+++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake
@@ -11,12 +11,8 @@
#=============================================================================
# Copyright 2013 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPENSUBDIV_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOpenVDB.cmake b/build_files/cmake/Modules/FindOpenVDB.cmake
index 5f24231fcf4..1c7d955d1d4 100644
--- a/build_files/cmake/Modules/FindOpenVDB.cmake
+++ b/build_files/cmake/Modules/FindOpenVDB.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2015 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPENVDB_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindOptiX.cmake b/build_files/cmake/Modules/FindOptiX.cmake
index 5b606afea27..2cb1ce09e46 100644
--- a/build_files/cmake/Modules/FindOptiX.cmake
+++ b/build_files/cmake/Modules/FindOptiX.cmake
@@ -10,12 +10,8 @@
#=============================================================================
# Copyright 2019 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If OPTIX_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindPCRE.cmake b/build_files/cmake/Modules/FindPCRE.cmake
index dfe721920fd..678826e4ab1 100644
--- a/build_files/cmake/Modules/FindPCRE.cmake
+++ b/build_files/cmake/Modules/FindPCRE.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If PCRE_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindPugiXML.cmake b/build_files/cmake/Modules/FindPugiXML.cmake
index 73d7b9ef92c..5dced1c6df8 100644
--- a/build_files/cmake/Modules/FindPugiXML.cmake
+++ b/build_files/cmake/Modules/FindPugiXML.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2014 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If PUGIXML_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
index 0e3ecac14f0..5b3f2e52256 100644
--- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake
+++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake
@@ -25,12 +25,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If PYTHON_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindSDL2.cmake b/build_files/cmake/Modules/FindSDL2.cmake
index ba89a6e3fce..7ef9a84dab0 100644
--- a/build_files/cmake/Modules/FindSDL2.cmake
+++ b/build_files/cmake/Modules/FindSDL2.cmake
@@ -13,12 +13,8 @@
#=============================================================================
# Copyright 2015 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If SDL2_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindSndFile.cmake b/build_files/cmake/Modules/FindSndFile.cmake
index 0d66b4785e2..aae5b692228 100644
--- a/build_files/cmake/Modules/FindSndFile.cmake
+++ b/build_files/cmake/Modules/FindSndFile.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If LIBSNDFILE_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindSpacenav.cmake b/build_files/cmake/Modules/FindSpacenav.cmake
index 353b05f90b5..b7c8c01dc32 100644
--- a/build_files/cmake/Modules/FindSpacenav.cmake
+++ b/build_files/cmake/Modules/FindSpacenav.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If SPACENAV_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindTBB.cmake b/build_files/cmake/Modules/FindTBB.cmake
index de7db09ddb5..5a0d5a7d42d 100644
--- a/build_files/cmake/Modules/FindTBB.cmake
+++ b/build_files/cmake/Modules/FindTBB.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2016 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If TBB_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindUSD.cmake b/build_files/cmake/Modules/FindUSD.cmake
index 043a10ffa98..d0e772038a7 100644
--- a/build_files/cmake/Modules/FindUSD.cmake
+++ b/build_files/cmake/Modules/FindUSD.cmake
@@ -12,12 +12,8 @@
#=============================================================================
# Copyright 2019 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If USD_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindXML2.cmake b/build_files/cmake/Modules/FindXML2.cmake
index c16ab4468cc..d313150f7a0 100644
--- a/build_files/cmake/Modules/FindXML2.cmake
+++ b/build_files/cmake/Modules/FindXML2.cmake
@@ -14,12 +14,8 @@
#=============================================================================
# Copyright 2011 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If XML2_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/FindXR_OpenXR_SDK.cmake b/build_files/cmake/Modules/FindXR_OpenXR_SDK.cmake
index 567a0101b4a..3e9cebdbae4 100644
--- a/build_files/cmake/Modules/FindXR_OpenXR_SDK.cmake
+++ b/build_files/cmake/Modules/FindXR_OpenXR_SDK.cmake
@@ -20,12 +20,8 @@
# XR_OPENXR_SDK_LOADER_LIBRARY, where to find the OpenXR-SDK loader library.
#=============================================================================
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#=============================================================================
# If XR_OPENXR_SDK_ROOT_DIR was defined in the environment, use it.
diff --git a/build_files/cmake/Modules/GTest.cmake b/build_files/cmake/Modules/GTest.cmake
index 9a82fc49628..6981c1ddc55 100644
--- a/build_files/cmake/Modules/GTest.cmake
+++ b/build_files/cmake/Modules/GTest.cmake
@@ -1,5 +1,5 @@
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#[=======================================================================[.rst:
GoogleTest
diff --git a/build_files/cmake/Modules/GTestAddTests.cmake b/build_files/cmake/Modules/GTestAddTests.cmake
index 8be07b8e2e5..850504bdbea 100644
--- a/build_files/cmake/Modules/GTestAddTests.cmake
+++ b/build_files/cmake/Modules/GTestAddTests.cmake
@@ -1,5 +1,5 @@
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
# Blender: disable ASAN leak detection when trying to discover tests.
set(ENV{ASAN_OPTIONS} "detect_leaks=0")
diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake
index ea9a1edeb43..a744f4202da 100644
--- a/build_files/cmake/Modules/GTestTesting.cmake
+++ b/build_files/cmake/Modules/GTestTesting.cmake
@@ -1,12 +1,8 @@
#=============================================================================
# Copyright 2014 Blender Foundation.
#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+# Distributed under the OSI-approved BSD 3-Clause License,
+# see accompanying file BSD-3-Clause-license.txt for details.
#
# Inspired on the Testing.cmake from Libmv
#
diff --git a/doc/license/BSD-3-Clause-license.txt b/doc/license/BSD-3-Clause-license.txt
new file mode 100644
index 00000000000..3879237a0a9
--- /dev/null
+++ b/doc/license/BSD-3-Clause-license.txt
@@ -0,0 +1,26 @@
+BSD 3-Clause License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp
index 3d1b6e1d865..145b1fa492c 100644
--- a/intern/cycles/render/geometry.cpp
+++ b/intern/cycles/render/geometry.cpp
@@ -1201,9 +1201,13 @@ void GeometryManager::device_update_volume_images(Device *device, Scene *scene,
}
ImageHandle &handle = attr.data_voxel();
- const int slot = handle.svm_slot();
- if (slot != -1) {
- volume_images.insert(slot);
+ /* We can build directly from OpenVDB data structures, no need to
+ * load such images early. */
+ if (!handle.vdb_loader()) {
+ const int slot = handle.svm_slot();
+ if (slot != -1) {
+ volume_images.insert(slot);
+ }
}
}
}
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 691eb162dd0..a5dfcf60d61 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -18,6 +18,7 @@
#include "device/device.h"
#include "render/colorspace.h"
#include "render/image_oiio.h"
+#include "render/image_vdb.h"
#include "render/scene.h"
#include "render/stats.h"
@@ -172,6 +173,31 @@ device_texture *ImageHandle::image_memory(const int tile_index) const
return img ? img->mem : NULL;
}
+VDBImageLoader *ImageHandle::vdb_loader(const int tile_index) const
+{
+ if (tile_index >= tile_slots.size()) {
+ return NULL;
+ }
+
+ ImageManager::Image *img = manager->images[tile_slots[tile_index]];
+
+ if (img == NULL) {
+ return NULL;
+ }
+
+ ImageLoader *loader = img->loader;
+
+ if (loader == NULL) {
+ return NULL;
+ }
+
+ if (loader->is_vdb_loader()) {
+ return dynamic_cast<VDBImageLoader *>(loader);
+ }
+
+ return NULL;
+}
+
bool ImageHandle::operator==(const ImageHandle &other) const
{
return manager == other.manager && tile_slots == other.tile_slots;
@@ -258,6 +284,11 @@ bool ImageLoader::equals(const ImageLoader *a, const ImageLoader *b)
}
}
+bool ImageLoader::is_vdb_loader() const
+{
+ return false;
+}
+
/* Image Manager */
ImageManager::ImageManager(const DeviceInfo &info)
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 47be0ee559a..cb059256ce3 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -39,6 +39,7 @@ class Progress;
class RenderStats;
class Scene;
class ColorSpaceProcessor;
+class VDBImageLoader;
/* Image Parameters */
class ImageParams {
@@ -124,6 +125,8 @@ class ImageLoader {
virtual bool equals(const ImageLoader &other) const = 0;
static bool equals(const ImageLoader *a, const ImageLoader *b);
+ virtual bool is_vdb_loader() const;
+
/* Work around for no RTTI. */
};
@@ -149,6 +152,8 @@ class ImageHandle {
int svm_slot(const int tile_index = 0) const;
device_texture *image_memory(const int tile_index = 0) const;
+ VDBImageLoader *vdb_loader(const int tile_index = 0) const;
+
protected:
vector<int> tile_slots;
ImageManager *manager;
diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp
index 500131c2d84..3f7dd45ee88 100644
--- a/intern/cycles/render/image_vdb.cpp
+++ b/intern/cycles/render/image_vdb.cpp
@@ -185,4 +185,16 @@ void VDBImageLoader::cleanup()
#endif
}
+bool VDBImageLoader::is_vdb_loader() const
+{
+ return true;
+}
+
+#ifdef WITH_OPENVDB
+openvdb::GridBase::ConstPtr VDBImageLoader::get_grid()
+{
+ return grid;
+}
+#endif
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/image_vdb.h b/intern/cycles/render/image_vdb.h
index 7dec63b11e6..4500cfbfb88 100644
--- a/intern/cycles/render/image_vdb.h
+++ b/intern/cycles/render/image_vdb.h
@@ -43,6 +43,12 @@ class VDBImageLoader : public ImageLoader {
virtual void cleanup() override;
+ virtual bool is_vdb_loader() const override;
+
+#ifdef WITH_OPENVDB
+ openvdb::GridBase::ConstPtr get_grid();
+#endif
+
protected:
string grid_name;
#ifdef WITH_OPENVDB
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
index 607363d01c6..70189ea4812 100644
--- a/intern/cycles/render/mesh_volume.cpp
+++ b/intern/cycles/render/mesh_volume.cpp
@@ -15,34 +15,25 @@
*/
#include "render/attribute.h"
+#include "render/image_vdb.h"
#include "render/mesh.h"
#include "render/scene.h"
+#ifdef WITH_OPENVDB
+# include <openvdb/tools/Dense.h>
+# include <openvdb/tools/GridTransformer.h>
+# include <openvdb/tools/Morphology.h>
+#endif
+
#include "util/util_foreach.h"
#include "util/util_hash.h"
#include "util/util_logging.h"
+#include "util/util_openvdb.h"
#include "util/util_progress.h"
#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
-const int64_t VOXEL_INDEX_NONE = -1;
-
-static int64_t compute_voxel_index(const int3 &resolution, int64_t x, int64_t y, int64_t z)
-{
- if (x < 0 || x >= resolution.x) {
- return VOXEL_INDEX_NONE;
- }
- else if (y < 0 || y >= resolution.y) {
- return VOXEL_INDEX_NONE;
- }
- else if (z < 0 || z >= resolution.z) {
- return VOXEL_INDEX_NONE;
- }
-
- return x + y * resolution.x + z * resolution.x * resolution.y;
-}
-
struct QuadData {
int v0, v1, v2, v3;
@@ -123,122 +114,146 @@ static void create_quad(int3 corners[8],
quads.push_back(quad);
}
-struct VolumeParams {
- int3 resolution;
- float3 cell_size;
- float3 start_point;
- int pad_size;
-};
-
-static const int CUBE_SIZE = 8;
-
/* Create a mesh from a volume.
*
* The way the algorithm works is as follows:
*
- * - The coordinates of active voxels from a dense volume (or 3d image) are
- * gathered inside an auxiliary volume.
- * - Each set of coordinates of an CUBE_SIZE cube are mapped to the same
- * coordinate of the auxiliary volume.
- * - Quads are created between active and non-active voxels in the auxiliary
- * volume to generate a tight mesh around the volume.
+ * - The topologies of input OpenVDB grids are merged into a temporary grid.
+ * - Voxels of the temporary grid are dilated to account for the padding necessary for volume
+ * sampling.
+ * - Quads are created on the boundary between active and inactive leaf nodes of the temporary
+ * grid.
*/
class VolumeMeshBuilder {
- /* Auxiliary volume that is used to check if a node already added. */
- vector<char> grid;
-
- /* The resolution of the auxiliary volume, set to be equal to 1/CUBE_SIZE
- * of the original volume on each axis. */
- int3 res;
-
- size_t number_of_nodes;
-
- /* Offset due to padding in the original grid. Padding will transform the
- * coordinates of the original grid from 0...res to -padding...res+padding,
- * so some coordinates are negative, and we need to properly account for
- * them. */
- int3 pad_offset;
-
- VolumeParams *params;
-
public:
- VolumeMeshBuilder(VolumeParams *volume_params);
+#ifdef WITH_OPENVDB
+ /* use a MaskGrid to store the topology to save memory */
+ openvdb::MaskGrid::Ptr topology_grid;
+ openvdb::CoordBBox bbox;
+#endif
+ bool first_grid;
- void add_node(int x, int y, int z);
+ VolumeMeshBuilder();
- void add_node_with_padding(int x, int y, int z);
+#ifdef WITH_OPENVDB
+ void add_grid(openvdb::GridBase::ConstPtr grid, bool do_clipping, float volume_clipping);
+#endif
- void create_mesh(vector<float3> &vertices, vector<int> &indices, vector<float3> &face_normals);
+ void add_padding(int pad_size);
+
+ void create_mesh(vector<float3> &vertices,
+ vector<int> &indices,
+ vector<float3> &face_normals,
+ const float face_overlap_avoidance);
- private:
void generate_vertices_and_quads(vector<int3> &vertices_is, vector<QuadData> &quads);
- void convert_object_space(const vector<int3> &vertices, vector<float3> &out_vertices);
+ void convert_object_space(const vector<int3> &vertices,
+ vector<float3> &out_vertices,
+ const float face_overlap_avoidance);
void convert_quads_to_tris(const vector<QuadData> &quads,
vector<int> &tris,
vector<float3> &face_normals);
-};
-VolumeMeshBuilder::VolumeMeshBuilder(VolumeParams *volume_params)
-{
- params = volume_params;
- number_of_nodes = 0;
+ bool empty_grid() const;
- const int64_t x = divide_up(params->resolution.x, CUBE_SIZE);
- const int64_t y = divide_up(params->resolution.y, CUBE_SIZE);
- const int64_t z = divide_up(params->resolution.z, CUBE_SIZE);
+#ifdef WITH_OPENVDB
+ template <typename GridType>
+ void merge_grid(openvdb::GridBase::ConstPtr grid, bool do_clipping, float volume_clipping)
+ {
+ typename GridType::ConstPtr typed_grid = openvdb::gridConstPtrCast<GridType>(grid);
- /* Adding 2*pad_size since we pad in both positive and negative directions
- * along the axis. */
- const int64_t px = divide_up(params->resolution.x + 2 * params->pad_size, CUBE_SIZE);
- const int64_t py = divide_up(params->resolution.y + 2 * params->pad_size, CUBE_SIZE);
- const int64_t pz = divide_up(params->resolution.z + 2 * params->pad_size, CUBE_SIZE);
+ if (do_clipping) {
+ using ValueType = typename GridType::ValueType;
+ typename GridType::Ptr copy = typed_grid->deepCopy();
+ typename GridType::ValueOnIter iter = copy->beginValueOn();
- res = make_int3(px, py, pz);
- pad_offset = make_int3(px - x, py - y, pz - z);
+ for (; iter; ++iter) {
+ if (iter.getValue() < ValueType(volume_clipping)) {
+ iter.setValueOff();
+ }
+ }
- grid.resize(px * py * pz, 0);
-}
+ typed_grid = copy;
+ }
-void VolumeMeshBuilder::add_node(int x, int y, int z)
-{
- /* Map coordinates to index space. */
- const int index_x = (x / CUBE_SIZE) + pad_offset.x;
- const int index_y = (y / CUBE_SIZE) + pad_offset.y;
- const int index_z = (z / CUBE_SIZE) + pad_offset.z;
+ topology_grid->topologyUnion(*typed_grid);
+ }
+#endif
+};
- assert((index_x >= 0) && (index_y >= 0) && (index_z >= 0));
+VolumeMeshBuilder::VolumeMeshBuilder()
+{
+ first_grid = true;
+}
- const int64_t index = compute_voxel_index(res, index_x, index_y, index_z);
- if (index == VOXEL_INDEX_NONE) {
- return;
+#ifdef WITH_OPENVDB
+void VolumeMeshBuilder::add_grid(openvdb::GridBase::ConstPtr grid, bool do_clipping, float volume_clipping)
+{
+ /* set the transform of our grid from the first one */
+ if (first_grid) {
+ topology_grid = openvdb::MaskGrid::create();
+ topology_grid->setTransform(grid->transform().copy());
+ first_grid = false;
}
-
- /* We already have a node here. */
- if (grid[index] == 1) {
- return;
+ /* if the transforms do not match, we need to resample one of the grids so that
+ * its index space registers with that of the other, here we resample our mask
+ * grid so memory usage is kept low */
+ else if (topology_grid->transform() != grid->transform()) {
+ openvdb::MaskGrid::Ptr temp_grid = topology_grid->copyWithNewTree();
+ temp_grid->setTransform(grid->transform().copy());
+ openvdb::tools::resampleToMatch<openvdb::tools::BoxSampler>(*topology_grid, *temp_grid);
+ topology_grid = temp_grid;
+ topology_grid->setTransform(grid->transform().copy());
}
- ++number_of_nodes;
-
- grid[index] = 1;
+ if (grid->isType<openvdb::FloatGrid>()) {
+ merge_grid<openvdb::FloatGrid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::Vec3fGrid>()) {
+ merge_grid<openvdb::Vec3fGrid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::Vec4fGrid>()) {
+ merge_grid<openvdb::Vec4fGrid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::BoolGrid>()) {
+ merge_grid<openvdb::BoolGrid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::DoubleGrid>()) {
+ merge_grid<openvdb::DoubleGrid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::Int32Grid>()) {
+ merge_grid<openvdb::Int32Grid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::Int64Grid>()) {
+ merge_grid<openvdb::Int64Grid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::Vec3IGrid>()) {
+ merge_grid<openvdb::Vec3IGrid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::Vec3dGrid>()) {
+ merge_grid<openvdb::Vec3dGrid>(grid, do_clipping, volume_clipping);
+ }
+ else if (grid->isType<openvdb::MaskGrid>()) {
+ topology_grid->topologyUnion(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid));
+ }
}
+#endif
-void VolumeMeshBuilder::add_node_with_padding(int x, int y, int z)
+void VolumeMeshBuilder::add_padding(int pad_size)
{
- for (int px = x - params->pad_size; px < x + params->pad_size; ++px) {
- for (int py = y - params->pad_size; py < y + params->pad_size; ++py) {
- for (int pz = z - params->pad_size; pz < z + params->pad_size; ++pz) {
- add_node(px, py, pz);
- }
- }
- }
+#ifdef WITH_OPENVDB
+ openvdb::tools::dilateVoxels(topology_grid->tree(), pad_size);
+#else
+ (void)pad_size;
+#endif
}
void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
vector<int> &indices,
- vector<float3> &face_normals)
+ vector<float3> &face_normals,
+ const float face_overlap_avoidance)
{
/* We create vertices in index space (is), and only convert them to object
* space when done. */
@@ -247,7 +262,7 @@ void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
generate_vertices_and_quads(vertices_is, quads);
- convert_object_space(vertices_is, vertices);
+ convert_object_space(vertices_is, vertices, face_overlap_avoidance);
convert_quads_to_tris(quads, indices, face_normals);
}
@@ -255,85 +270,97 @@ void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
void VolumeMeshBuilder::generate_vertices_and_quads(vector<ccl::int3> &vertices_is,
vector<QuadData> &quads)
{
- unordered_map<size_t, int> used_verts;
+#ifdef WITH_OPENVDB
+ const openvdb::MaskGrid::TreeType &tree = topology_grid->tree();
+ tree.evalLeafBoundingBox(bbox);
- for (int z = 0; z < res.z; ++z) {
- for (int y = 0; y < res.y; ++y) {
- for (int x = 0; x < res.x; ++x) {
- int64_t voxel_index = compute_voxel_index(res, x, y, z);
- if (grid[voxel_index] == 0) {
- continue;
- }
+ const int3 resolution = make_int3(bbox.dim().x(), bbox.dim().y(), bbox.dim().z());
- /* Compute min and max coords of the node in index space. */
- int3 min = make_int3((x - pad_offset.x) * CUBE_SIZE,
- (y - pad_offset.y) * CUBE_SIZE,
- (z - pad_offset.z) * CUBE_SIZE);
-
- /* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */
- int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE);
-
- int3 corners[8] = {
- make_int3(min[0], min[1], min[2]),
- make_int3(max[0], min[1], min[2]),
- make_int3(max[0], max[1], min[2]),
- make_int3(min[0], max[1], min[2]),
- make_int3(min[0], min[1], max[2]),
- make_int3(max[0], min[1], max[2]),
- make_int3(max[0], max[1], max[2]),
- make_int3(min[0], max[1], max[2]),
- };
-
- /* Only create a quad if on the border between an active and
- * an inactive node.
- */
-
- voxel_index = compute_voxel_index(res, x - 1, y, z);
- if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN);
- }
+ unordered_map<size_t, int> used_verts;
- voxel_index = compute_voxel_index(res, x + 1, y, z);
- if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX);
- }
+ for (auto iter = tree.cbeginLeaf(); iter; ++iter) {
+ openvdb::CoordBBox leaf_bbox = iter->getNodeBoundingBox();
+ /* +1 to convert from exclusive to include bounds. */
+ leaf_bbox.max() = leaf_bbox.max().offsetBy(1);
+
+ int3 min = make_int3(leaf_bbox.min().x(), leaf_bbox.min().y(), leaf_bbox.min().z());
+ int3 max = make_int3(leaf_bbox.max().x(), leaf_bbox.max().y(), leaf_bbox.max().z());
+
+ int3 corners[8] = {
+ make_int3(min[0], min[1], min[2]),
+ make_int3(max[0], min[1], min[2]),
+ make_int3(max[0], max[1], min[2]),
+ make_int3(min[0], max[1], min[2]),
+ make_int3(min[0], min[1], max[2]),
+ make_int3(max[0], min[1], max[2]),
+ make_int3(max[0], max[1], max[2]),
+ make_int3(min[0], max[1], max[2]),
+ };
+
+ /* Only create a quad if on the border between an active and an inactive leaf.
+ *
+ * We verify that a leaf exists by probing a coordinate that is at its center,
+ * to do so we compute the center of the current leaf and offset this coordinate
+ * by the size of a leaf in each direction.
+ */
+ static const int LEAF_DIM = openvdb::MaskGrid::TreeType::LeafNodeType::DIM;
+ auto center = leaf_bbox.min() + openvdb::Coord(LEAF_DIM / 2);
+
+ if (!tree.probeLeaf(openvdb::Coord(center.x() - LEAF_DIM, center.y(), center.z()))) {
+ create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_X_MIN);
+ }
- voxel_index = compute_voxel_index(res, x, y - 1, z);
- if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN);
- }
+ if (!tree.probeLeaf(openvdb::Coord(center.x() + LEAF_DIM, center.y(), center.z()))) {
+ create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_X_MAX);
+ }
- voxel_index = compute_voxel_index(res, x, y + 1, z);
- if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX);
- }
+ if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y() - LEAF_DIM, center.z()))) {
+ create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Y_MIN);
+ }
- voxel_index = compute_voxel_index(res, x, y, z - 1);
- if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN);
- }
+ if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y() + LEAF_DIM, center.z()))) {
+ create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Y_MAX);
+ }
- voxel_index = compute_voxel_index(res, x, y, z + 1);
- if (voxel_index == VOXEL_INDEX_NONE || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX);
- }
- }
+ if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y(), center.z() - LEAF_DIM))) {
+ create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Z_MIN);
+ }
+
+ if (!tree.probeLeaf(openvdb::Coord(center.x(), center.y(), center.z() + LEAF_DIM))) {
+ create_quad(corners, vertices_is, quads, resolution, used_verts, QUAD_Z_MAX);
}
}
+#else
+ (void)vertices_is;
+ (void)quads;
+#endif
}
void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
- vector<float3> &out_vertices)
+ vector<float3> &out_vertices,
+ const float face_overlap_avoidance)
{
+#ifdef WITH_OPENVDB
+ /* compute the offset for the face overlap avoidance */
+ bbox = topology_grid->evalActiveVoxelBoundingBox();
+ openvdb::Coord dim = bbox.dim();
+
+ float3 cell_size = make_float3(1.0f / dim.x(), 1.0f / dim.y(), 1.0f / dim.z());
+ float3 point_offset = cell_size * face_overlap_avoidance;
+
out_vertices.reserve(vertices.size());
for (size_t i = 0; i < vertices.size(); ++i) {
- float3 vertex = make_float3(vertices[i].x, vertices[i].y, vertices[i].z);
- vertex *= params->cell_size;
- vertex += params->start_point;
-
- out_vertices.push_back(vertex);
+ openvdb::math::Vec3d p = topology_grid->indexToWorld(
+ openvdb::math::Vec3d(vertices[i].x, vertices[i].y, vertices[i].z));
+ float3 vertex = make_float3((float)p.x(), (float)p.y(), (float)p.z());
+ out_vertices.push_back(vertex + point_offset);
}
+#else
+ (void)vertices;
+ (void)out_vertices;
+ (void)face_overlap_avoidance;
+#endif
}
void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads,
@@ -359,57 +386,115 @@ void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads,
}
}
-/* ************************************************************************** */
+bool VolumeMeshBuilder::empty_grid() const
+{
+#ifdef WITH_OPENVDB
+ return !topology_grid || topology_grid->tree().leafCount() == 0;
+#else
+ return true;
+#endif
+}
-struct VoxelAttributeGrid {
- float *data;
- int channels;
-};
+#ifdef WITH_OPENVDB
+template<typename GridType>
+static openvdb::GridBase::ConstPtr openvdb_grid_from_device_texture(device_texture *image_memory,
+ float volume_clipping,
+ Transform transform_3d)
+{
+ using ValueType = typename GridType::ValueType;
+
+ openvdb::CoordBBox dense_bbox(0,
+ 0,
+ 0,
+ image_memory->data_width - 1,
+ image_memory->data_height - 1,
+ image_memory->data_depth - 1);
+ openvdb::tools::Dense<ValueType, openvdb::tools::MemoryLayout::LayoutXYZ> dense(
+ dense_bbox, static_cast<ValueType *>(image_memory->host_pointer));
+
+ typename GridType::Ptr sparse = GridType::create(ValueType(0.0f));
+ openvdb::tools::copyFromDense(dense, *sparse, ValueType(volume_clipping));
+
+ /* copyFromDense will remove any leaf node that contains constant data and replace it with a tile,
+ * however, we need to preserve the leaves in order to generate the mesh, so revoxelize the leaves
+ * that were pruned. This should not affect areas that were skipped due to the volume_clipping parameter. */
+ sparse->tree().voxelizeActiveTiles();
+
+ /* Compute index to world matrix. */
+ float3 voxel_size = make_float3(1.0f / image_memory->data_width, 1.0f / image_memory->data_height, 1.0f / image_memory->data_depth);
+
+ transform_3d = transform_inverse(transform_3d);
+
+ openvdb::Mat4R index_to_world_mat((double)(voxel_size.x * transform_3d[0][0]), 0.0, 0.0, 0.0,
+ 0.0, (double)(voxel_size.y * transform_3d[1][1]), 0.0, 0.0,
+ 0.0, 0.0, (double)(voxel_size.z * transform_3d[2][2]), 0.0,
+ (double)transform_3d[0][3], (double)transform_3d[1][3], (double)transform_3d[2][3], 1.0);
+
+ openvdb::math::Transform::Ptr index_to_world_tfm = openvdb::math::Transform::createLinearTransform(index_to_world_mat);
+
+ sparse->setTransform(index_to_world_tfm);
+
+ return sparse;
+}
+#endif
+
+/* ************************************************************************** */
void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress)
{
string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str());
progress.set_status("Updating Mesh", msg);
- vector<VoxelAttributeGrid> voxel_grids;
-
- /* Compute volume parameters. */
- VolumeParams volume_params;
- volume_params.resolution = make_int3(0, 0, 0);
-
- Transform transform = transform_identity();
+ VolumeMeshBuilder builder;
+#ifdef WITH_OPENVDB
foreach (Attribute &attr, mesh->attributes.attributes) {
if (attr.element != ATTR_ELEMENT_VOXEL) {
continue;
}
+ bool do_clipping = false;
+
ImageHandle &handle = attr.data_voxel();
- device_texture *image_memory = handle.image_memory();
- int3 resolution = make_int3(
- image_memory->data_width, image_memory->data_height, image_memory->data_depth);
- if (volume_params.resolution == make_int3(0, 0, 0)) {
- volume_params.resolution = resolution;
- }
- else if (volume_params.resolution != resolution) {
- /* TODO: support this as it's common for OpenVDB. */
- VLOG(1) << "Can't create accurate volume mesh, all voxel grid resolutions must be equal\n";
- continue;
+ /* Try building from OpenVDB grid directly. */
+ VDBImageLoader *vdb_loader = handle.vdb_loader();
+ openvdb::GridBase::ConstPtr grid;
+ if (vdb_loader) {
+ grid = vdb_loader->get_grid();
+
+ /* If building from an OpenVDB grid, we need to manually clip the values. */
+ do_clipping = true;
}
- VoxelAttributeGrid voxel_grid;
- voxel_grid.data = static_cast<float *>(image_memory->host_pointer);
- voxel_grid.channels = image_memory->data_elements;
- voxel_grids.push_back(voxel_grid);
+ /* Else fall back to creating an OpenVDB grid from the dense volume data. */
+ if (!grid) {
+ device_texture *image_memory = handle.image_memory();
- /* TODO: support multiple transforms. */
- if (image_memory->info.use_transform_3d) {
- transform = image_memory->info.transform_3d;
+ if (image_memory->data_elements == 1) {
+ grid = openvdb_grid_from_device_texture<openvdb::FloatGrid>(image_memory,
+ mesh->volume_clipping,
+ handle.metadata().transform_3d);
+ }
+ else if (image_memory->data_elements == 3) {
+ grid = openvdb_grid_from_device_texture<openvdb::Vec3fGrid>(image_memory,
+ mesh->volume_clipping,
+ handle.metadata().transform_3d);
+ }
+ else if (image_memory->data_elements == 4) {
+ grid = openvdb_grid_from_device_texture<openvdb::Vec4fGrid>(image_memory,
+ mesh->volume_clipping,
+ handle.metadata().transform_3d);
+ }
+ }
+
+ if (grid) {
+ builder.add_grid(grid, do_clipping, mesh->volume_clipping);
}
}
+#endif
- if (voxel_grids.empty()) {
+ if (builder.empty_grid()) {
return;
}
@@ -438,56 +523,19 @@ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress)
return;
}
- /* Compute start point and cell size from transform. */
- const int3 resolution = volume_params.resolution;
- float3 start_point = make_float3(0.0f, 0.0f, 0.0f);
- float3 cell_size = make_float3(1.0f / resolution.x, 1.0f / resolution.y, 1.0f / resolution.z);
-
- /* TODO: support arbitrary transforms, not just scale + translate. */
- const Transform itfm = transform_inverse(transform);
- start_point = transform_point(&itfm, start_point);
- cell_size = transform_direction(&itfm, cell_size);
+ builder.add_padding(pad_size);
/* Slightly offset vertex coordinates to avoid overlapping faces with other
* volumes or meshes. The proper solution would be to improve intersection in
* the kernel to support robust handling of multiple overlapping faces or use
* an all-hit intersection similar to shadows. */
- const float3 face_overlap_avoidance = cell_size * 0.1f *
- hash_uint_to_float(hash_string(mesh->name.c_str()));
-
- volume_params.start_point = start_point + face_overlap_avoidance;
- volume_params.cell_size = cell_size;
- volume_params.pad_size = pad_size;
-
- /* Build bounding mesh around non-empty volume cells. */
- VolumeMeshBuilder builder(&volume_params);
- const float clipping = mesh->volume_clipping;
-
- for (int z = 0; z < resolution.z; ++z) {
- for (int y = 0; y < resolution.y; ++y) {
- for (int x = 0; x < resolution.x; ++x) {
- int64_t voxel_index = compute_voxel_index(resolution, x, y, z);
-
- for (size_t i = 0; i < voxel_grids.size(); ++i) {
- const VoxelAttributeGrid &voxel_grid = voxel_grids[i];
- const int channels = voxel_grid.channels;
-
- for (int c = 0; c < channels; c++) {
- if (voxel_grid.data[voxel_index * channels + c] >= clipping) {
- builder.add_node_with_padding(x, y, z);
- break;
- }
- }
- }
- }
- }
- }
+ const float face_overlap_avoidance = 0.1f * hash_uint_to_float(hash_string(mesh->name.c_str()));
/* Create mesh. */
vector<float3> vertices;
vector<int> indices;
vector<float3> face_normals;
- builder.create_mesh(vertices, indices, face_normals);
+ builder.create_mesh(vertices, indices, face_normals, face_overlap_avoidance);
mesh->clear(true);
mesh->reserve_mesh(vertices.size(), indices.size() / 3);
@@ -514,10 +562,6 @@ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress)
indices.size() * sizeof(int)) /
(1024.0 * 1024.0)
<< "Mb.";
-
- VLOG(1) << "Memory usage volume grid: "
- << (resolution.x * resolution.y * resolution.z * sizeof(float)) / (1024.0 * 1024.0)
- << "Mb.";
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 08a8cb08254..70c4214c684 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -1156,8 +1156,15 @@ bool Session::render_need_denoise(bool &delayed)
return false;
}
+ /* Immediately denoise when we reach the start sample or last sample. */
+ const int num_samples_finished = tile_manager.state.sample + 1;
+ if (num_samples_finished == params.denoising.start_sample ||
+ num_samples_finished == params.samples) {
+ return true;
+ }
+
/* Do not denoise until the sample at which denoising should start is reached. */
- if (tile_manager.state.sample < min(params.denoising.start_sample, params.samples - 1)) {
+ if (num_samples_finished < params.denoising.start_sample) {
return false;
}
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index f5e488d1bd2..a35ec6c7e29 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -88,6 +88,7 @@ set(SRC_HEADERS
util_murmurhash.h
util_openimagedenoise.h
util_opengl.h
+ util_openvdb.h
util_optimization.h
util_param.h
util_path.h
diff --git a/intern/cycles/util/util_openvdb.h b/intern/cycles/util/util_openvdb.h
new file mode 100644
index 00000000000..a3ebb03e5a4
--- /dev/null
+++ b/intern/cycles/util/util_openvdb.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011-2020 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_OPENVDB_H__
+#define __UTIL_OPENVDB_H__
+
+#ifdef WITH_OPENVDB
+# include <openvdb/openvdb.h>
+
+namespace openvdb {
+
+using Vec4fTree = tree::Tree4<Vec4f, 5, 4, 3>::Type;
+using Vec4fGrid = Grid<Vec4fTree>;
+
+}; // namespace openvdb
+
+#endif
+
+#endif /* __UTIL_OPENVDB_H__ */
diff --git a/intern/guardedalloc/tests/guardedalloc_overflow_test.cc b/intern/guardedalloc/tests/guardedalloc_overflow_test.cc
index eb9a2a68cb0..e5754bc95ea 100644
--- a/intern/guardedalloc/tests/guardedalloc_overflow_test.cc
+++ b/intern/guardedalloc/tests/guardedalloc_overflow_test.cc
@@ -11,7 +11,7 @@
# define ABORT_PREDICATE ::testing::KilledBySignal(SIGABRT)
#endif
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__clang__)
/* Disable since it's the purpose of this test. */
# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
#endif
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 02f3d0e559e..52e5bebefe4 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -1926,6 +1926,12 @@ def km_file_browser_main(params):
items.extend([
("file.execute", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'},
{"properties": [("need_active", True)]}),
+ # Both .execute and .select are needed here. The former only works if
+ # there's a file operator (i.e. not in regular editor mode) but is
+ # needed to load files. The latter makes selection work if there's no
+ # operator (i.e. in regular editor mode).
+ ("file.select", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'},
+ {"properties": [("open", True), ("deselect_all", not params.legacy)]}),
("file.refresh", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("file.select", {"type": 'LEFTMOUSE', "value": 'PRESS'},
{"properties": [("open", False), ("deselect_all", not params.legacy)]}),
@@ -6364,6 +6370,18 @@ def km_3d_view_tool_sculpt_mask_by_color(params):
]},
)
+def km_3d_view_tool_sculpt_face_set_edit(params):
+ return (
+ "3D View Tool: Sculpt, Face Set Edit",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {"items": [
+ ("sculpt.face_set_edit", {"type": params.tool_mouse, "value": 'ANY'},
+ None),
+ ("sculpt.face_set_edit", {"type": params.tool_tweak, "value": 'ANY'},
+ None)
+ ]},
+ )
+
def km_3d_view_tool_paint_weight_sample_weight(params):
return (
"3D View Tool: Paint Weight, Sample Weight",
@@ -6908,6 +6926,7 @@ def generate_keymaps(params=None):
km_3d_view_tool_sculpt_cloth_filter(params),
km_3d_view_tool_sculpt_color_filter(params),
km_3d_view_tool_sculpt_mask_by_color(params),
+ km_3d_view_tool_sculpt_face_set_edit(params),
km_3d_view_tool_paint_weight_sample_weight(params),
km_3d_view_tool_paint_weight_sample_vertex_group(params),
km_3d_view_tool_paint_weight_gradient(params),
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 77308fed014..7ff2688f2a7 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -350,7 +350,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
if enable_edit or (ob.use_shape_key_edit_mode and ob.type == 'MESH'):
enable_pin = True
- if ob.show_only_shape_key:
+ if ob.show_only_shape_key is False:
enable_edit_value = True
row = layout.row()
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index ae144d9e8d0..38879d41a64 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1335,6 +1335,22 @@ class _defs_sculpt:
draw_settings=draw_settings,
)
+ @ToolDef.from_fn
+ def face_set_edit():
+ def draw_settings(_context, layout, tool):
+ props = tool.operator_properties("sculpt.face_set_edit")
+ layout.prop(props, "mode", expand=False)
+ layout.prop(props, "modify_hidden")
+
+ return dict(
+ idname="builtin.face_set_edit",
+ label="Edit Face Set",
+ icon="ops.sculpt.face_set_edit",
+ widget=None,
+ keymap="3D View Tool: Sculpt, Face Set Edit",
+ draw_settings=draw_settings,
+ )
+
class _defs_vertex_paint:
@@ -2595,6 +2611,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
else ()
),
None,
+ _defs_sculpt.face_set_edit,
+ None,
_defs_transform.translate,
_defs_transform.rotate,
_defs_transform.scale,
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index ae0a669bfb3..6ea113d8828 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -44,7 +44,7 @@ extern "C" {
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
* was written with too new a version. */
-#define BLENDER_FILE_MIN_VERSION 280
+#define BLENDER_FILE_MIN_VERSION 290
#define BLENDER_FILE_MIN_SUBVERSION 0
/** User readable version string. */
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index a2ad4f7dc2a..429ddf4e551 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -137,6 +137,11 @@ bool BKE_gpencil_merge_materials_table_get(struct Object *ob,
const float sat_threshold,
const float val_threshold,
struct GHash *r_mat_table);
+bool BKE_gpencil_merge_materials(struct Object *ob,
+ const float hue_threshold,
+ const float sat_threshold,
+ const float val_threshold,
+ int *r_removed);
/* statistics functions */
void BKE_gpencil_stats_update(struct bGPdata *gpd);
diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h
index 6a9271700e8..b68fac23f56 100644
--- a/source/blender/blenkernel/BKE_gpencil_curve.h
+++ b/source/blender/blenkernel/BKE_gpencil_curve.h
@@ -40,7 +40,8 @@ void BKE_gpencil_convert_curve(struct Main *bmain,
struct Object *ob_cu,
const bool gpencil_lines,
const bool use_collections,
- const bool only_stroke);
+ const float scale_thickness,
+ const float sample);
struct bGPDcurve *BKE_gpencil_stroke_editcurve_generate(struct bGPDstroke *gps,
float error_threshold);
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index 2277eb27ef1..7833ba9c046 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -311,6 +311,9 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
SubdivCCGNeighbors *r_neighbors);
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index);
+void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ float r_point[3]);
typedef enum SubdivCCGAdjacencyType {
SUBDIV_CCG_ADJACENT_NONE,
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index e2d17f34992..1833ad5a748 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -165,7 +165,7 @@ void BKE_bpath_relative_rebase(Main *bmain,
ReportList *reports)
{
BPathRebase_Data data = {NULL};
- const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
+ const int flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
BLI_assert(basedir_src[0] != '\0');
BLI_assert(basedir_dst[0] != '\0');
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index af186dc4940..8cd30c2241f 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1481,6 +1481,11 @@ void BKE_brush_sculpt_reset(Brush *br)
br->curve_preset = BRUSH_CURVE_POW4;
br->spacing = 5;
break;
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ br->curve_preset = BRUSH_CURVE_SMOOTHER;
+ br->spacing = 10;
+ br->alpha = 1.0f;
+ break;
case SCULPT_TOOL_SLIDE_RELAX:
br->spacing = 10;
br->alpha = 1.0f;
@@ -1680,6 +1685,7 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_PAINT:
case SCULPT_TOOL_MASK:
case SCULPT_TOOL_DRAW_FACE_SETS:
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
br->add_col[0] = 0.75f;
br->add_col[1] = 0.75f;
br->add_col[2] = 0.75f;
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index f358355912b..7015e36be1a 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -647,6 +647,31 @@ DO_INLINE void collision_interpolateOnTriangle(float to[3],
VECADDMUL(to, v3, w3);
}
+static void cloth_selfcollision_impulse_vert(const float clamp_sq,
+ const float impulse[3],
+ struct ClothVertex *vert)
+{
+ float impulse_len_sq = len_squared_v3(impulse);
+
+ if ((clamp_sq > 0.0f) && (impulse_len_sq > clamp_sq)) {
+ return;
+ }
+
+ if (fabsf(vert->impulse[0]) < fabsf(impulse[0])) {
+ vert->impulse[0] = impulse[0];
+ }
+
+ if (fabsf(vert->impulse[1]) < fabsf(impulse[1])) {
+ vert->impulse[1] = impulse[1];
+ }
+
+ if (fabsf(vert->impulse[2]) < fabsf(impulse[2])) {
+ vert->impulse[2] = impulse[2];
+ }
+
+ vert->impulse_count++;
+}
+
static int cloth_collision_response_static(ClothModifierData *clmd,
CollisionModifierData *collmd,
Object *collob,
@@ -665,11 +690,12 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
cloth1 = clmd->clothObject;
for (int i = 0; i < collision_count; i++, collpair++) {
- float i1[3], i2[3], i3[3];
-
+ float i1[3], i2[3], i3[3], time_multiplier, d;
zero_v3(i1);
zero_v3(i2);
zero_v3(i3);
+ time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
+ d = clmd->coll_parms->epsilon * 8.0f / 9.0f + epsilon2 * 8.0f / 9.0f - collpair->distance;
/* Only handle static collisions here. */
if (collpair->flag & (COLLISION_IN_FUTURE | COLLISION_INACTIVE)) {
@@ -728,11 +754,10 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
/* If magrelVel < 0 the edges are approaching each other. */
if (magrelVel > 0.0f) {
/* Calculate Impulse magnitude to stop all motion in normal direction. */
- float magtangent = 0, repulse = 0, d = 0;
+ float magtangent = 0, repulse = 0;
double impulse = 0.0;
float vrel_t_pre[3];
float temp[3];
- float time_multiplier;
/* Calculate tangential velocity. */
copy_v3_v3(temp, collpair->normal);
@@ -762,20 +787,11 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
impulse = magrelVel / 1.5f;
VECADDMUL(i1, collpair->normal, w1 * impulse);
- cloth1->verts[collpair->ap1].impulse_count++;
-
VECADDMUL(i2, collpair->normal, w2 * impulse);
- cloth1->verts[collpair->ap2].impulse_count++;
-
if (!is_hair) {
VECADDMUL(i3, collpair->normal, w3 * impulse);
- cloth1->verts[collpair->ap3].impulse_count++;
}
- time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
-
- d = clmd->coll_parms->epsilon * 8.0f / 9.0f + epsilon2 * 8.0f / 9.0f - collpair->distance;
-
if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) {
repulse = MIN2(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel);
@@ -790,7 +806,6 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
VECADDMUL(i1, collpair->normal, impulse);
VECADDMUL(i2, collpair->normal, impulse);
-
if (!is_hair) {
VECADDMUL(i3, collpair->normal, impulse);
}
@@ -798,92 +813,33 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
result = 1;
}
- else {
- float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
- float d;
-
- d = clmd->coll_parms->epsilon * 8.0f / 9.0f + epsilon2 * 8.0f / 9.0f - collpair->distance;
-
- if (d > ALMOST_ZERO) {
- /* Stay on the safe side and clamp repulse. */
- float repulse = d / time_multiplier;
- float impulse = repulse / 4.5f;
-
- VECADDMUL(i1, collpair->normal, w1 * impulse);
- VECADDMUL(i2, collpair->normal, w2 * impulse);
+ else if (d > ALMOST_ZERO) {
+ /* Stay on the safe side and clamp repulse. */
+ float repulse = d / time_multiplier;
+ float impulse = repulse / 4.5f;
- if (!is_hair) {
- VECADDMUL(i3, collpair->normal, w3 * impulse);
- }
-
- cloth1->verts[collpair->ap1].impulse_count++;
- cloth1->verts[collpair->ap2].impulse_count++;
-
- if (!is_hair) {
- cloth1->verts[collpair->ap3].impulse_count++;
- }
+ VECADDMUL(i1, collpair->normal, w1 * impulse);
+ VECADDMUL(i2, collpair->normal, w2 * impulse);
- result = 1;
+ if (!is_hair) {
+ VECADDMUL(i3, collpair->normal, w3 * impulse);
}
+
+ result = 1;
}
if (result) {
- float clamp = clmd->coll_parms->clamp * dt;
-
- if ((clamp > 0.0f) &&
- ((len_v3(i1) > clamp) || (len_v3(i2) > clamp) || (len_v3(i3) > clamp))) {
- return 0;
- }
-
- for (int j = 0; j < 3; j++) {
- if (cloth1->verts[collpair->ap1].impulse_count > 0 &&
- fabsf(cloth1->verts[collpair->ap1].impulse[j]) < fabsf(i1[j])) {
- cloth1->verts[collpair->ap1].impulse[j] = i1[j];
- }
-
- if (cloth1->verts[collpair->ap2].impulse_count > 0 &&
- fabsf(cloth1->verts[collpair->ap2].impulse[j]) < fabsf(i2[j])) {
- cloth1->verts[collpair->ap2].impulse[j] = i2[j];
- }
-
- if (!is_hair) {
- if (cloth1->verts[collpair->ap3].impulse_count > 0 &&
- fabsf(cloth1->verts[collpair->ap3].impulse[j]) < fabsf(i3[j])) {
- cloth1->verts[collpair->ap3].impulse[j] = i3[j];
- }
- }
- }
+ float clamp_sq = clmd->coll_parms->clamp * dt;
+ clamp_sq *= clamp_sq;
+ cloth_selfcollision_impulse_vert(clamp_sq, i1, &cloth1->verts[collpair->ap1]);
+ cloth_selfcollision_impulse_vert(clamp_sq, i2, &cloth1->verts[collpair->ap2]);
+ cloth_selfcollision_impulse_vert(clamp_sq, i3, &cloth1->verts[collpair->ap3]);
}
}
return result;
}
-static void cloth_selfcollision_impulse_vert(const float clamp_sq,
- const float impulse[3],
- struct ClothVertex *vert)
-{
- float impulse_len_sq = len_squared_v3(impulse);
-
- if ((clamp_sq > 0.0f) && (impulse_len_sq > clamp_sq)) {
- return;
- }
-
- if (fabsf(vert->impulse[0]) < fabsf(impulse[0])) {
- vert->impulse[0] = impulse[0];
- }
-
- if (fabsf(vert->impulse[1]) < fabsf(impulse[1])) {
- vert->impulse[1] = impulse[1];
- }
-
- if (fabsf(vert->impulse[2]) < fabsf(impulse[2])) {
- vert->impulse[2] = impulse[2];
- }
-
- vert->impulse_count++;
-}
-
static int cloth_selfcollision_response_static(ClothModifierData *clmd,
CollPair *collpair,
uint collision_count,
@@ -900,6 +856,8 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
for (int i = 0; i < collision_count; i++, collpair++) {
float ia[3][3] = {{0.0f}};
float ib[3][3] = {{0.0f}};
+ float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
+ float d = clmd->coll_parms->selfepsilon * 8.0f / 9.0f * 2.0f - collpair->distance;
/* Only handle static collisions here. */
if (collpair->flag & (COLLISION_IN_FUTURE | COLLISION_INACTIVE)) {
@@ -952,10 +910,10 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
/* If magrelVel < 0 the edges are approaching each other. */
if (magrelVel > 0.0f) {
/* Calculate Impulse magnitude to stop all motion in normal direction. */
- float magtangent = 0, repulse = 0, d = 0;
+ float magtangent = 0, repulse = 0;
double impulse = 0.0;
float vrel_t_pre[3];
- float temp[3], time_multiplier;
+ float temp[3];
/* Calculate tangential velocity. */
copy_v3_v3(temp, collpair->normal);
@@ -993,10 +951,6 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
VECADDMUL(ib[1], collpair->normal, -u2 * impulse);
VECADDMUL(ib[2], collpair->normal, -u3 * impulse);
- time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
-
- d = clmd->coll_parms->selfepsilon * 8.0f / 9.0f * 2.0f - collpair->distance;
-
if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) {
repulse = MIN2(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel);
@@ -1019,27 +973,20 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
result = 1;
}
- else {
- float time_multiplier = 1.0f / (clmd->sim_parms->dt * clmd->sim_parms->timescale);
- float d;
-
- d = clmd->coll_parms->selfepsilon * 8.0f / 9.0f * 2.0f - collpair->distance;
+ else if (d > ALMOST_ZERO) {
+ /* Stay on the safe side and clamp repulse. */
+ float repulse = d * 1.0f / time_multiplier;
+ float impulse = repulse / 9.0f;
- if (d > ALMOST_ZERO) {
- /* Stay on the safe side and clamp repulse. */
- float repulse = d * 1.0f / time_multiplier;
- float impulse = repulse / 9.0f;
-
- VECADDMUL(ia[0], collpair->normal, w1 * impulse);
- VECADDMUL(ia[1], collpair->normal, w2 * impulse);
- VECADDMUL(ia[2], collpair->normal, w3 * impulse);
+ VECADDMUL(ia[0], collpair->normal, w1 * impulse);
+ VECADDMUL(ia[1], collpair->normal, w2 * impulse);
+ VECADDMUL(ia[2], collpair->normal, w3 * impulse);
- VECADDMUL(ib[0], collpair->normal, -u1 * impulse);
- VECADDMUL(ib[1], collpair->normal, -u2 * impulse);
- VECADDMUL(ib[2], collpair->normal, -u3 * impulse);
+ VECADDMUL(ib[0], collpair->normal, -u1 * impulse);
+ VECADDMUL(ib[1], collpair->normal, -u2 * impulse);
+ VECADDMUL(ib[2], collpair->normal, -u3 * impulse);
- result = 1;
- }
+ result = 1;
}
if (result) {
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index bbc4e48677d..a1c4e7d1ef2 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1965,6 +1965,7 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
Material *ma_secondary = NULL;
MaterialGPencilStyle *gp_style_primary = NULL;
MaterialGPencilStyle *gp_style_secondary = NULL;
+ GHash *mat_used = BLI_ghash_int_new(__func__);
short *totcol = BKE_object_material_len_p(ob);
if (totcol == 0) {
@@ -1977,8 +1978,15 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
if (ma_primary == NULL) {
continue;
}
+ for (int idx_secondary = 0; idx_secondary < *totcol; idx_secondary++) {
+ if ((idx_secondary == idx_primary) ||
+ BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) {
+ continue;
+ }
+ if (BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_secondary))) {
+ continue;
+ }
- for (int idx_secondary = idx_primary + 1; idx_secondary < *totcol; idx_secondary++) {
/* Read secondary material to compare with primary material. */
ma_secondary = BKE_gpencil_material(ob, idx_secondary + 1);
if ((ma_secondary == NULL) ||
@@ -2016,6 +2024,11 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
}
float s_hsv_a[3], s_hsv_b[3], f_hsv_a[3], f_hsv_b[3], col[3];
+ zero_v3(s_hsv_a);
+ zero_v3(s_hsv_b);
+ zero_v3(f_hsv_a);
+ zero_v3(f_hsv_b);
+
copy_v3_v3(col, gp_style_primary->stroke_rgba);
rgb_to_hsv_compat_v(col, s_hsv_a);
copy_v3_v3(col, gp_style_secondary->stroke_rgba);
@@ -2026,24 +2039,102 @@ bool BKE_gpencil_merge_materials_table_get(Object *ob,
copy_v3_v3(col, gp_style_secondary->fill_rgba);
rgb_to_hsv_compat_v(col, f_hsv_b);
- /* Check stroke and fill color (only Hue and Saturation). */
+ /* Check stroke and fill color. */
if ((!compare_ff(s_hsv_a[0], s_hsv_b[0], hue_threshold)) ||
(!compare_ff(s_hsv_a[1], s_hsv_b[1], sat_threshold)) ||
+ (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
(!compare_ff(f_hsv_a[0], f_hsv_b[0], hue_threshold)) ||
(!compare_ff(f_hsv_a[1], f_hsv_b[1], sat_threshold)) ||
- (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
- (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
- (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
- (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold))) {
+ (!compare_ff(f_hsv_a[2], f_hsv_b[2], val_threshold)) ||
+ (!compare_ff(gp_style_primary->stroke_rgba[3],
+ gp_style_secondary->stroke_rgba[3],
+ val_threshold)) ||
+ (!compare_ff(
+ gp_style_primary->fill_rgba[3], gp_style_secondary->fill_rgba[3], val_threshold))) {
continue;
}
/* Save conversion indexes. */
- BLI_ghash_insert(
- r_mat_table, POINTER_FROM_INT(idx_secondary), POINTER_FROM_INT(idx_primary));
- changed = true;
+ if (!BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) {
+ BLI_ghash_insert(
+ r_mat_table, POINTER_FROM_INT(idx_secondary), POINTER_FROM_INT(idx_primary));
+ changed = true;
+
+ if (!BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_primary))) {
+ BLI_ghash_insert(mat_used, POINTER_FROM_INT(idx_primary), POINTER_FROM_INT(idx_primary));
+ }
+ }
}
}
+ /* Free hash memory. */
+ BLI_ghash_free(mat_used, NULL, NULL);
+
+ return changed;
+}
+
+/**
+ * Merge similar materials
+ * \param ob: Grease pencil object
+ * \param hue_threshold: Threshold for Hue
+ * \param sat_threshold: Threshold for Saturation
+ * \param val_threshold: Threshold for Value
+ * \param r_removed: Number of materials removed
+ * \return True if done
+ */
+bool BKE_gpencil_merge_materials(Object *ob,
+ const float hue_threshold,
+ const float sat_threshold,
+ const float val_threshold,
+ int *r_removed)
+{
+ bGPdata *gpd = ob->data;
+
+ short *totcol = BKE_object_material_len_p(ob);
+ if (totcol == 0) {
+ *r_removed = 0;
+ return 0;
+ }
+
+ /* Review materials. */
+ GHash *mat_table = BLI_ghash_int_new(__func__);
+
+ bool changed = BKE_gpencil_merge_materials_table_get(
+ ob, hue_threshold, sat_threshold, val_threshold, mat_table);
+
+ *r_removed = BLI_ghash_len(mat_table);
+
+ /* Update stroke material index. */
+ if (changed) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ /* Check if the color is editable. */
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if (gp_style != NULL) {
+ if (gp_style->flag & GP_MATERIAL_HIDE) {
+ continue;
+ }
+ if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) &&
+ (gp_style->flag & GP_MATERIAL_LOCKED)) {
+ continue;
+ }
+ }
+
+ if (BLI_ghash_haskey(mat_table, POINTER_FROM_INT(gps->mat_nr))) {
+ int *idx = BLI_ghash_lookup(mat_table, POINTER_FROM_INT(gps->mat_nr));
+ gps->mat_nr = POINTER_AS_INT(idx);
+ }
+ }
+ }
+ }
+ }
+
+ /* Free hash memory. */
+ BLI_ghash_free(mat_table, NULL, NULL);
return changed;
}
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index eb22927a731..79c41c7c713 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -60,60 +60,111 @@
* \{ */
/* Helper: Check materials with same color. */
-static int gpencil_check_same_material_color(Object *ob_gp, const float color[4], Material **r_mat)
+static int gpencil_check_same_material_color(Object *ob_gp,
+ const float color_stroke[4],
+ const float color_fill[4],
+ const bool do_fill,
+ const bool do_stroke,
+ Material **r_mat)
{
+ int index = -1;
Material *ma = NULL;
+ *r_mat = NULL;
float color_cu[4];
- copy_v4_v4(color_cu, color);
+ float hsv_stroke[4], hsv_fill[4];
+
+ copy_v4_v4(color_cu, color_stroke);
+ zero_v3(hsv_stroke);
+ rgb_to_hsv_v(color_cu, hsv_stroke);
+ hsv_stroke[3] = color_stroke[3];
+
+ copy_v4_v4(color_cu, color_fill);
+ zero_v3(hsv_fill);
+ rgb_to_hsv_v(color_cu, hsv_fill);
+ hsv_fill[3] = color_fill[3];
- float hsv1[4];
- rgb_to_hsv_v(color_cu, hsv1);
- hsv1[3] = color[3];
+ bool match_stroke = false;
+ bool match_fill = false;
for (int i = 1; i <= ob_gp->totcol; i++) {
ma = BKE_object_material_get(ob_gp, i);
MaterialGPencilStyle *gp_style = ma->gp_style;
- /* Check color with small tolerance (better in HSV). */
+ const bool fill = (gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID);
+ const bool stroke = (gp_style->fill_style == GP_MATERIAL_STROKE_STYLE_SOLID);
+
+ if (do_fill && !fill) {
+ continue;
+ }
+
+ if (do_stroke && !stroke) {
+ continue;
+ }
+
+ /* Check color with small tolerance (better result in HSV). */
float hsv2[4];
- rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
- hsv2[3] = gp_style->fill_rgba[3];
- if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) &&
- (compare_v4v4(hsv1, hsv2, 0.01f))) {
- *r_mat = ma;
- return i - 1;
+ if (do_fill) {
+ zero_v3(hsv2);
+ rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
+ hsv2[3] = gp_style->fill_rgba[3];
+ if (compare_v4v4(hsv_fill, hsv2, 0.01f)) {
+ *r_mat = ma;
+ index = i - 1;
+ match_fill = true;
+ }
+ }
+ else {
+ match_fill = true;
+ }
+
+ if (do_stroke) {
+ zero_v3(hsv2);
+ rgb_to_hsv_v(gp_style->stroke_rgba, hsv2);
+ hsv2[3] = gp_style->stroke_rgba[3];
+ if (compare_v4v4(hsv_stroke, hsv2, 0.01f)) {
+ *r_mat = ma;
+ index = i - 1;
+ match_stroke = true;
+ }
+ }
+ else {
+ match_stroke = true;
+ }
+
+ /* If match, don't look for more. */
+ if (match_stroke || match_fill) {
+ break;
}
}
- *r_mat = NULL;
- return -1;
+ if (!match_stroke || !match_fill) {
+ *r_mat = NULL;
+ index = -1;
+ }
+
+ return index;
}
/* Helper: Add gpencil material using curve material as base. */
static Material *gpencil_add_from_curve_material(Main *bmain,
Object *ob_gp,
- const float cu_color[4],
- const bool gpencil_lines,
+ const float stroke_color[4],
+ const float fill_color[4],
+ const bool stroke,
const bool fill,
int *r_idx)
{
- Material *mat_gp = BKE_gpencil_object_material_new(
- bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx);
+ Material *mat_gp = BKE_gpencil_object_material_new(bmain, ob_gp, "Material", r_idx);
MaterialGPencilStyle *gp_style = mat_gp->gp_style;
/* Stroke color. */
- if (gpencil_lines) {
- ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
+ if (stroke) {
+ copy_v4_v4(mat_gp->gp_style->stroke_rgba, stroke_color);
gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
- else {
- copy_v4_v4(mat_gp->gp_style->stroke_rgba, cu_color);
- gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
- }
/* Fill color. */
- copy_v4_v4(mat_gp->gp_style->fill_rgba, cu_color);
- /* Fill is false if the original curve hasn't material assigned, so enable it. */
if (fill) {
+ copy_v4_v4(mat_gp->gp_style->fill_rgba, fill_color);
gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
@@ -128,13 +179,18 @@ static Material *gpencil_add_from_curve_material(Main *bmain,
/* Helper: Create new stroke section. */
static void gpencil_add_new_points(bGPDstroke *gps,
- float *coord_array,
- float pressure,
- int init,
- int totpoints,
+ const float *coord_array,
+ const float pressure_start,
+ const float pressure_end,
+ const int init,
+ const int totpoints,
const float init_co[3],
- bool last)
+ const bool last)
{
+ BLI_assert(totpoints > 0);
+
+ const float step = 1.0f / ((float)totpoints - 1.0f);
+ float factor = 0.0f;
for (int i = 0; i < totpoints; i++) {
bGPDspoint *pt = &gps->points[i + init];
copy_v3_v3(&pt->x, &coord_array[3 * i]);
@@ -149,8 +205,9 @@ static void gpencil_add_new_points(bGPDstroke *gps,
}
}
- pt->pressure = pressure;
pt->strength = 1.0f;
+ pt->pressure = interpf(pressure_end, pressure_start, factor);
+ factor += step;
}
}
@@ -169,18 +226,86 @@ static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob)
return mycol;
}
+static int gpencil_get_stroke_material_fromcurve(
+ Main *bmain, Object *ob_gp, Object *ob_cu, bool *do_stroke, bool *do_fill)
+{
+ Curve *cu = (Curve *)ob_cu->data;
+
+ Material *mat_gp = NULL;
+ Material *mat_curve_stroke = NULL;
+ Material *mat_curve_fill = NULL;
+
+ float color_stroke[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float color_fill[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ /* If the curve has 2 materials, the first is considered as Fill and the second as Stroke.
+ * If the has only one material, if the name contains _stroke, the is used
+ * as stroke, else as fill.*/
+ if (ob_cu->totcol >= 2) {
+ *do_stroke = true;
+ *do_fill = true;
+ mat_curve_fill = BKE_object_material_get(ob_cu, 1);
+ mat_curve_stroke = BKE_object_material_get(ob_cu, 2);
+ }
+ else if (ob_cu->totcol == 1) {
+ mat_curve_stroke = BKE_object_material_get(ob_cu, 1);
+ if ((mat_curve_stroke) && (strstr(mat_curve_stroke->id.name, "_stroke") != NULL)) {
+ *do_stroke = true;
+ *do_fill = false;
+ mat_curve_fill = NULL;
+ }
+ else {
+ *do_stroke = false;
+ *do_fill = true;
+ /* Invert materials. */
+ mat_curve_fill = mat_curve_stroke;
+ mat_curve_stroke = NULL;
+ }
+ }
+ else {
+ /* No materials in the curve. */
+ *do_fill = false;
+ return -1;
+ }
+
+ if (mat_curve_stroke) {
+ copy_v4_v4(color_stroke, &mat_curve_stroke->r);
+ }
+ if (mat_curve_fill) {
+ copy_v4_v4(color_fill, &mat_curve_fill->r);
+ }
+
+ int r_idx = gpencil_check_same_material_color(
+ ob_gp, color_stroke, color_fill, *do_stroke, *do_fill, &mat_gp);
+
+ if ((ob_gp->totcol < r_idx) || (r_idx < 0)) {
+ mat_gp = gpencil_add_from_curve_material(
+ bmain, ob_gp, color_stroke, color_fill, *do_stroke, *do_fill, &r_idx);
+ }
+
+ /* Set fill and stroke depending of curve type (3D or 2D). */
+ if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
+ mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
+ }
+ else {
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
+ }
+
+ return r_idx;
+}
/* Helper: Convert one spline to grease pencil stroke. */
static void gpencil_convert_spline(Main *bmain,
Object *ob_gp,
Object *ob_cu,
const bool gpencil_lines,
- const bool only_stroke,
+ const float scale_thickness,
+ const float sample,
bGPDframe *gpf,
Nurb *nu)
{
- Curve *cu = (Curve *)ob_cu->data;
- bGPdata *gpd = (bGPdata *)ob_gp->data;
bool cyclic = true;
/* Create Stroke. */
@@ -215,75 +340,8 @@ static void gpencil_convert_spline(Main *bmain,
/* Materials
* Notice: The color of the material is the color of viewport and not the final shader color.
*/
- Material *mat_gp = NULL;
- bool fill = true;
- /* Check if grease pencil has a material with same color.*/
- float color[4];
- if ((cu->mat) && (*cu->mat)) {
- Material *mat_cu = *cu->mat;
- copy_v4_v4(color, &mat_cu->r);
- }
- else {
- /* Gray (unassigned from SVG add-on) */
- zero_v4(color);
- add_v3_fl(color, 0.6f);
- color[3] = 1.0f;
- fill = false;
- }
-
- /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and
- * there is only one color, the stroke must not be closed, fill to false and use for
- * stroke the fill color.
- */
- bool do_stroke = false;
- if (ob_cu->totcol == 1) {
- Material *ma_stroke = BKE_object_material_get(ob_cu, 1);
- if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) {
- do_stroke = true;
- }
- }
-
- int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp);
- if ((ob_cu->totcol > 0) && (r_idx < 0)) {
- Material *mat_curve = BKE_object_material_get(ob_cu, 1);
- mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx);
-
- if ((mat_curve) && (mat_curve->gp_style != NULL)) {
- MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style;
- MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style;
-
- copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba);
- gp_style_gp->fill_style = gp_style_cur->fill_style;
- gp_style_gp->mix_factor = gp_style_cur->mix_factor;
- }
-
- /* If object has more than 1 material, use second material for stroke color. */
- if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) {
- mat_curve = BKE_object_material_get(ob_cu, 2);
- if (mat_curve) {
- copy_v4_v4(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
- }
- }
- else if ((only_stroke) || (do_stroke)) {
- /* Also use the first color if the fill is none for stroke color. */
- if (ob_cu->totcol > 0) {
- mat_curve = BKE_object_material_get(ob_cu, 1);
- if (mat_curve) {
- copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
- mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
- /* Set fill and stroke depending of curve type (3D or 2D). */
- if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
- mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
- mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
- }
- else {
- mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
- mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
- }
- }
- }
- }
- }
+ bool do_stroke, do_fill;
+ int r_idx = gpencil_get_stroke_material_fromcurve(bmain, ob_gp, ob_cu, &do_stroke, &do_fill);
CLAMP_MIN(r_idx, 0);
/* Assign material index to stroke. */
@@ -347,7 +405,11 @@ static void gpencil_convert_spline(Main *bmain,
copy_v3_v3(init_co, &coord_array[0]);
}
/* Add points to the stroke */
- gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last);
+ float radius_start = prevbezt->radius * scale_thickness;
+ float radius_end = bezt->radius * scale_thickness;
+
+ gpencil_add_new_points(
+ gps, coord_array, radius_start, radius_end, init, resolu, init_co, last);
/* Free memory. */
MEM_SAFE_FREE(coord_array);
@@ -378,7 +440,7 @@ static void gpencil_convert_spline(Main *bmain,
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
/* Add points. */
- gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false);
+ gpencil_add_new_points(gps, coord_array, 1.0f, 1.0f, 0, gps->totpoints, init_co, false);
MEM_SAFE_FREE(coord_array);
}
@@ -389,10 +451,14 @@ static void gpencil_convert_spline(Main *bmain,
}
}
/* Cyclic curve, close stroke. */
- if ((cyclic) && (!do_stroke)) {
+ if (cyclic) {
BKE_gpencil_stroke_close(gps);
}
+ if (sample > 0.0f) {
+ BKE_gpencil_stroke_sample(gps, sample, false);
+ }
+
/* Recalc fill geometry. */
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
@@ -417,7 +483,8 @@ static void gpencil_editstroke_deselect_all(bGPDcurve *gpc)
* \param ob_cu: Curve to convert.
* \param gpencil_lines: Use lines for strokes.
* \param use_collections: Create layers using collection names.
- * \param only_stroke: The material must be only stroke without fill.
+ * \param scale_thickness: Scale thickness factor.
+ * \param sample: Sample distance, zero to disable.
*/
void BKE_gpencil_convert_curve(Main *bmain,
Scene *scene,
@@ -425,7 +492,8 @@ void BKE_gpencil_convert_curve(Main *bmain,
Object *ob_cu,
const bool gpencil_lines,
const bool use_collections,
- const bool only_stroke)
+ const float scale_thickness,
+ const float sample)
{
if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
return;
@@ -463,11 +531,32 @@ void BKE_gpencil_convert_curve(Main *bmain,
/* Read all splines of the curve and create a stroke for each. */
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
- gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu);
+ gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, scale_thickness, sample, gpf, nu);
+ }
+
+ /* Merge any similar material. */
+ int removed = 0;
+ BKE_gpencil_merge_materials(ob_gp, 0.001f, 0.001f, 0.001f, &removed);
+
+ /* Remove any unused slot. */
+ int actcol = ob_gp->actcol;
+
+ for (int slot = 1; slot <= ob_gp->totcol; slot++) {
+ while (slot <= ob_gp->totcol && !BKE_object_material_slot_used(ob_gp->data, slot)) {
+ ob_gp->actcol = slot;
+ BKE_object_material_slot_remove(bmain, ob_gp);
+
+ if (actcol >= slot) {
+ actcol--;
+ }
+ }
}
+ ob_gp->actcol = actcol;
+
/* Tag for recalculation */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&ob_gp->id, ID_RECALC_GEOMETRY);
}
/** \} */
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index 86c57491393..0997b42a19f 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -234,7 +234,7 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
const int ptex_face_index = data->face_ptex_offset[face_index];
const int grid_size = subdiv_ccg->grid_size;
- const float grid_size_1_inv = 1.0f / (float)(grid_size - 1);
+ const float grid_size_1_inv = 1.0f / (grid_size - 1);
const int element_size = element_size_bytes_get(subdiv_ccg);
SubdivCCGFace *faces = subdiv_ccg->faces;
SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
@@ -243,9 +243,9 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_
const int grid_index = face->start_grid_index + corner;
unsigned char *grid = (unsigned char *)subdiv_ccg->grids[grid_index];
for (int y = 0; y < grid_size; y++) {
- const float grid_v = (float)y * grid_size_1_inv;
+ const float grid_v = y * grid_size_1_inv;
for (int x = 0; x < grid_size; x++) {
- const float grid_u = (float)x * grid_size_1_inv;
+ const float grid_u = x * grid_size_1_inv;
float u, v;
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
const size_t grid_element_index = (size_t)y * grid_size + x;
@@ -265,7 +265,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_
{
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
const int grid_size = subdiv_ccg->grid_size;
- const float grid_size_1_inv = 1.0f / (float)(grid_size - 1);
+ const float grid_size_1_inv = 1.0f / (grid_size - 1);
const int element_size = element_size_bytes_get(subdiv_ccg);
SubdivCCGFace *faces = subdiv_ccg->faces;
SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
@@ -275,9 +275,9 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_
const int ptex_face_index = data->face_ptex_offset[face_index] + corner;
unsigned char *grid = (unsigned char *)subdiv_ccg->grids[grid_index];
for (int y = 0; y < grid_size; y++) {
- const float u = 1.0f - ((float)y * grid_size_1_inv);
+ const float u = 1.0f - (y * grid_size_1_inv);
for (int x = 0; x < grid_size; x++) {
- const float v = 1.0f - ((float)x * grid_size_1_inv);
+ const float v = 1.0f - (x * grid_size_1_inv);
const size_t grid_element_index = (size_t)y * grid_size + x;
const size_t grid_element_offset = grid_element_index * element_size;
subdiv_ccg_eval_grid_element(data, ptex_face_index, u, v, &grid[grid_element_offset]);
@@ -766,7 +766,7 @@ static void subdiv_ccg_average_inner_face_normals(SubdivCCG *subdiv_ccg,
counter++;
}
/* Normalize and store. */
- mul_v3_v3fl(CCG_grid_elem_no(key, grid, x, y), normal_acc, 1.0f / (float)counter);
+ mul_v3_v3fl(CCG_grid_elem_no(key, grid, x, y), normal_acc, 1.0f / counter);
}
}
}
@@ -1009,7 +1009,7 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg,
CCGElem *grid_center_element = CCG_grid_elem(key, grid, 0, 0);
element_accumulator_add(&center_accumulator, subdiv_ccg, key, grid_center_element);
}
- element_accumulator_mul_fl(&center_accumulator, 1.0f / (float)num_face_grids);
+ element_accumulator_mul_fl(&center_accumulator, 1.0f / num_face_grids);
for (int corner = 0; corner < num_face_grids; corner++) {
CCGElem *grid = grids[face->start_grid_index + corner];
CCGElem *grid_center_element = CCG_grid_elem(key, grid, 0, 0);
@@ -1066,7 +1066,7 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG *subdiv_ccg,
}
}
for (int i = 1; i < grid_size2 - 1; i++) {
- element_accumulator_mul_fl(&tls->accumulators[i], 1.0f / (float)num_adjacent_faces);
+ element_accumulator_mul_fl(&tls->accumulators[i], 1.0f / num_adjacent_faces);
}
/* Copy averaged value to all the other faces. */
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
@@ -1118,7 +1118,7 @@ static void subdiv_ccg_average_grids_corners(SubdivCCG *subdiv_ccg,
key, subdiv_ccg, &adjacent_vertex->corner_coords[face_index]);
element_accumulator_add(&accumulator, subdiv_ccg, key, grid_element);
}
- element_accumulator_mul_fl(&accumulator, 1.0f / (float)num_adjacent_faces);
+ element_accumulator_mul_fl(&accumulator, 1.0f / num_adjacent_faces);
/* Copy averaged value to all the other faces. */
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
CCGElem *grid_element = subdiv_ccg_coord_to_elem(
@@ -1933,4 +1933,47 @@ void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index)
subdiv_ccg->grid_hidden[grid_index] = BLI_BITMAP_NEW(key.grid_area, __func__);
}
+static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ int *r_ptex_face_index,
+ float *r_u,
+ float *r_v)
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+
+ const float grid_size = subdiv_ccg->grid_size;
+ const float grid_size_1_inv = 1.0f / (grid_size - 1);
+
+ const float grid_u = coord->x * grid_size_1_inv;
+ const float grid_v = coord->y * grid_size_1_inv;
+
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index);
+ const SubdivCCGFace *faces = subdiv_ccg->faces;
+ const SubdivCCGFace *face = &faces[face_index];
+ const int *face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
+ *r_ptex_face_index = face_ptex_offset[face_index];
+
+ const float corner = coord->grid_index - face->start_grid_index;
+
+ if (face->num_grids == 4) {
+ BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, r_u, r_v);
+ }
+ else {
+ *r_ptex_face_index += corner;
+ *r_u = 1.0f - grid_v;
+ *r_v = 1.0f - grid_u;
+ }
+}
+
+void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG *subdiv_ccg,
+ const SubdivCCGCoord *coord,
+ float r_point[3])
+{
+ Subdiv *subdiv = subdiv_ccg->subdiv;
+ int ptex_face_index;
+ float u, v;
+ subdiv_ccg_coord_to_ptex_coord(subdiv_ccg, coord, &ptex_face_index, &u, &v);
+ BKE_subdiv_eval_limit_point(subdiv, ptex_face_index, u, v, r_point);
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/subdiv_deform.c b/source/blender/blenkernel/intern/subdiv_deform.c
index f03cf4c4d21..2c900fbd600 100644
--- a/source/blender/blenkernel/intern/subdiv_deform.c
+++ b/source/blender/blenkernel/intern/subdiv_deform.c
@@ -214,7 +214,7 @@ void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv,
}
}
- /* Initialize subdivion mesh creation context. */
+ /* Initialize subdivision mesh creation context. */
SubdivDeformContext subdiv_context = {0};
subdiv_context.coarse_mesh = coarse_mesh;
subdiv_context.subdiv = subdiv;
diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c
index 37cca12721a..4400e9c976f 100644
--- a/source/blender/blenkernel/intern/subdiv_foreach.c
+++ b/source/blender/blenkernel/intern/subdiv_foreach.c
@@ -1746,7 +1746,7 @@ static void subdiv_foreach_vertices_of_loose_edges_task(void *__restrict userdat
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
const Mesh *coarse_mesh = ctx->coarse_mesh;
const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index];
- /* Subdivion vertices which corresponds to edge's v1 and v2. */
+ /* Subdivision vertices which corresponds to edge's v1 and v2. */
const int subdiv_v1_index = ctx->vertices_corner_offset + coarse_edge->v1;
const int subdiv_v2_index = ctx->vertices_corner_offset + coarse_edge->v2;
/* First subdivided inner vertex of the edge. */
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index 987cc0311c7..8f97fb82db7 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -1207,7 +1207,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
return NULL;
}
}
- /* Initialize subdivion mesh creation context. */
+ /* Initialize subdivision mesh creation context. */
SubdivMeshContext subdiv_context = {0};
subdiv_context.settings = settings;
subdiv_context.coarse_mesh = coarse_mesh;
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 631961e342d..df0b2b380fa 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -722,6 +722,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
brush->sculpt_tool = SCULPT_TOOL_DRAW_FACE_SETS;
}
+ brush_name = "Multires Displacement Eraser";
+ brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2);
+ if (!brush) {
+ brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT);
+ id_us_min(&brush->id);
+ brush->sculpt_tool = SCULPT_TOOL_DISPLACEMENT_ERASER;
+ }
+
/* Use the same tool icon color in the brush cursor */
for (brush = bmain->brushes.first; brush; brush = brush->id.next) {
if (brush->ob_mode & OB_MODE_SCULPT) {
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index ec3ed05375c..b9c9aa3aec8 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -427,9 +427,8 @@ static FKind get_face_kind(BevelParams *bp, BMFace *f)
/* Are d1 and d2 parallel or nearly so? */
static bool nearly_parallel(const float d1[3], const float d2[3])
{
- float ang;
+ float ang = angle_v3v3(d1, d2);
- ang = angle_v3v3(d1, d2);
return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG);
}
@@ -493,10 +492,8 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, int ifrom, int jfrom, int kfrom)
{
- NewVert *nvto, *nvfrom;
-
- nvto = mesh_vert(vm, ito, jto, kto);
- nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom);
+ NewVert *nvto = mesh_vert(vm, ito, jto, kto);
+ NewVert *nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom);
nvto->v = nvfrom->v;
copy_v3_v3(nvto->co, nvfrom->co);
}
@@ -504,9 +501,7 @@ static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, int ifrom, int
/* Find the EdgeHalf in bv's array that has edge bme. */
static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme)
{
- int i;
-
- for (i = 0; i < bv->edgecount; i++) {
+ for (int i = 0; i < bv->edgecount; i++) {
if (bv->edges[i].e == bme) {
return &bv->edges[i];
}
@@ -527,15 +522,12 @@ static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv)
*/
static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert **r_bvother)
{
- BevVert *bvo;
- EdgeHalf *eother;
-
- bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
+ BevVert *bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
if (bvo) {
if (r_bvother) {
*r_bvother = bvo;
}
- eother = find_edge_half(bvo, e->e);
+ EdgeHalf *eother = find_edge_half(bvo, e->e);
BLI_assert(eother != NULL);
return eother;
}
@@ -549,12 +541,10 @@ static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert
* If from_e is NULL, find the first beveled edge. */
static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
{
- EdgeHalf *e;
-
if (from_e == NULL) {
from_e = &bv->edges[bv->edgecount - 1];
}
- e = from_e;
+ EdgeHalf *e = from_e;
do {
if (e->is_bev) {
return e;
@@ -584,9 +574,8 @@ static int count_ccw_edges_between(EdgeHalf *e1, EdgeHalf *e2)
* where the next or previous edge in the face must be bme2. */
static bool edges_face_connected_at_vert(BMEdge *bme1, BMEdge *bme2)
{
- BMLoop *l;
BMIter iter;
-
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, bme1, BM_LOOPS_OF_EDGE) {
if (l->prev->e == bme2 || l->next->e == bme2) {
return true;
@@ -604,9 +593,9 @@ static bool edges_face_connected_at_vert(BMEdge *bme1, BMEdge *bme2)
*/
static BMFace *boundvert_rep_face(BoundVert *v, BMFace **r_fother)
{
- BMFace *frep, *frep2;
+ BMFace *frep;
- frep2 = NULL;
+ BMFace *frep2 = NULL;
if (v->ebev) {
frep = v->ebev->fprev;
if (v->efirst->fprev != frep) {
@@ -675,20 +664,16 @@ static BMFace *bev_create_ngon(BMesh *bm,
int mat_nr,
bool do_interp)
{
- BMIter iter;
- BMLoop *l;
- BMFace *f, *interp_f;
- BMEdge *bme;
- float save_co[3];
- int i;
-
- f = BM_face_create_verts(bm, vert_arr, totv, facerep, BM_CREATE_NOP, true);
+ BMFace *f = BM_face_create_verts(bm, vert_arr, totv, facerep, BM_CREATE_NOP, true);
if ((facerep || (face_arr && face_arr[0])) && f) {
BM_elem_attrs_copy(bm, bm, facerep ? facerep : face_arr[0], f);
if (do_interp) {
- i = 0;
+ int i = 0;
+ BMIter iter;
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
+ BMFace *interp_f;
if (face_arr) {
/* Assume loops of created face are in same order as verts. */
BLI_assert(l->v == vert_arr[i]);
@@ -698,10 +683,11 @@ static BMFace *bev_create_ngon(BMesh *bm,
interp_f = facerep;
}
if (interp_f) {
- bme = NULL;
+ BMEdge *bme = NULL;
if (edge_arr) {
bme = edge_arr[i];
}
+ float save_co[3];
if (bme) {
copy_v3_v3(save_co, l->v->co);
closest_to_line_segment_v3(l->v->co, save_co, bme->v1->co, bme->v2->co);
@@ -720,6 +706,8 @@ static BMFace *bev_create_ngon(BMesh *bm,
* this is done so the operator can select newly created geometry. */
if (f) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BMIter iter;
+ BMEdge *bme;
BM_ITER_ELEM (bme, &iter, f, BM_EDGES_OF_FACE) {
flag_out_edge(bm, bme);
}
@@ -784,16 +772,11 @@ static bool contig_ldata_across_loops(BMesh *bm, BMLoop *l1, BMLoop *l2, int lay
*/
static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f2)
{
- BMLoop *lef1, *lef2;
- BMLoop *lv1f1, *lv1f2, *lv2f1, *lv2f2;
- BMVert *v1, *v2;
- UNUSED_VARS_NDEBUG(v1, v2);
- int i;
-
if (bm->ldata.totlayer == 0) {
return true;
}
+ BMLoop *lef1, *lef2;
if (!BM_edge_loop_pair(e, &lef1, &lef2)) {
return false;
}
@@ -806,16 +789,17 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
if (lef1->f != f1 || lef2->f != f2) {
return false;
}
- v1 = lef1->v;
- v2 = lef2->v;
+ BMVert *v1 = lef1->v;
+ BMVert *v2 = lef2->v;
BLI_assert((v1 == e->v1 && v2 == e->v2) || (v1 == e->v2 && v2 == e->v1));
- lv1f1 = lef1;
- lv2f1 = lef1->next;
- lv1f2 = lef2->next;
- lv2f2 = lef2;
+ UNUSED_VARS_NDEBUG(v1, v2);
+ BMLoop *lv1f1 = lef1;
+ BMLoop *lv2f1 = lef1->next;
+ BMLoop *lv1f2 = lef2->next;
+ BMLoop *lv2f2 = lef2;
BLI_assert(lv1f1->v == v1 && lv1f1->f == f1 && lv2f1->v == v2 && lv2f1->f == f1 &&
lv1f2->v == v1 && lv1f2->f == f2 && lv2f2->v == v2 && lv2f2->f == f2);
- for (i = 0; i < bm->ldata.totlayer; i++) {
+ for (int i = 0; i < bm->ldata.totlayer; i++) {
if (CustomData_layer_has_math(&bm->ldata, i)) {
if (!contig_ldata_across_loops(bm, lv1f1, lv1f2, i) ||
!contig_ldata_across_loops(bm, lv2f1, lv2f2, i)) {
@@ -834,18 +818,9 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
*/
static void math_layer_info_init(BevelParams *bp, BMesh *bm)
{
- int i, f, stack_top, totface, current_component;
- int bmf_index, bmf_other_index;
- int *face_component;
- BMFace *bmf, *bmf_other;
- BMEdge *bme;
- BMFace **stack;
- bool *in_stack;
- BMIter eiter, fiter;
-
bp->math_layer_info.has_math_layers = false;
bp->math_layer_info.face_component = NULL;
- for (i = 0; i < bm->ldata.totlayer; i++) {
+ for (int i = 0; i < bm->ldata.totlayer; i++) {
if (CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
bp->math_layer_info.has_math_layers = true;
break;
@@ -857,32 +832,32 @@ static void math_layer_info_init(BevelParams *bp, BMesh *bm)
BM_mesh_elem_index_ensure(bm, BM_FACE);
BM_mesh_elem_table_ensure(bm, BM_FACE);
- totface = bm->totface;
- face_component = BLI_memarena_alloc(bp->mem_arena, totface * sizeof(int));
+ int totface = bm->totface;
+ int *face_component = BLI_memarena_alloc(bp->mem_arena, sizeof(int) * totface);
bp->math_layer_info.face_component = face_component;
/* Use an array as a stack. Stack size can't exceed total faces if keep track of what is in
* stack. */
- stack = MEM_malloc_arrayN(totface, sizeof(BMFace *), __func__);
- in_stack = MEM_malloc_arrayN(totface, sizeof(bool), __func__);
+ BMFace **stack = MEM_malloc_arrayN(totface, sizeof(BMFace *), __func__);
+ bool *in_stack = MEM_malloc_arrayN(totface, sizeof(bool), __func__);
/* Set all component ids by DFS from faces with unassigned components. */
- for (f = 0; f < totface; f++) {
+ for (int f = 0; f < totface; f++) {
face_component[f] = -1;
in_stack[f] = false;
}
- current_component = -1;
- for (f = 0; f < totface; f++) {
+ int current_component = -1;
+ for (int f = 0; f < totface; f++) {
if (face_component[f] == -1 && !in_stack[f]) {
- stack_top = 0;
+ int stack_top = 0;
current_component++;
BLI_assert(stack_top < totface);
stack[stack_top] = BM_face_at_index(bm, f);
in_stack[f] = true;
while (stack_top >= 0) {
- bmf = stack[stack_top];
+ BMFace *bmf = stack[stack_top];
stack_top--;
- bmf_index = BM_elem_index_get(bmf);
+ int bmf_index = BM_elem_index_get(bmf);
in_stack[bmf_index] = false;
if (face_component[bmf_index] != -1) {
continue;
@@ -892,10 +867,14 @@ static void math_layer_info_init(BevelParams *bp, BMesh *bm)
* are where contig_ldata_across_edge(...) is true for the
* shared edge and two faces.
*/
+ BMIter eiter;
+ BMEdge *bme;
BM_ITER_ELEM (bme, &eiter, bmf, BM_EDGES_OF_FACE) {
+ BMIter fiter;
+ BMFace *bmf_other;
BM_ITER_ELEM (bmf_other, &fiter, bme, BM_FACES_OF_EDGE) {
if (bmf_other != bmf) {
- bmf_other_index = BM_elem_index_get(bmf_other);
+ int bmf_other_index = BM_elem_index_get(bmf_other);
if (face_component[bmf_other_index] != -1 || in_stack[bmf_other_index]) {
continue;
}
@@ -929,26 +908,22 @@ static void math_layer_info_init(BevelParams *bp, BMesh *bm)
*/
static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
{
- int bmf_index, value_index, best_f, i;
- BMFace *bmf;
- float cent[3];
#define VEC_VALUE_LEN 6
float(*value_vecs)[VEC_VALUE_LEN] = NULL;
- bool *still_viable = NULL;
int num_viable = 0;
value_vecs = BLI_array_alloca(value_vecs, nfaces);
- still_viable = BLI_array_alloca(still_viable, nfaces);
+ bool *still_viable = BLI_array_alloca(still_viable, nfaces);
for (int f = 0; f < nfaces; f++) {
- bmf = face[f];
+ BMFace *bmf = face[f];
if (bmf == NULL) {
still_viable[f] = false;
continue;
}
still_viable[f] = true;
num_viable++;
- bmf_index = BM_elem_index_get(bmf);
- value_index = 0;
+ int bmf_index = BM_elem_index_get(bmf);
+ int value_index = 0;
/* First tie-breaker: lower math-layer connected component id. */
value_vecs[f][value_index++] = bp->math_layer_info.face_component ?
(float)bp->math_layer_info.face_component[bmf_index] :
@@ -958,6 +933,7 @@ static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
/* Next tie-breaker: lower material index. */
value_vecs[f][value_index++] = bmf->mat_nr >= 0 ? (float)bmf->mat_nr : 0.0f;
/* Next three tie-breakers: z, x, y components of face center. */
+ float cent[3];
BM_face_calc_center_bounds(bmf, cent);
value_vecs[f][value_index++] = cent[2];
value_vecs[f][value_index++] = cent[0];
@@ -968,8 +944,8 @@ static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
/* Look for a face that has a unique minimum value for in a value_index,
* trying each value_index in turn until find a unique minimum.
*/
- best_f = -1;
- for (value_index = 0; num_viable > 1 && value_index < VEC_VALUE_LEN; value_index++) {
+ int best_f = -1;
+ for (int value_index = 0; num_viable > 1 && value_index < VEC_VALUE_LEN; value_index++) {
for (int f = 0; f < nfaces; f++) {
if (!still_viable[f] || f == best_f) {
continue;
@@ -981,7 +957,7 @@ static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
if (value_vecs[f][value_index] < value_vecs[best_f][value_index]) {
best_f = f;
/* Previous f's are now not viable any more. */
- for (i = f - 1; i >= 0; i--) {
+ for (int i = f - 1; i >= 0; i--) {
if (still_viable[i]) {
still_viable[i] = false;
num_viable--;
@@ -1005,32 +981,28 @@ static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
* Caller should ensure that no seams are violated by doing this. */
static void bev_merge_uvs(BMesh *bm, BMVert *v)
{
- BMIter iter;
- MLoopUV *luv;
- BMLoop *l;
- float uv[2];
- int n;
int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
- int i;
- for (i = 0; i < num_of_uv_layers; i++) {
+ for (int i = 0; i < num_of_uv_layers; i++) {
int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
if (cd_loop_uv_offset == -1) {
return;
}
- n = 0;
- zero_v2(uv);
+ int n = 0;
+ float uv[2] = {0.0f, 0.0f};
+ BMIter iter;
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
n++;
}
if (n > 1) {
mul_v2_fl(uv, 1.0f / (float)n);
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(luv->uv, uv);
}
}
@@ -1041,15 +1013,12 @@ static void bev_merge_uvs(BMesh *bm, BMVert *v)
* and part of faces that share edge bme. */
static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
{
- BMIter iter;
- MLoopUV *luv;
- BMLoop *l, *l1, *l2;
- float uv[2];
int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
- int i;
- l1 = NULL;
- l2 = NULL;
+ BMLoop *l1 = NULL;
+ BMLoop *l2 = NULL;
+ BMIter iter;
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
if (l->e == bme) {
l1 = l;
@@ -1062,15 +1031,15 @@ static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
return;
}
- for (i = 0; i < num_of_uv_layers; i++) {
+ for (int i = 0; i < num_of_uv_layers; i++) {
int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
if (cd_loop_uv_offset == -1) {
return;
}
- zero_v2(uv);
- luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
+ float uv[2] = {0.0f, 0.0f};
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
@@ -1085,10 +1054,10 @@ static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco. */
static void slide_dist(EdgeHalf *e, BMVert *v, float d, float r_slideco[3])
{
- float dir[3], len;
-
+ float dir[3];
sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co);
- len = normalize_v3(dir);
+ float len = normalize_v3(dir);
+
if (d > len) {
d = len - (float)(50.0 * BEVEL_EPSILON_D);
}
@@ -1099,12 +1068,13 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float r_slideco[3])
/* Is co not on the edge e? If not, return the closer end of e in ret_closer_v. */
static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_v)
{
- float h[3], u[3], lambda, lenu, *l1 = e->e->v1->co;
+ float h[3], u[3];
+ float *l1 = e->e->v1->co;
sub_v3_v3v3(u, e->e->v2->co, l1);
sub_v3_v3v3(h, co, l1);
- lenu = normalize_v3(u);
- lambda = dot_v3v3(u, h);
+ float lenu = normalize_v3(u);
+ float lambda = dot_v3v3(u, h);
if (lambda <= -BEVEL_EPSILON_BIG * lenu) {
*ret_closer_v = e->e->v1;
return true;
@@ -1119,18 +1089,18 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
/* Return whether the angle is less than, equal to, or larger than 180 degrees. */
static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
{
- BMVert *v1, *v2;
- float dir1[3], dir2[3], cross[3], *no, dot;
-
- v1 = BM_edge_other_vert(e1->e, v);
- v2 = BM_edge_other_vert(e2->e, v);
+ BMVert *v1 = BM_edge_other_vert(e1->e, v);
+ BMVert *v2 = BM_edge_other_vert(e2->e, v);
+ float dir1[3], dir2[3];
sub_v3_v3v3(dir1, v->co, v1->co);
sub_v3_v3v3(dir2, v->co, v2->co);
normalize_v3(dir1);
normalize_v3(dir2);
/* Angles are in [0,pi]. Need to compare cross product with normal to see if they are reflex. */
+ float cross[3];
cross_v3_v3v3(cross, dir1, dir2);
normalize_v3(cross);
+ float *no;
if (e1->fnext) {
no = e1->fnext->no;
}
@@ -1140,7 +1110,7 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
else {
no = v->no;
}
- dot = dot_v3v3(cross, no);
+ float dot = dot_v3v3(cross, no);
if (fabsf(dot) < BEVEL_EPSILON_BIG) {
return ANGLE_STRAIGHT;
}
@@ -1155,20 +1125,18 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
static bool point_between_edges(
const float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, EdgeHalf *e2)
{
- BMVert *v1, *v2;
float dir1[3], dir2[3], dirco[3], no[3];
- float ang11, ang1co;
- v1 = BM_edge_other_vert(e1->e, v);
- v2 = BM_edge_other_vert(e2->e, v);
+ BMVert *v1 = BM_edge_other_vert(e1->e, v);
+ BMVert *v2 = BM_edge_other_vert(e2->e, v);
sub_v3_v3v3(dir1, v->co, v1->co);
sub_v3_v3v3(dir2, v->co, v2->co);
sub_v3_v3v3(dirco, v->co, co);
normalize_v3(dir1);
normalize_v3(dir2);
normalize_v3(dirco);
- ang11 = angle_normalized_v3v3(dir1, dir2);
- ang1co = angle_normalized_v3v3(dir1, dirco);
+ float ang11 = angle_normalized_v3v3(dir1, dir2);
+ float ang1co = angle_normalized_v3v3(dir1, dirco);
/* Angles are in [0,pi]. Need to compare cross product with normal to see if they are reflex. */
cross_v3_v3v3(no, dir1, dir2);
if (dot_v3v3(no, f->no) < 0.0f) {
@@ -1207,22 +1175,15 @@ static void offset_meet(EdgeHalf *e1,
float meetco[3],
const EdgeHalf *e_in_plane)
{
- float dir1[3], dir2[3], dir1n[3], dir2p[3], norm_v[3], norm_v1[3], norm_v2[3];
- float norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3];
- float isect2[3], dropco[3], plane[4];
- float ang, d;
- BMVert *closer_v;
- EdgeHalf *e, *e1next, *e2prev;
- BMFace *fnext;
- int isect_kind;
-
/* Get direction vectors for two offset lines. */
+ float dir1[3], dir2[3];
sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
+ float dir1n[3], dir2p[3];
if (edges_between) {
- e1next = e1->next;
- e2prev = e2->prev;
+ EdgeHalf *e1next = e1->next;
+ EdgeHalf *e2prev = e2->prev;
sub_v3_v3v3(dir1n, BM_edge_other_vert(e1next->e, v)->co, v->co);
sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
}
@@ -1232,7 +1193,8 @@ static void offset_meet(EdgeHalf *e1,
zero_v3(dir2p);
}
- ang = angle_v3v3(dir1, dir2);
+ float ang = angle_v3v3(dir1, dir2);
+ float norm_perp1[3];
if (ang < BEVEL_EPSILON_ANG) {
/* Special case: e1 and e2 are parallel; put offset point perp to both, from v.
* need to find a suitable plane.
@@ -1242,6 +1204,7 @@ static void offset_meet(EdgeHalf *e1,
* If offsets are different, we're out of luck:
* Use the max of the two (so get consistent looking results if the same situation
* arises elsewhere in the object but with opposite roles for e1 and e2. */
+ float norm_v[3];
if (f) {
copy_v3_v3(norm_v, f->no);
}
@@ -1251,8 +1214,9 @@ static void offset_meet(EdgeHalf *e1,
add_v3_v3(dir1, dir2);
cross_v3_v3v3(norm_perp1, dir1, norm_v);
normalize_v3(norm_perp1);
+ float off1a[3];
copy_v3_v3(off1a, v->co);
- d = max_ff(e1->offset_r, e2->offset_l);
+ float d = max_ff(e1->offset_r, e2->offset_l);
d = d / cosf(ang / 2.0f);
madd_v3_v3fl(off1a, norm_perp1, d);
copy_v3_v3(meetco, off1a);
@@ -1260,7 +1224,7 @@ static void offset_meet(EdgeHalf *e1,
else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
/* Special case: e1 and e2 are antiparallel, so bevel is into a zero-area face.
* Just make the offset point on the common line, at offset distance from v. */
- d = max_ff(e1->offset_r, e2->offset_l);
+ float d = max_ff(e1->offset_r, e2->offset_l);
slide_dist(e2, v, d, meetco);
}
else {
@@ -1273,6 +1237,7 @@ static void offset_meet(EdgeHalf *e1,
* If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
* Use f->no to figure out which side to look at angle from, as even if f is non-planar,
* will be more accurate than vertex normal. */
+ float norm_v1[3], norm_v2[3];
if (f && ang < BEVEL_SMALL_ANG) {
copy_v3_v3(norm_v1, f->no);
copy_v3_v3(norm_v2, f->no);
@@ -1302,12 +1267,14 @@ static void offset_meet(EdgeHalf *e1,
}
/* Get vectors perp to each edge, perp to norm_v, and pointing into face. */
+ float norm_perp2[3];
cross_v3_v3v3(norm_perp1, dir1, norm_v1);
cross_v3_v3v3(norm_perp2, dir2, norm_v2);
normalize_v3(norm_perp1);
normalize_v3(norm_perp2);
/* Get points that are offset distances from each line, then another point on each line. */
+ float off1a[3], off1b[3], off2a[3], off2b[3];
copy_v3_v3(off1a, v->co);
madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
add_v3_v3v3(off1b, off1a, dir1);
@@ -1316,7 +1283,8 @@ static void offset_meet(EdgeHalf *e1,
add_v3_v3v3(off2b, off2a, dir2);
/* Intersect the offset lines. */
- isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
+ float isect2[3];
+ int isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
if (isect_kind == 0) {
/* Lines are collinear: we already tested for this, but this used a different epsilon. */
copy_v3_v3(meetco, off1a); /* Just to do something. */
@@ -1326,6 +1294,7 @@ static void offset_meet(EdgeHalf *e1,
* One problem to check: if one of the offsets is 0, then we don't want an intersection
* that is outside that edge itself. This can happen if angle between them is > 180 degrees,
* or if the offset amount is > the edge length. */
+ BMVert *closer_v;
if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) {
copy_v3_v3(meetco, closer_v->co);
}
@@ -1338,12 +1307,14 @@ static void offset_meet(EdgeHalf *e1,
/* Lines didn't meet in 3d: get average of meetco and isect2. */
mid_v3_v3v3(meetco, meetco, isect2);
}
- for (e = e1; e != e2; e = e->next) {
- fnext = e->fnext;
+ for (EdgeHalf *e = e1; e != e2; e = e->next) {
+ BMFace *fnext = e->fnext;
if (!fnext) {
continue;
}
+ float plane[4];
plane_from_point_normal_v3(plane, v->co, fnext->no);
+ float dropco[3];
closest_to_plane_normalized_v3(dropco, plane, meetco);
/* Don't drop to the faces next to the in plane edge. */
if (e_in_plane) {
@@ -1376,21 +1347,21 @@ static void offset_meet(EdgeHalf *e1,
static bool offset_meet_edge(
EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetco[3], float *r_angle)
{
- float dir1[3], dir2[3], fno[3], ang, sinang;
-
+ float dir1[3], dir2[3];
sub_v3_v3v3(dir1, BM_edge_other_vert(e1->e, v)->co, v->co);
sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
normalize_v3(dir1);
normalize_v3(dir2);
/* Find angle from dir1 to dir2 as viewed from vertex normal side. */
- ang = angle_normalized_v3v3(dir1, dir2);
+ float ang = angle_normalized_v3v3(dir1, dir2);
if (fabsf(ang) < BEVEL_GOOD_ANGLE) {
if (r_angle) {
*r_angle = 0.0f;
}
return false;
}
+ float fno[3];
cross_v3_v3v3(fno, dir1, dir2);
if (dot_v3v3(fno, v->no) < 0.0f) {
ang = 2.0f * (float)M_PI - ang; /* Angle is reflex. */
@@ -1407,7 +1378,7 @@ static bool offset_meet_edge(
return false;
}
- sinang = sinf(ang);
+ float sinang = sinf(ang);
copy_v3_v3(meetco, v->co);
if (e1->offset_r == 0.0f) {
@@ -1440,15 +1411,14 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em
static bool offset_on_edge_between(
EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v, float meetco[3], float *r_sinratio)
{
- float ang1, ang2;
- float meet1[3], meet2[3];
- bool ok1, ok2;
bool retval = false;
BLI_assert(e1->is_bev && e2->is_bev && !emid->is_bev);
- ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
- ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
+ float ang1, ang2;
+ float meet1[3], meet2[3];
+ bool ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
+ bool ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
if (ok1 && ok2) {
mid_v3_v3v3(meetco, meet1, meet2);
if (r_sinratio) {
@@ -1476,11 +1446,9 @@ static bool offset_on_edge_between(
* If plane_no is NULL, choose an arbitrary plane different from eh's direction. */
static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, float r_co[3])
{
- float dir[3], no[3], fdir[3];
- BMVert *v;
-
- v = e->is_rev ? e->e->v2 : e->e->v1;
+ BMVert *v = e->is_rev ? e->e->v2 : e->e->v1;
+ float dir[3], no[3];
sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co);
normalize_v3(dir);
if (plane_no) {
@@ -1495,6 +1463,8 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, flo
no[1] = 1.0f;
}
}
+
+ float fdir[3];
if (left) {
cross_v3_v3v3(fdir, dir, no);
}
@@ -1513,7 +1483,6 @@ static void project_to_edge(const BMEdge *e,
float projco[3])
{
float otherco[3];
-
if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) {
#ifdef BEVEL_ASSERT_PROJECT
BLI_assert(!"project meet failure");
@@ -1526,11 +1495,11 @@ static void project_to_edge(const BMEdge *e,
* It is the closest point on the beveled edge to the line segment between bndv and bndv->next. */
static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
{
- float start[3], end[3], co3[3], d1[3], d2[3];
bool do_linear_interp = true;
EdgeHalf *e = bndv->ebev;
Profile *pro = &bndv->profile;
+ float start[3], end[3];
copy_v3_v3(start, bndv->nv.co);
copy_v3_v3(end, bndv->next->nv.co);
if (e) {
@@ -1546,6 +1515,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
copy_v3_v3(pro->start, start);
copy_v3_v3(pro->end, end);
/* Default plane to project onto is the one with triangle start - middle - end in it. */
+ float d1[3], d2[3];
sub_v3_v3v3(d1, pro->middle, start);
sub_v3_v3v3(d2, pro->middle, end);
normalize_v3(d1);
@@ -1577,6 +1547,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
do_linear_interp = true;
}
else {
+ float co3[3];
add_v3_v3v3(co3, start, d3);
add_v3_v3v3(co4, end, d4);
isect_kind = isect_line_line_v3(start, co3, end, co4, meetco, isect2);
@@ -1650,24 +1621,27 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
*/
static void move_profile_plane(BoundVert *bndv, BMVert *bmvert)
{
- float d1[3], d2[3], no[3], no2[3], no3[3], dot2, dot3;
Profile *pro = &bndv->profile;
/* Only do this if projecting, and start, end, and proj_dir are not coplanar. */
if (is_zero_v3(pro->proj_dir)) {
return;
}
+
+ float d1[3], d2[3];
sub_v3_v3v3(d1, bmvert->co, pro->start);
normalize_v3(d1);
sub_v3_v3v3(d2, bmvert->co, pro->end);
normalize_v3(d2);
+ float no[3], no2[3], no3[3];
cross_v3_v3v3(no, d1, d2);
cross_v3_v3v3(no2, d1, pro->proj_dir);
cross_v3_v3v3(no3, d2, pro->proj_dir);
+
if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG &&
normalize_v3(no3) > BEVEL_EPSILON_BIG) {
- dot2 = dot_v3v3(no, no2);
- dot3 = dot_v3v3(no, no3);
+ float dot2 = dot_v3v3(no, no2);
+ float dot3 = dot_v3v3(no, no3);
if (fabsf(dot2) < (1 - BEVEL_EPSILON_BIG) && fabsf(dot3) < (1 - BEVEL_EPSILON_BIG)) {
copy_v3_v3(bndv->profile.plane_no, no);
}
@@ -1686,25 +1660,26 @@ static void move_profile_plane(BoundVert *bndv, BMVert *bmvert)
*/
static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *bndv2)
{
- float d1[3], d2[3], no[3], no2[3], no3[3], dot1, dot2, l1, l2, l3;
-
/* Only do this if projecting, and d1, d2, and proj_dir are not coplanar. */
if (is_zero_v3(bndv1->profile.proj_dir) || is_zero_v3(bndv2->profile.proj_dir)) {
return;
}
+ float d1[3], d2[3], no[3];
sub_v3_v3v3(d1, bv->v->co, bndv1->nv.co);
sub_v3_v3v3(d2, bv->v->co, bndv2->nv.co);
cross_v3_v3v3(no, d1, d2);
- l1 = normalize_v3(no);
+ float l1 = normalize_v3(no);
+
/* "no" is new normal projection plane, but don't move if it is coplanar with both of the
* projection dirs. */
+ float no2[3], no3[3];
cross_v3_v3v3(no2, d1, bndv1->profile.proj_dir);
- l2 = normalize_v3(no2);
+ float l2 = normalize_v3(no2);
cross_v3_v3v3(no3, d2, bndv2->profile.proj_dir);
- l3 = normalize_v3(no3);
+ float l3 = normalize_v3(no3);
if (l1 > BEVEL_EPSILON && (l2 > BEVEL_EPSILON || l3 > BEVEL_EPSILON)) {
- dot1 = fabsf(dot_v3v3(no, no2));
- dot2 = fabsf(dot_v3v3(no, no3));
+ float dot1 = fabsf(dot_v3v3(no, no2));
+ float dot2 = fabsf(dot_v3v3(no, no3));
if (fabsf(dot1 - 1.0f) > BEVEL_EPSILON) {
copy_v3_v3(bndv1->profile.plane_no, no);
}
@@ -1722,13 +1697,11 @@ static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *b
* and -1 if they are reversed, and 0 if there is no shared face f. */
static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
{
- BMLoop *la, *lb;
-
if (!f) {
return 0;
}
- la = BM_face_edge_share_loop(f, a);
- lb = BM_face_edge_share_loop(f, b);
+ BMLoop *la = BM_face_edge_share_loop(f, a);
+ BMLoop *lb = BM_face_edge_share_loop(f, b);
if (!la || !lb) {
return 0;
}
@@ -1761,8 +1734,7 @@ static bool make_unit_square_map(const float va[3],
const float vb[3],
float r_mat[4][4])
{
- float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3];
-
+ float vb_vmid[3], va_vmid[3];
sub_v3_v3v3(va_vmid, vmid, va);
sub_v3_v3v3(vb_vmid, vmid, vb);
@@ -1774,6 +1746,7 @@ static bool make_unit_square_map(const float va[3],
return false;
}
+ float vo[3], vd[3], vddir[3];
sub_v3_v3v3(vo, va, vb_vmid);
cross_v3_v3v3(vddir, vb_vmid, va_vmid);
normalize_v3(vddir);
@@ -1871,8 +1844,6 @@ static double superellipse_co(double x, float r, bool rbig)
*/
static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int nseg, float r_co[3])
{
- int subsample_spacing;
-
if (bp->seg == 1) {
if (i == 0) {
copy_v3_v3(r_co, pro->start);
@@ -1890,7 +1861,7 @@ static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int ns
else {
BLI_assert(is_power_of_2_i(nseg) && nseg <= bp->pro_spacing.seg_2);
/* Find spacing between subsamples in prof_co_2. */
- subsample_spacing = bp->pro_spacing.seg_2 / nseg;
+ int subsample_spacing = bp->pro_spacing.seg_2 / nseg;
copy_v3_v3(r_co, pro->prof_co_2 + 3 * i * subsample_spacing);
}
}
@@ -2022,16 +1993,18 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
*/
static void snap_to_superellipsoid(float co[3], const float super_r, bool midline)
{
- float a, b, c, x, y, z, r, rinv, dx, dy;
- r = super_r;
+ float r = super_r;
if (r == PRO_CIRCLE_R) {
normalize_v3(co);
return;
}
- x = a = max_ff(0.0f, co[0]);
- y = b = max_ff(0.0f, co[1]);
- z = c = max_ff(0.0f, co[2]);
+ float a = max_ff(0.0f, co[0]);
+ float b = max_ff(0.0f, co[1]);
+ float c = max_ff(0.0f, co[2]);
+ float x = a;
+ float y = b;
+ float z = c;
if (r == PRO_SQUARE_R || r == PRO_SQUARE_IN_R) {
/* Will only be called for 2d profile. */
BLI_assert(fabsf(z) < BEVEL_EPSILON);
@@ -2040,8 +2013,8 @@ static void snap_to_superellipsoid(float co[3], const float super_r, bool midlin
y = min_ff(1.0f, y);
if (r == PRO_SQUARE_R) {
/* Snap to closer of x==1 and y==1 lines, or maybe both. */
- dx = 1.0f - x;
- dy = 1.0f - y;
+ float dx = 1.0f - x;
+ float dy = 1.0f - y;
if (dx < dy) {
x = 1.0f;
y = midline ? 1.0f : y;
@@ -2064,7 +2037,7 @@ static void snap_to_superellipsoid(float co[3], const float super_r, bool midlin
}
}
else {
- rinv = 1.0f / r;
+ float rinv = 1.0f / r;
if (a == 0.0f) {
if (b == 0.0f) {
x = 0.0f;
@@ -2249,11 +2222,8 @@ static void bevel_extend_edge_data(BevVert *bv)
/* Mark edges as sharp if they are between a smooth reconstructed face and a new face. */
static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp)
{
- BMIter fiter, liter;
- BMFace *f, *fother;
- BMLoop *l, *lother;
- FKind fkind;
-
+ BMIter fiter;
+ BMFace *f;
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
continue;
@@ -2261,12 +2231,14 @@ static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp)
if (get_face_kind(bp, f) != F_RECON) {
continue;
}
+ BMIter liter;
+ BMLoop *l;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
/* Cases we care about will have exactly one adjacent face. */
- lother = l->radial_next;
- fother = lother->f;
+ BMLoop *lother = l->radial_next;
+ BMFace *fother = lother->f;
if (lother != l && fother) {
- fkind = get_face_kind(bp, lother->f);
+ FKind fkind = get_face_kind(bp, lother->f);
if (ELEM(fkind, F_EDGE, F_VERT)) {
BM_elem_flag_disable(l->e, BM_ELEM_SMOOTH);
}
@@ -2285,15 +2257,6 @@ static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp)
*/
static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
{
- BMIter liter, fiter;
- BMFace *f;
- BMLoop *l, *lnext, *lprev, *lprevprev, *lnextnext;
- BMEdge *estep;
- FKind fkind, fprevkind, fnextkind, fprevprevkind, fnextnextkind;
- int cd_clnors_offset, l_index;
- short *clnors;
- float *pnorm, norm[3];
-
if (bp->offset == 0.0 || !bp->harden_normals) {
return;
}
@@ -2302,7 +2265,7 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
/* I suspect this is not necessary. TODO: test that guess. */
BM_mesh_normals_update(bm);
- cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
/* If there is not already a custom split normal layer then making one (with BM_lnorspace_update)
* will not respect the autosmooth angle between smooth faces. To get that to happen, we have
@@ -2321,19 +2284,25 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
}
+ BMIter fiter;
+ BMFace *f;
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- fkind = get_face_kind(bp, f);
+ FKind fkind = get_face_kind(bp, f);
if (fkind == F_ORIG || fkind == F_RECON) {
continue;
}
+ BMIter liter;
+ BMLoop *l;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- estep = l->prev->e; /* Causes CW walk around l->v fan. */
- lprev = BM_vert_step_fan_loop(l, &estep);
+ BMEdge *estep = l->prev->e; /* Causes CW walk around l->v fan. */
+ BMLoop *lprev = BM_vert_step_fan_loop(l, &estep);
estep = l->e; /* Causes CCW walk around l->v fan. */
- lnext = BM_vert_step_fan_loop(l, &estep);
- fprevkind = lprev ? get_face_kind(bp, lprev->f) : F_NONE;
- fnextkind = lnext ? get_face_kind(bp, lnext->f) : F_NONE;
- pnorm = NULL;
+ BMLoop *lnext = BM_vert_step_fan_loop(l, &estep);
+ FKind fprevkind = lprev ? get_face_kind(bp, lprev->f) : F_NONE;
+ FKind fnextkind = lnext ? get_face_kind(bp, lnext->f) : F_NONE;
+
+ float norm[3];
+ float *pnorm = NULL;
if (fkind == F_EDGE) {
if (fprevkind == F_EDGE && BM_elem_flag_test(l, BM_ELEM_LONG_TAG)) {
add_v3_v3v3(norm, f->no, lprev->f->no);
@@ -2364,6 +2333,7 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
pnorm = lnext->f->no;
}
else {
+ BMLoop *lprevprev, *lnextnext;
if (lprev) {
estep = lprev->prev->e;
lprevprev = BM_vert_step_fan_loop(lprev, &estep);
@@ -2378,8 +2348,8 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
else {
lnextnext = NULL;
}
- fprevprevkind = lprevprev ? get_face_kind(bp, lprevprev->f) : F_NONE;
- fnextnextkind = lnextnext ? get_face_kind(bp, lnextnext->f) : F_NONE;
+ FKind fprevprevkind = lprevprev ? get_face_kind(bp, lprevprev->f) : F_NONE;
+ FKind fnextnextkind = lnextnext ? get_face_kind(bp, lnextnext->f) : F_NONE;
if (fprevkind == F_EDGE && fprevprevkind == F_RECON) {
pnorm = lprevprev->f->no;
}
@@ -2400,8 +2370,8 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
if (pnorm == norm) {
normalize_v3(norm);
}
- l_index = BM_elem_index_get(l);
- clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], pnorm, clnors);
}
}
@@ -2410,12 +2380,7 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
static void bevel_set_weighted_normal_face_strength(BMesh *bm, BevelParams *bp)
{
- BMFace *f;
- BMIter fiter;
- FKind fkind;
- int strength;
- int mode = bp->face_strength_mode;
- bool do_set_strength;
+ const int mode = bp->face_strength_mode;
const char *wn_layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
int cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT32, wn_layer_id);
@@ -2427,9 +2392,12 @@ static void bevel_set_weighted_normal_face_strength(BMesh *bm, BevelParams *bp)
const int cd_prop_int_offset = CustomData_get_n_offset(
&bm->pdata, CD_PROP_INT32, cd_prop_int_idx);
+ BMIter fiter;
+ BMFace *f;
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- fkind = get_face_kind(bp, f);
- do_set_strength = true;
+ FKind fkind = get_face_kind(bp, f);
+ bool do_set_strength = true;
+ int strength;
switch (fkind) {
case F_VERT:
strength = FACE_STRENGTH_WEAK;
@@ -2460,14 +2428,11 @@ static void bevel_set_weighted_normal_face_strength(BMesh *bm, BevelParams *bp)
/* Set the any_seam property for a BevVert and all its BoundVerts. */
static void set_bound_vert_seams(BevVert *bv, bool mark_seam, bool mark_sharp)
{
- BoundVert *v;
- EdgeHalf *e;
-
bv->any_seam = false;
- v = bv->vmesh->boundstart;
+ BoundVert *v = bv->vmesh->boundstart;
do {
v->any_seam = false;
- for (e = v->efirst; e; e = e->next) {
+ for (EdgeHalf *e = v->efirst; e; e = e->next) {
v->any_seam |= e->is_seam;
if (e == v->elast) {
break;
@@ -2486,14 +2451,12 @@ static void set_bound_vert_seams(BevVert *bv, bool mark_seam, bool mark_sharp)
static int count_bound_vert_seams(BevVert *bv)
{
- int ans, i;
-
if (!bv->any_seam) {
return 0;
}
- ans = 0;
- for (i = 0; i < bv->edgecount; i++) {
+ int ans = 0;
+ for (int i = 0; i < bv->edgecount; i++) {
if (bv->edges[i].is_seam) {
ans++;
}
@@ -2504,10 +2467,8 @@ static int count_bound_vert_seams(BevVert *bv)
/* Is e between two faces with a 180 degree angle between their normals? */
static bool eh_on_plane(EdgeHalf *e)
{
- float dot;
-
if (e->fprev && e->fnext) {
- dot = dot_v3v3(e->fprev->no, e->fnext->no);
+ float dot = dot_v3v3(e->fprev->no, e->fnext->no);
if (fabsf(dot + 1.0f) <= BEVEL_EPSILON_BIG || fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG) {
return true;
}
@@ -2545,17 +2506,16 @@ static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool construct)
{
VMesh *vm = bv->vmesh;
- EdgeHalf *efirst, *e;
- BoundVert *v;
- float co[3];
BLI_assert(bp->affect_type == BEVEL_AFFECT_VERTICES);
- e = efirst = &bv->edges[0];
+ EdgeHalf *efirst = &bv->edges[0];
+ EdgeHalf *e = efirst;
do {
+ float co[3];
slide_dist(e, bv->v, e->offset_l, co);
if (construct) {
- v = add_new_bound_vert(bp->mem_arena, vm, co);
+ BoundVert *v = add_new_bound_vert(bp->mem_arena, vm, co);
v->efirst = v->elast = e;
e->leftv = e->rightv = v;
}
@@ -2590,19 +2550,15 @@ static void build_boundary_terminal_edge(BevelParams *bp,
{
MemArena *mem_arena = bp->mem_arena;
VMesh *vm = bv->vmesh;
- BoundVert *bndv;
- EdgeHalf *e;
- const float *no;
- float co[3], d;
- bool use_tri_fan;
- e = efirst;
+ EdgeHalf *e = efirst;
+ float co[3];
if (bv->edgecount == 2) {
/* Only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge. */
- no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
+ const float *no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
offset_in_plane(e, no, true, co);
if (construct) {
- bndv = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = bndv->elast = bndv->ebev = e;
e->leftv = bndv;
}
@@ -2612,7 +2568,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL);
offset_in_plane(e, no, false, co);
if (construct) {
- bndv = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = bndv->elast = e;
e->rightv = bndv;
}
@@ -2622,7 +2578,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
/* Make artificial extra point along unbeveled edge, and form triangle. */
slide_dist(e->next, bv->v, e->offset_l, co);
if (construct) {
- bndv = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = bndv->elast = e->next;
e->next->leftv = e->next->rightv = bndv;
set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
@@ -2638,7 +2594,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
/* TODO: should do something else if angle between e and e->prev > 180 */
offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
if (construct) {
- bndv = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
bndv->elast = bndv->ebev = e;
e->leftv = bndv;
@@ -2650,7 +2606,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
e = e->next;
offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
if (construct) {
- bndv = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
bndv->elast = e;
e->leftv = e->rightv = bndv;
@@ -2660,14 +2616,14 @@ static void build_boundary_terminal_edge(BevelParams *bp,
adjust_bound_vert(e->leftv, co);
}
/* For the edges not adjacent to the beveled edge, slide the bevel amount along. */
- d = efirst->offset_l_spec;
+ float d = efirst->offset_l_spec;
if (bp->profile_type == BEVEL_PROFILE_CUSTOM || bp->profile < 0.25f) {
d *= sqrtf(2.0f); /* Need to go further along the edge to make room for full profile area. */
}
for (e = e->next; e->next != efirst; e = e->next) {
slide_dist(e, bv->v, d, co);
if (construct) {
- bndv = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = bndv->elast = e;
e->leftv = e->rightv = bndv;
}
@@ -2679,7 +2635,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
if (bv->edgecount >= 3) {
/* Special case: snap profile to plane of adjacent two edges. */
- bndv = vm->boundstart;
+ BoundVert *bndv = vm->boundstart;
BLI_assert(bndv->ebev != NULL);
set_profile_params(bp, bv, bndv);
move_profile_plane(bndv, bv->v);
@@ -2692,10 +2648,10 @@ static void build_boundary_terminal_edge(BevelParams *bp,
vm->mesh_kind = M_NONE;
}
else if (vm->count == 3) {
- use_tri_fan = true;
+ bool use_tri_fan = true;
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Prevent overhanging edges: use M_POLY if the extra point is planar with the profile. */
- bndv = efirst->leftv;
+ BoundVert *bndv = efirst->leftv;
float profile_plane[4];
plane_from_point_normal_v3(profile_plane, bndv->profile.plane_co, bndv->profile.plane_no);
bndv = efirst->rightv->next; /* The added boundvert placed along the non-adjacent edge. */
@@ -2714,13 +2670,10 @@ static void build_boundary_terminal_edge(BevelParams *bp,
/* Helper for build_boundary to handle special miters. */
static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
{
- float co1[3], co2[3], co3[3], edge_dir[3], line_p[3];
- BoundVert *v1, *v2, *v3, *v1prev, *v3next;
- BMVert *vother;
- EdgeHalf *emiter_other;
int miter_outer = bp->miter_outer;
- v1 = emiter->rightv;
+ BoundVert *v1 = emiter->rightv;
+ BoundVert *v2, *v3;
if (miter_outer == BEVEL_MITER_PATCH) {
v2 = v1->next;
v3 = v2->next;
@@ -2730,8 +2683,9 @@ static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
v2 = NULL;
v3 = v1->next;
}
- v1prev = v1->prev;
- v3next = v3->next;
+ BoundVert *v1prev = v1->prev;
+ BoundVert *v3next = v3->next;
+ float co2[3];
copy_v3_v3(co2, v1->nv.co);
if (v1->is_arc_start) {
copy_v3_v3(v1->profile.middle, co2);
@@ -2739,7 +2693,8 @@ static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
/* co1 is intersection of line through co2 in dir of emiter->e
* and plane with normal the dir of emiter->e and through v1prev. */
- vother = BM_edge_other_vert(emiter->e, bv->v);
+ float co1[3], edge_dir[3], line_p[3];
+ BMVert *vother = BM_edge_other_vert(emiter->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
normalize_v3(edge_dir);
float d = bp->offset / (bp->seg / 2.0f); /* A fallback amount to move. */
@@ -2750,7 +2705,8 @@ static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
adjust_bound_vert(v1, co1);
/* co3 is similar, but plane is through v3next and line is other side of miter edge. */
- emiter_other = v3->elast;
+ float co3[3];
+ EdgeHalf *emiter_other = v3->elast;
vother = BM_edge_other_vert(emiter_other->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
normalize_v3(edge_dir);
@@ -2763,19 +2719,16 @@ static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
{
- BoundVert *v, *vstart, *v3;
- EdgeHalf *e;
- BMVert *vother;
- float edge_dir[3], co[3];
-
- v = vstart = bv->vmesh->boundstart;
+ BoundVert *vstart = bv->vmesh->boundstart;
+ BoundVert *v = vstart;
do {
if (v->is_arc_start) {
- v3 = v->next;
- e = v->efirst;
+ BoundVert *v3 = v->next;
+ EdgeHalf *e = v->efirst;
if (e != emiter) {
+ float edge_dir[3], co[3];
copy_v3_v3(co, v->nv.co);
- vother = BM_edge_other_vert(e->e, bv->v);
+ BMVert *vother = BM_edge_other_vert(e->e, bv->v);
sub_v3_v3v3(edge_dir, vother->co, bv->v->co);
normalize_v3(edge_dir);
madd_v3_v3v3fl(v->nv.co, co, edge_dir, bp->spread);
@@ -2810,12 +2763,6 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em
static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
MemArena *mem_arena = bp->mem_arena;
- EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eon, *emiter;
- BoundVert *v, *v1, *v2, *v3;
- VMesh *vm;
- float co[3], r;
- int in_plane, not_in_plane, miter_outer, miter_inner;
- int ang_kind;
/* Current bevel does nothing if only one edge into a vertex. */
if (bv->edgecount <= 1) {
@@ -2827,11 +2774,11 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
return;
}
- vm = bv->vmesh;
+ VMesh *vm = bv->vmesh;
/* Find a beveled edge to be efirst. */
- e = efirst = next_bev(bv, NULL);
- BLI_assert(e->is_bev);
+ EdgeHalf *efirst = next_bev(bv, NULL);
+ BLI_assert(efirst->is_bev);
if (bv->selcount == 1) {
/* Special case: only one beveled edge in. */
@@ -2840,26 +2787,29 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
/* Special miters outside only for 3 or more beveled edges. */
- miter_outer = (bv->selcount >= 3) ? bp->miter_outer : BEVEL_MITER_SHARP;
- miter_inner = bp->miter_inner;
+ int miter_outer = (bv->selcount >= 3) ? bp->miter_outer : BEVEL_MITER_SHARP;
+ int miter_inner = bp->miter_inner;
/* Keep track of the first beveled edge of an outside miter (there can be at most 1 per bv). */
- emiter = NULL;
+ EdgeHalf *emiter = NULL;
/* There is more than one beveled edge.
* We make BoundVerts to connect the sides of the beveled edges.
* Non-beveled edges in between will just join to the appropriate juncture point. */
- e = efirst;
+ EdgeHalf *e = efirst;
do {
BLI_assert(e->is_bev);
- eon = NULL;
+ EdgeHalf *eon = NULL;
/* Make the BoundVert for the right side of e; the other side will be made when the beveled
* edge to the left of e is handled.
* Analyze edges until next beveled edge: They are either "in plane" (preceding and subsequent
* faces are coplanar) or not. The "non-in-plane" edges affect the silhouette and we prefer to
* slide along one of those if possible. */
- in_plane = not_in_plane = 0; /* Counts of in-plane / not-in-plane. */
- enip = eip = NULL; /* Representatives of each type. */
+ int in_plane = 0; /* Counts of in-plane / not-in-plane. */
+ int not_in_plane = 0;
+ EdgeHalf *enip = NULL; /* Representatives of each type. */
+ EdgeHalf *eip = NULL;
+ EdgeHalf *e2;
for (e2 = e->next; !e2->is_bev; e2 = e2->next) {
if (eh_on_plane(e2)) {
in_plane++;
@@ -2871,6 +2821,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
+ float r, co[3];
if (in_plane == 0 && not_in_plane == 0) {
offset_meet(e, e2, bv->v, e->fnext, false, co, NULL);
}
@@ -2897,7 +2848,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e;
v->elast = e2;
v->ebev = e2;
@@ -2907,10 +2858,10 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
e->rightv = v;
e2->leftv = v;
- for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ for (EdgeHalf *e3 = e->next; e3 != e2; e3 = e3->next) {
e3->leftv = e3->rightv = v;
}
- ang_kind = edges_angle_kind(e, e2, bv->v);
+ int ang_kind = edges_angle_kind(e, e2, bv->v);
/* Are we doing special mitering?
* There can only be one outer reflex angle, so only one outer miter,
@@ -2922,15 +2873,16 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
emiter = e;
}
/* Make one or two more boundverts; for now all will have same co. */
- v1 = v;
+ BoundVert *v1 = v;
v1->ebev = NULL;
+ BoundVert *v2;
if (ang_kind == ANGLE_LARGER && miter_outer == BEVEL_MITER_PATCH) {
v2 = add_new_bound_vert(mem_arena, vm, co);
}
else {
v2 = NULL;
}
- v3 = add_new_bound_vert(mem_arena, vm, co);
+ BoundVert *v3 = add_new_bound_vert(mem_arena, vm, co);
v3->ebev = e2;
v3->efirst = e2;
v3->elast = e2;
@@ -2950,7 +2902,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
else {
v2->efirst = e->next;
- for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ for (EdgeHalf *e3 = e->next; e3 != e2; e3 = e3->next) {
e3->leftv = e3->rightv = v2;
v2->elast = e3;
}
@@ -2969,7 +2921,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
int i = 0;
/* Put first half of in-between edges at index 0, second half at index bp->seg.
* If between is odd, put middle one at mid-index. */
- for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ for (EdgeHalf *e3 = e->next; e3 != e2; e3 = e3->next) {
v1->elast = e3;
if (i < bet2) {
e3->profile_index = 0;
@@ -2987,13 +2939,15 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else { /* construct == false. */
- ang_kind = edges_angle_kind(e, e2, bv->v);
+ int ang_kind = edges_angle_kind(e, e2, bv->v);
if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == ANGLE_LARGER) ||
(miter_inner != BEVEL_MITER_SHARP && ang_kind == ANGLE_SMALLER)) {
if (ang_kind == ANGLE_LARGER) {
emiter = e;
}
- v1 = e->rightv;
+ BoundVert *v1 = e->rightv;
+ BoundVert *v2;
+ BoundVert *v3;
if (ang_kind == ANGLE_LARGER && miter_outer == BEVEL_MITER_PATCH) {
v2 = v1->next;
v3 = v2->next;
@@ -3047,28 +3001,21 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
#ifdef DEBUG_ADJUST
static void print_adjust_stats(BoundVert *vstart)
{
- BoundVert *v;
- EdgeHalf *eleft, *eright;
- double even_residual2, spec_residual2;
- double max_even_r, max_even_r_pct;
- double max_spec_r, max_spec_r_pct;
- double delta, delta_pct;
-
printf("\nSolution analysis\n");
- even_residual2 = 0.0;
- spec_residual2 = 0.0;
- max_even_r = 0.0;
- max_even_r_pct = 0.0;
- max_spec_r = 0.0;
- max_spec_r_pct = 0.0;
+ double even_residual2 = 0.0;
+ double spec_residual2 = 0.0;
+ double max_even_r = 0.0;
+ double max_even_r_pct = 0.0;
+ double max_spec_r = 0.0;
+ double max_spec_r_pct = 0.0;
printf("width matching\n");
- v = vstart;
+ BoundVert *v = vstart;
do {
if (v->adjchain != NULL) {
- eright = v->efirst;
- eleft = v->adjchain->elast;
- delta = fabs(eright->offset_r - eleft->offset_l);
- delta_pct = 100.0 * delta / eright->offset_r_spec;
+ EdgeHalf *eright = v->efirst;
+ EdgeHalf *eleft = v->adjchain->elast;
+ double delta = fabs(eright->offset_r - eleft->offset_l);
+ double delta_pct = 100.0 * delta / eright->offset_r_spec;
printf("e%d r(%f) vs l(%f): abs(delta)=%f, delta_pct=%f\n",
BM_elem_index_get(eright->e),
eright->offset_r,
@@ -3090,10 +3037,10 @@ static void print_adjust_stats(BoundVert *vstart)
v = vstart;
do {
if (v->adjchain != NULL) {
- eright = v->efirst;
- eleft = v->adjchain->elast;
- delta = eright->offset_r - eright->offset_r_spec;
- delta_pct = 100.0 * delta / eright->offset_r_spec;
+ EdgeHalf *eright = v->efirst;
+ EdgeHalf *eleft = v->adjchain->elast;
+ double delta = eright->offset_r - eright->offset_r_spec;
+ double delta_pct = 100.0 * delta / eright->offset_r_spec;
printf("e%d r(%f) vs r spec(%f): delta=%f, delta_pct=%f\n",
BM_elem_index_get(eright->e),
eright->offset_r,
@@ -3149,19 +3096,12 @@ static void print_adjust_stats(BoundVert *vstart)
* But keep it here for a while in case performance issues demand that it be used sometimes. */
static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscycle)
{
- BoundVert *v;
- EdgeHalf *eleft, *eright;
- float *g;
- float *g_prod;
- float gprod, gprod_sum, spec_sum, p;
- int i;
-
- g = MEM_mallocN(np * sizeof(float), "beveladjust");
- g_prod = MEM_mallocN(np * sizeof(float), "beveladjust");
+ float *g = MEM_mallocN(np * sizeof(float), "beveladjust");
+ float *g_prod = MEM_mallocN(np * sizeof(float), "beveladjust");
- v = vstart;
- spec_sum = 0.0f;
- i = 0;
+ BoundVert *v = vstart;
+ float spec_sum = 0.0f;
+ int i = 0;
do {
g[i] = v->sinratio;
if (iscycle || v->adjchain != NULL) {
@@ -3174,8 +3114,8 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
v = v->adjchain;
} while (v && v != vstart);
- gprod = 1.00f;
- gprod_sum = 1.0f;
+ float gprod = 1.00f;
+ float gprod_sum = 1.0f;
for (i = np - 1; i > 0; i--) {
gprod *= g[i];
g_prod[i] = gprod;
@@ -3196,15 +3136,15 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
MEM_freeN(g_prod);
return false;
}
- p = spec_sum / gprod_sum;
+ float p = spec_sum / gprod_sum;
/* Apply the new offsets. */
v = vstart;
i = 0;
do {
if (iscycle || v->adjchain != NULL) {
- eright = v->efirst;
- eleft = v->elast;
+ EdgeHalf *eright = v->efirst;
+ EdgeHalf *eleft = v->elast;
eright->offset_r = g_prod[(i + 1) % np] * p;
if (iscycle || v != vstart) {
eleft->offset_l = v->sinratio * eright->offset_r;
@@ -3212,7 +3152,7 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
}
else {
/* Not a cycle, and last of chain. */
- eleft = v->elast;
+ EdgeHalf *eleft = v->elast;
eleft->offset_l = p;
}
i++;
@@ -3242,80 +3182,77 @@ static EdgeHalf *next_edgehalf_bev(BevelParams *bp,
bool toward_bv,
BevVert **r_bv)
{
- EdgeHalf *new_edge;
- EdgeHalf *next_edge = NULL;
- float dir_start_edge[3], dir_new_edge[3];
- float second_best_dot = 0.0f, best_dot = 0.0f;
- float new_dot;
+ /* Case 1: The next EdgeHalf is the other side of the BMEdge.
+ * It's part of the same BMEdge, so we know the other EdgeHalf is also beveled. */
+ if (!toward_bv) {
+ return find_other_end_edge_half(bp, start_edge, r_bv);
+ }
- /* Case 1: The next EdgeHalf is across a BevVert from the current EdgeHalf. */
- if (toward_bv) {
- /* Skip all the logic if there's only one beveled edge at the vertex, we're at an end. */
- if ((*r_bv)->selcount == 1) {
- return NULL; /* No other edges to go to. */
- }
+ /* Case 2: The next EdgeHalf is across a BevVert from the current EdgeHalf. */
+ /* Skip all the logic if there's only one beveled edge at the vertex, we're at an end. */
+ if ((*r_bv)->selcount == 1) {
+ return NULL; /* No other edges to go to. */
+ }
- /* The case with only one other edge connected to the vertex is special too. */
- if ((*r_bv)->selcount == 2) {
- /* Just find the next beveled edge, that's the only other option. */
- new_edge = start_edge;
- do {
- new_edge = new_edge->next;
- } while (!new_edge->is_bev);
+ /* The case with only one other edge connected to the vertex is special too. */
+ if ((*r_bv)->selcount == 2) {
+ /* Just find the next beveled edge, that's the only other option. */
+ EdgeHalf *new_edge = start_edge;
+ do {
+ new_edge = new_edge->next;
+ } while (!new_edge->is_bev);
- return new_edge;
- }
+ return new_edge;
+ }
- /* Find the direction vector of the current edge (pointing INTO the BevVert).
- * v1 and v2 don't necessarily have an order, so we need to check which is closer to bv. */
- if (start_edge->e->v1 == (*r_bv)->v) {
- sub_v3_v3v3(dir_start_edge, start_edge->e->v1->co, start_edge->e->v2->co);
+ /* Find the direction vector of the current edge (pointing INTO the BevVert).
+ * v1 and v2 don't necessarily have an order, so we need to check which is closer to bv. */
+ float dir_start_edge[3];
+ if (start_edge->e->v1 == (*r_bv)->v) {
+ sub_v3_v3v3(dir_start_edge, start_edge->e->v1->co, start_edge->e->v2->co);
+ }
+ else {
+ sub_v3_v3v3(dir_start_edge, start_edge->e->v2->co, start_edge->e->v1->co);
+ }
+ normalize_v3(dir_start_edge);
+
+ /* Find the beveled edge coming out of the BevVert that's most parallel to the current edge. */
+ EdgeHalf *new_edge = start_edge->next;
+ float second_best_dot = 0.0f, best_dot = 0.0f;
+ EdgeHalf *next_edge = NULL;
+ while (new_edge != start_edge) {
+ if (!new_edge->is_bev) {
+ new_edge = new_edge->next;
+ continue;
+ }
+ /* Find direction vector of the possible next edge (pointing OUT of the BevVert). */
+ float dir_new_edge[3];
+ if (new_edge->e->v2 == (*r_bv)->v) {
+ sub_v3_v3v3(dir_new_edge, new_edge->e->v1->co, new_edge->e->v2->co);
}
else {
- sub_v3_v3v3(dir_start_edge, start_edge->e->v2->co, start_edge->e->v1->co);
+ sub_v3_v3v3(dir_new_edge, new_edge->e->v2->co, new_edge->e->v1->co);
}
- normalize_v3(dir_start_edge);
-
- /* Find the beveled edge coming out of the BevVert that's most parallel to the current edge. */
- new_edge = start_edge->next;
- while (new_edge != start_edge) {
- if (!new_edge->is_bev) {
- new_edge = new_edge->next;
- continue;
- }
- /* Find direction vector of the possible next edge (pointing OUT of the BevVert). */
- if (new_edge->e->v2 == (*r_bv)->v) {
- sub_v3_v3v3(dir_new_edge, new_edge->e->v1->co, new_edge->e->v2->co);
- }
- else {
- sub_v3_v3v3(dir_new_edge, new_edge->e->v2->co, new_edge->e->v1->co);
- }
- normalize_v3(dir_new_edge);
+ normalize_v3(dir_new_edge);
- /* Use this edge if it is the most parallel to the orignial so far. */
- new_dot = dot_v3v3(dir_new_edge, dir_start_edge);
- if (new_dot > best_dot) {
- second_best_dot = best_dot; /* For remembering if the choice was too close. */
- best_dot = new_dot;
- next_edge = new_edge;
- }
- else if (new_dot > second_best_dot) {
- second_best_dot = new_dot;
- }
-
- new_edge = new_edge->next;
+ /* Use this edge if it is the most parallel to the orignial so far. */
+ float new_dot = dot_v3v3(dir_new_edge, dir_start_edge);
+ if (new_dot > best_dot) {
+ second_best_dot = best_dot; /* For remembering if the choice was too close. */
+ best_dot = new_dot;
+ next_edge = new_edge;
}
-
- /* Only return a new Edge if one was found and if the choice of next edge was not too close. */
- if ((next_edge != NULL) && compare_ff(best_dot, second_best_dot, BEVEL_SMALL_ANG_DOT)) {
- return NULL;
+ else if (new_dot > second_best_dot) {
+ second_best_dot = new_dot;
}
- return next_edge;
+
+ new_edge = new_edge->next;
}
- /* Case 2: The next EdgeHalf is the other side of the BMEdge.
- * It's part of the same BMEdge, so we know the other EdgeHalf is also beveled. */
- next_edge = find_other_end_edge_half(bp, start_edge, r_bv);
+ /* Only return a new Edge if one was found and if the choice of next edge was not too close. */
+ if ((next_edge != NULL) && compare_ff(best_dot, second_best_dot, BEVEL_SMALL_ANG_DOT)) {
+ return NULL;
+ }
return next_edge;
}
@@ -3340,13 +3277,10 @@ static void regularize_profile_orientation(BevelParams *bp, BMEdge *bme)
start_edgehalf->visited_rpo = true;
/* First loop starts in the away from BevVert direction and the second starts toward it. */
- bool toward_bv;
- BevVert *bv;
- EdgeHalf *edgehalf;
for (int i = 0; i < 2; i++) {
- edgehalf = start_edgehalf;
- bv = start_bv;
- toward_bv = (i == 0);
+ EdgeHalf *edgehalf = start_edgehalf;
+ BevVert *bv = start_bv;
+ bool toward_bv = (i == 0);
edgehalf = next_edgehalf_bev(bp, edgehalf, toward_bv, &bv);
/* Keep traveling until there is no unvisited beveled edgehalf to visit next. */
@@ -3381,17 +3315,11 @@ static void regularize_profile_orientation(BevelParams *bp, BMEdge *bme)
*/
static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
{
- BoundVert *v;
- EdgeHalf *eleft, *eright, *enextleft;
- LinearSolver *solver;
- double weight, val;
- int i, np, nrows, row;
-
- np = 0;
+ int np = 0;
#ifdef DEBUG_ADJUST
printf("\nadjust the %s (with eigen)\n", iscycle ? "cycle" : "chain");
#endif
- v = vstart;
+ BoundVert *v = vstart;
do {
#ifdef DEBUG_ADJUST
eleft = v->elast;
@@ -3411,13 +3339,15 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
}
#endif
- nrows = iscycle ? 3 * np : 3 * np - 3;
+ int nrows = iscycle ? 3 * np : 3 * np - 3;
- solver = EIG_linear_least_squares_solver_new(nrows, np, 1);
+ LinearSolver *solver = EIG_linear_least_squares_solver_new(nrows, np, 1);
v = vstart;
- i = 0;
- weight = BEVEL_MATCH_SPEC_WEIGHT; /* Sqrt of factor to weight down importance of spec match. */
+ int i = 0;
+ /* Sqrt of factor to weight down importance of spec match. */
+ double weight = BEVEL_MATCH_SPEC_WEIGHT;
+ EdgeHalf *eleft, *eright, *enextleft;
do {
/* Except at end of chain, v's indep variable is offset_r of v->efirst. */
if (iscycle || i < np - 1) {
@@ -3448,7 +3378,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
/* Residue np + 2*i (if cycle) else np - 1 + 2*i:
* right offset for parm i matches its spec; weighted. */
- row = iscycle ? np + 2 * i : np - 1 + 2 * i;
+ int row = iscycle ? np + 2 * i : np - 1 + 2 * i;
EIG_linear_solver_matrix_add(solver, row, i, weight);
EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r);
#ifdef DEBUG_ADJUST
@@ -3499,7 +3429,7 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
v = vstart;
i = 0;
do {
- val = EIG_linear_solver_variable_get(solver, 0, i);
+ double val = EIG_linear_solver_variable_get(solver, 0, i);
if (iscycle || i < np - 1) {
eright = v->efirst;
eleft = v->elast;
@@ -3547,25 +3477,20 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
*/
static void adjust_offsets(BevelParams *bp, BMesh *bm)
{
- BMVert *bmv;
- BevVert *bv, *bvcur;
- BoundVert *v, *vanchor, *vchainstart, *vchainend, *vnext;
- EdgeHalf *enext;
- BMIter iter;
- bool iscycle;
- int chainlen;
-
/* Find and process chains and cycles of unvisited BoundVerts that have eon set. */
/* Note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts. */
+ BMIter iter;
+ BMVert *bmv;
BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
continue;
}
- bv = bvcur = find_bevvert(bp, bmv);
+ BevVert *bv = find_bevvert(bp, bmv);
+ BevVert *bvcur = bv;
if (!bv) {
continue;
}
- vanchor = bv->vmesh->boundstart;
+ BoundVert *vanchor = bv->vmesh->boundstart;
do {
if (vanchor->visited || !vanchor->eon) {
continue;
@@ -3582,20 +3507,22 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
* pairs with the right side of the next edge in the cycle or chain. */
/* First follow paired edges in left->right direction. */
+ BoundVert *v, *vchainstart, *vchainend;
v = vchainstart = vchainend = vanchor;
- iscycle = false;
- chainlen = 1;
+
+ bool iscycle = false;
+ int chainlen = 1;
while (v->eon && !v->visited && !iscycle) {
v->visited = true;
if (!v->efirst) {
break;
}
- enext = find_other_end_edge_half(bp, v->efirst, &bvcur);
+ EdgeHalf *enext = find_other_end_edge_half(bp, v->efirst, &bvcur);
if (!enext) {
break;
}
BLI_assert(enext != NULL);
- vnext = enext->leftv;
+ BoundVert *vnext = enext->leftv;
v->adjchain = vnext;
vchainend = vnext;
chainlen++;
@@ -3618,11 +3545,11 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
if (!v->elast) {
break;
}
- enext = find_other_end_edge_half(bp, v->elast, &bvcur);
+ EdgeHalf *enext = find_other_end_edge_half(bp, v->elast, &bvcur);
if (!enext) {
break;
}
- vnext = enext->rightv;
+ BoundVert *vnext = enext->rightv;
vnext->adjchain = v;
chainlen++;
vchainstart = vnext;
@@ -3638,7 +3565,7 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
/* Rebuild boundaries with new width specs. */
BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
- bv = find_bevvert(bp, bmv);
+ BevVert *bv = find_bevvert(bp, bmv);
if (bv) {
build_boundary(bp, bv, false);
}
@@ -3657,22 +3584,18 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
*/
static BoundVert *pipe_test(BevVert *bv)
{
- EdgeHalf *e, *epipe;
- VMesh *vm;
- BoundVert *v1, *v2, *v3;
- float dir1[3], dir3[3];
-
- vm = bv->vmesh;
+ VMesh *vm = bv->vmesh;
if (vm->count < 3 || vm->count > 4 || bv->selcount < 3 || bv->selcount > 4) {
return NULL;
}
/* Find v1, v2, v3 all with beveled edges, where v1 and v3 have collinear edges. */
- epipe = NULL;
- v1 = vm->boundstart;
+ EdgeHalf *epipe = NULL;
+ BoundVert *v1 = vm->boundstart;
+ float dir1[3], dir3[3];
do {
- v2 = v1->next;
- v3 = v2->next;
+ BoundVert *v2 = v1->next;
+ BoundVert *v3 = v2->next;
if (v1->ebev && v2->ebev && v3->ebev) {
sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(v1->ebev->e, bv->v)->co);
sub_v3_v3v3(dir3, BM_edge_other_vert(v3->ebev->e, bv->v)->co, bv->v->co);
@@ -3690,7 +3613,7 @@ static BoundVert *pipe_test(BevVert *bv)
}
/* Check face planes: all should have normals perpendicular to epipe. */
- for (e = &bv->edges[0]; e != &bv->edges[bv->edgecount]; e++) {
+ for (EdgeHalf *e = &bv->edges[0]; e != &bv->edges[bv->edgecount]; e++) {
if (e->fnext) {
if (fabsf(dot_v3v3(dir1, e->fnext->no)) > BEVEL_EPSILON_BIG) {
return NULL;
@@ -3702,14 +3625,12 @@ static BoundVert *pipe_test(BevVert *bv)
static VMesh *new_adj_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *bounds)
{
- VMesh *vm;
-
- vm = (VMesh *)BLI_memarena_alloc(mem_arena, sizeof(VMesh));
+ VMesh *vm = (VMesh *)BLI_memarena_alloc(mem_arena, sizeof(VMesh));
vm->count = count;
vm->seg = seg;
vm->boundstart = bounds;
- vm->mesh = (NewVert *)BLI_memarena_alloc(
- mem_arena, (size_t)(count * (1 + seg / 2) * (1 + seg)) * sizeof(NewVert));
+ vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena,
+ sizeof(NewVert) * count * (1 + seg / 2) * (1 + seg));
vm->mesh_kind = M_ADJ;
return vm;
}
@@ -3726,28 +3647,22 @@ static VMesh *new_adj_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *
*/
static NewVert *mesh_vert_canon(VMesh *vm, int i, int j, int k)
{
- int n, ns, ns2, odd;
- NewVert *ans;
-
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
- odd = ns % 2;
+ int n = vm->count;
+ int ns = vm->seg;
+ int ns2 = ns / 2;
+ int odd = ns % 2;
BLI_assert(0 <= i && i <= n && 0 <= j && j <= ns && 0 <= k && k <= ns);
if (!odd && j == ns2 && k == ns2) {
- ans = mesh_vert(vm, 0, j, k);
+ return mesh_vert(vm, 0, j, k);
}
- else if (j <= ns2 - 1 + odd && k <= ns2) {
- ans = mesh_vert(vm, i, j, k);
+ if (j <= ns2 - 1 + odd && k <= ns2) {
+ return mesh_vert(vm, i, j, k);
}
- else if (k <= ns2) {
- ans = mesh_vert(vm, (i + n - 1) % n, k, ns - j);
+ if (k <= ns2) {
+ return mesh_vert(vm, (i + n - 1) % n, k, ns - j);
}
- else {
- ans = mesh_vert(vm, (i + 1) % n, ns - k, j);
- }
- return ans;
+ return mesh_vert(vm, (i + 1) % n, ns - k, j);
}
static bool is_canon(VMesh *vm, int i, int j, int k)
@@ -3763,20 +3678,17 @@ static bool is_canon(VMesh *vm, int i, int j, int k)
/* Copy the vertex data to all of vm verts from canonical ones. */
static void vmesh_copy_equiv_verts(VMesh *vm)
{
- int n, ns, ns2, i, j, k;
- NewVert *v0, *v1;
-
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
- for (i = 0; i < n; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns; k++) {
+ int n = vm->count;
+ int ns = vm->seg;
+ int ns2 = ns / 2;
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j <= ns2; j++) {
+ for (int k = 0; k <= ns; k++) {
if (is_canon(vm, i, j, k)) {
continue;
}
- v1 = mesh_vert(vm, i, j, k);
- v0 = mesh_vert_canon(vm, i, j, k);
+ NewVert *v1 = mesh_vert(vm, i, j, k);
+ NewVert *v0 = mesh_vert_canon(vm, i, j, k);
copy_v3_v3(v1->co, v0->co);
v1->v = v0->v;
}
@@ -3787,13 +3699,11 @@ static void vmesh_copy_equiv_verts(VMesh *vm)
/* Calculate and return in r_cent the centroid of the center poly. */
static void vmesh_center(VMesh *vm, float r_cent[3])
{
- int n, ns2, i;
-
- n = vm->count;
- ns2 = vm->seg / 2;
+ int n = vm->count;
+ int ns2 = vm->seg / 2;
if (vm->seg % 2) {
zero_v3(r_cent);
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
add_v3_v3(r_cent, mesh_vert(vm, i, ns2, ns2)->co);
}
mul_v3_fl(r_cent, 1.0f / (float)n);
@@ -3815,53 +3725,47 @@ static void avg4(
/* Gamma needed for smooth Catmull-Clark, Sabin modification. */
static float sabin_gamma(int n)
{
- double ans, k, k2, k4, k6, x, y;
-
/* pPrecalculated for common cases of n. */
if (n < 3) {
return 0.0f;
}
if (n == 3) {
- ans = 0.065247584f;
- }
- else if (n == 4) {
- ans = 0.25f;
- }
- else if (n == 5) {
- ans = 0.401983447f;
- }
- else if (n == 6) {
- ans = 0.523423277f;
- }
- else {
- k = cos(M_PI / (double)n);
- /* Need x, real root of x^3 + (4k^2 - 3)x - 2k = 0.
- * Answer calculated via Wolfram Alpha. */
- k2 = k * k;
- k4 = k2 * k2;
- k6 = k4 * k2;
- y = pow(M_SQRT3 * sqrt(64.0 * k6 - 144.0 * k4 + 135.0 * k2 - 27.0) + 9.0 * k, 1.0 / 3.0);
- x = 0.480749856769136 * y - (0.231120424783545 * (12.0 * k2 - 9.0)) / y;
- ans = (k * x + 2.0 * k2 - 1.0) / (x * x * (k * x + 1.0));
- }
- return (float)ans;
+ return 0.065247584f;
+ }
+ if (n == 4) {
+ return 0.25f;
+ }
+ if (n == 5) {
+ return 0.401983447f;
+ }
+ if (n == 6) {
+ return 0.523423277f;
+ }
+ double k = cos(M_PI / (double)n);
+ /* Need x, real root of x^3 + (4k^2 - 3)x - 2k = 0.
+ * Answer calculated via Wolfram Alpha. */
+ double k2 = k * k;
+ double k4 = k2 * k2;
+ double k6 = k4 * k2;
+ double y = pow(M_SQRT3 * sqrt(64.0 * k6 - 144.0 * k4 + 135.0 * k2 - 27.0) + 9.0 * k, 1.0 / 3.0);
+ double x = 0.480749856769136 * y - (0.231120424783545 * (12.0 * k2 - 9.0)) / y;
+ return (k * x + 2.0 * k2 - 1.0) / (x * x * (k * x + 1.0));
}
/* Fill frac with fractions of the way along ring 0 for vertex i, for use with interp_range
* function. */
static void fill_vmesh_fracs(VMesh *vm, float *frac, int i)
{
- int k, ns;
float total = 0.0f;
- ns = vm->seg;
+ int ns = vm->seg;
frac[0] = 0.0f;
- for (k = 0; k < ns; k++) {
+ for (int k = 0; k < ns; k++) {
total += len_v3v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm, i, 0, k + 1)->co);
frac[k + 1] = total;
}
if (total > 0.0f) {
- for (k = 1; k <= ns; k++) {
+ for (int k = 1; k <= ns; k++) {
frac[k] /= total;
}
}
@@ -3873,20 +3777,19 @@ static void fill_vmesh_fracs(VMesh *vm, float *frac, int i)
/* Like fill_vmesh_fracs but want fractions for profile points of bndv, with ns segments. */
static void fill_profile_fracs(BevelParams *bp, BoundVert *bndv, float *frac, int ns)
{
- int k;
float co[3], nextco[3];
float total = 0.0f;
frac[0] = 0.0f;
copy_v3_v3(co, bndv->nv.co);
- for (k = 0; k < ns; k++) {
+ for (int k = 0; k < ns; k++) {
get_profile_point(bp, &bndv->profile, k + 1, ns, nextco);
total += len_v3v3(co, nextco);
frac[k + 1] = total;
copy_v3_v3(co, nextco);
}
if (total > 0.0f) {
- for (k = 1; k <= ns; k++) {
+ for (int k = 1; k <= ns; k++) {
frac[k] /= total;
}
}
@@ -3899,13 +3802,10 @@ static void fill_profile_fracs(BevelParams *bp, BoundVert *bndv, float *frac, in
* and put fraction of rest of way between frac[i] and frac[i + 1] into r_rest. */
static int interp_range(const float *frac, int n, const float f, float *r_rest)
{
- int i;
- float rest;
-
/* Could binary search in frac, but expect n to be reasonably small. */
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
if (f <= frac[i + 1]) {
- rest = f - frac[i];
+ float rest = f - frac[i];
if (rest == 0) {
*r_rest = 0.0f;
}
@@ -3929,39 +3829,34 @@ static int interp_range(const float *frac, int n, const float f, float *r_rest)
* neighbors. */
static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm_in, int nseg)
{
- int n_bndv, ns_in, nseg2, odd, i, j, k, j_in, k_in, k_in_prev, j0inc, k0inc;
- float *prev_frac, *frac, *new_frac, *prev_new_frac;
- float fraction, restj, restk, restkprev;
- float quad[4][3], co[3], center[3];
- VMesh *vm_out;
- BoundVert *bndv;
-
- n_bndv = vm_in->count;
- ns_in = vm_in->seg;
- nseg2 = nseg / 2;
- odd = nseg % 2;
- vm_out = new_adj_vmesh(bp->mem_arena, n_bndv, nseg, vm_in->boundstart);
-
- prev_frac = BLI_array_alloca(prev_frac, (ns_in + 1));
- frac = BLI_array_alloca(frac, (ns_in + 1));
- new_frac = BLI_array_alloca(new_frac, (nseg + 1));
- prev_new_frac = BLI_array_alloca(prev_new_frac, (nseg + 1));
+ int n_bndv = vm_in->count;
+ int ns_in = vm_in->seg;
+ int nseg2 = nseg / 2;
+ int odd = nseg % 2;
+ VMesh *vm_out = new_adj_vmesh(bp->mem_arena, n_bndv, nseg, vm_in->boundstart);
+
+ float *prev_frac = BLI_array_alloca(prev_frac, (ns_in + 1));
+ float *frac = BLI_array_alloca(frac, (ns_in + 1));
+ float *new_frac = BLI_array_alloca(new_frac, (nseg + 1));
+ float *prev_new_frac = BLI_array_alloca(prev_new_frac, (nseg + 1));
fill_vmesh_fracs(vm_in, prev_frac, n_bndv - 1);
- bndv = vm_in->boundstart;
+ BoundVert *bndv = vm_in->boundstart;
fill_profile_fracs(bp, bndv->prev, prev_new_frac, nseg);
- for (i = 0; i < n_bndv; i++) {
+ for (int i = 0; i < n_bndv; i++) {
fill_vmesh_fracs(vm_in, frac, i);
fill_profile_fracs(bp, bndv, new_frac, nseg);
- for (j = 0; j <= nseg2 - 1 + odd; j++) {
- for (k = 0; k <= nseg2; k++) {
+ for (int j = 0; j <= nseg2 - 1 + odd; j++) {
+ for (int k = 0; k <= nseg2; k++) {
/* Finding the locations where "fraction" fits into previous and current "frac". */
- fraction = new_frac[k];
- k_in = interp_range(frac, ns_in, fraction, &restk);
+ float fraction = new_frac[k];
+ float restk;
+ float restkprev;
+ int k_in = interp_range(frac, ns_in, fraction, &restk);
fraction = prev_new_frac[nseg - j];
- k_in_prev = interp_range(prev_frac, ns_in, fraction, &restkprev);
- j_in = ns_in - k_in_prev;
- restj = -restkprev;
+ int k_in_prev = interp_range(prev_frac, ns_in, fraction, &restkprev);
+ int j_in = ns_in - k_in_prev;
+ float restj = -restkprev;
if (restj > -BEVEL_EPSILON) {
restj = 0.0f;
}
@@ -3970,12 +3865,14 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm_in, int nseg)
restj = 1.0f + restj;
}
/* Use bilinear interpolation within the source quad; could be smarter here. */
+ float co[3];
if (restj < BEVEL_EPSILON && restk < BEVEL_EPSILON) {
copy_v3_v3(co, mesh_vert_canon(vm_in, i, j_in, k_in)->co);
}
else {
- j0inc = (restj < BEVEL_EPSILON || j_in == ns_in) ? 0 : 1;
- k0inc = (restk < BEVEL_EPSILON || k_in == ns_in) ? 0 : 1;
+ int j0inc = (restj < BEVEL_EPSILON || j_in == ns_in) ? 0 : 1;
+ int k0inc = (restk < BEVEL_EPSILON || k_in == ns_in) ? 0 : 1;
+ float quad[4][3];
copy_v3_v3(quad[0], mesh_vert_canon(vm_in, i, j_in, k_in)->co);
copy_v3_v3(quad[1], mesh_vert_canon(vm_in, i, j_in, k_in + k0inc)->co);
copy_v3_v3(quad[2], mesh_vert_canon(vm_in, i, j_in + j0inc, k_in + k0inc)->co);
@@ -3986,10 +3883,11 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm_in, int nseg)
}
}
bndv = bndv->next;
- memcpy(prev_frac, frac, (size_t)(ns_in + 1) * sizeof(float));
- memcpy(prev_new_frac, new_frac, (size_t)(nseg + 1) * sizeof(float));
+ memcpy(prev_frac, frac, sizeof(float) * (ns_in + 1));
+ memcpy(prev_new_frac, new_frac, sizeof(float) * (nseg + 1));
}
if (!odd) {
+ float center[3];
vmesh_center(vm_in, center);
copy_v3_v3(mesh_vert(vm_out, 0, nseg2, nseg2)->co, center);
}
@@ -4003,28 +3901,24 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm_in, int nseg)
* See Levin 1999 paper: "Filling an N-sided hole using combined subdivision schemes". */
static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
{
- int n_boundary, ns_in, ns_in2, ns_out;
- int i, j, k, inext;
- float co[3], co1[3], co2[3], acc[3];
- float beta, gamma;
- VMesh *vm_out;
- BoundVert *bndv;
-
- n_boundary = vm_in->count;
- ns_in = vm_in->seg;
- ns_in2 = ns_in / 2;
+ float co[3];
+
+ int n_boundary = vm_in->count;
+ int ns_in = vm_in->seg;
+ int ns_in2 = ns_in / 2;
BLI_assert(ns_in % 2 == 0);
- ns_out = 2 * ns_in;
- vm_out = new_adj_vmesh(bp->mem_arena, n_boundary, ns_out, vm_in->boundstart);
+ int ns_out = 2 * ns_in;
+ VMesh *vm_out = new_adj_vmesh(bp->mem_arena, n_boundary, ns_out, vm_in->boundstart);
/* First we adjust the boundary vertices of the input mesh, storing in output mesh. */
- for (i = 0; i < n_boundary; i++) {
+ for (int i = 0; i < n_boundary; i++) {
copy_v3_v3(mesh_vert(vm_out, i, 0, 0)->co, mesh_vert(vm_in, i, 0, 0)->co);
- for (k = 1; k < ns_in; k++) {
+ for (int k = 1; k < ns_in; k++) {
copy_v3_v3(co, mesh_vert(vm_in, i, 0, k)->co);
/* Smooth boundary rule. Custom profiles shouldn't be smoothed. */
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
+ float co1[3], co2[3], acc[3];
copy_v3_v3(co1, mesh_vert(vm_in, i, 0, k - 1)->co);
copy_v3_v3(co2, mesh_vert(vm_in, i, 0, k + 1)->co);
@@ -4037,13 +3931,14 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
}
}
/* Now adjust odd boundary vertices in output mesh, based on even ones. */
- bndv = vm_out->boundstart;
- for (i = 0; i < n_boundary; i++) {
- for (k = 1; k < ns_out; k += 2) {
+ BoundVert *bndv = vm_out->boundstart;
+ for (int i = 0; i < n_boundary; i++) {
+ for (int k = 1; k < ns_out; k += 2) {
get_profile_point(bp, &bndv->profile, k, ns_out, co);
/* Smooth if using a non-custom profile. */
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
+ float co1[3], co2[3], acc[3];
copy_v3_v3(co1, mesh_vert_canon(vm_out, i, 0, k - 1)->co);
copy_v3_v3(co2, mesh_vert_canon(vm_out, i, 0, k + 1)->co);
@@ -4059,8 +3954,8 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
vmesh_copy_equiv_verts(vm_out);
/* Copy adjusted verts back into vm_in. */
- for (i = 0; i < n_boundary; i++) {
- for (k = 0; k < ns_in; k++) {
+ for (int i = 0; i < n_boundary; i++) {
+ for (int k = 0; k < ns_in; k++) {
copy_v3_v3(mesh_vert(vm_in, i, 0, k)->co, mesh_vert(vm_out, i, 0, 2 * k)->co);
}
}
@@ -4071,9 +3966,9 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
* and assuming all boundary vertices have valence 4. */
/* The new face vertices. */
- for (i = 0; i < n_boundary; i++) {
- for (j = 0; j < ns_in2; j++) {
- for (k = 0; k < ns_in2; k++) {
+ for (int i = 0; i < n_boundary; i++) {
+ for (int j = 0; j < ns_in2; j++) {
+ for (int k = 0; k < ns_in2; k++) {
/* Face up and right from (j, k). */
avg4(co,
mesh_vert(vm_in, i, j, k),
@@ -4086,9 +3981,9 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
}
/* The new vertical edge vertices. */
- for (i = 0; i < n_boundary; i++) {
- for (j = 0; j < ns_in2; j++) {
- for (k = 1; k <= ns_in2; k++) {
+ for (int i = 0; i < n_boundary; i++) {
+ for (int j = 0; j < ns_in2; j++) {
+ for (int k = 1; k <= ns_in2; k++) {
/* Vertical edge between (j, k) and (j+1, k). */
avg4(co,
mesh_vert(vm_in, i, j, k),
@@ -4101,9 +3996,9 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
}
/* The new horizontal edge vertices. */
- for (i = 0; i < n_boundary; i++) {
- for (j = 1; j < ns_in2; j++) {
- for (k = 0; k < ns_in2; k++) {
+ for (int i = 0; i < n_boundary; i++) {
+ for (int j = 1; j < ns_in2; j++) {
+ for (int k = 0; k < ns_in2; k++) {
/* Horizontal edge between (j, k) and (j, k+1). */
avg4(co,
mesh_vert(vm_in, i, j, k),
@@ -4116,11 +4011,12 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
}
/* The new vertices, not on border. */
- gamma = 0.25f;
- beta = -gamma;
- for (i = 0; i < n_boundary; i++) {
- for (j = 1; j < ns_in2; j++) {
- for (k = 1; k <= ns_in2; k++) {
+ float gamma = 0.25f;
+ float beta = -gamma;
+ for (int i = 0; i < n_boundary; i++) {
+ for (int j = 1; j < ns_in2; j++) {
+ for (int k = 1; k <= ns_in2; k++) {
+ float co1[3], co2[3];
/* co1 = centroid of adjacent new edge verts. */
avg4(co1,
mesh_vert_canon(vm_out, i, 2 * j, 2 * k - 1),
@@ -4148,9 +4044,10 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
gamma = sabin_gamma(n_boundary);
beta = -gamma;
/* Accumulate edge verts in co1, face verts in co2. */
+ float co1[3], co2[3];
zero_v3(co1);
zero_v3(co2);
- for (i = 0; i < n_boundary; i++) {
+ for (int i = 0; i < n_boundary; i++) {
add_v3_v3(co1, mesh_vert(vm_out, i, ns_in, ns_in - 1)->co);
add_v3_v3(co2, mesh_vert(vm_out, i, ns_in - 1, ns_in - 1)->co);
add_v3_v3(co2, mesh_vert(vm_out, i, ns_in - 1, ns_in + 1)->co);
@@ -4159,15 +4056,15 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
mul_v3_fl(co, 1.0f / (float)n_boundary);
madd_v3_v3fl(co, co2, beta / (2.0f * (float)n_boundary));
madd_v3_v3fl(co, mesh_vert(vm_in, 0, ns_in2, ns_in2)->co, gamma);
- for (i = 0; i < n_boundary; i++) {
+ for (int i = 0; i < n_boundary; i++) {
copy_v3_v3(mesh_vert(vm_out, i, ns_in, ns_in)->co, co);
}
/* Final step: Copy the profile vertices to the VMesh's boundary. */
bndv = vm_out->boundstart;
- for (i = 0; i < n_boundary; i++) {
- inext = (i + 1) % n_boundary;
- for (k = 0; k <= ns_out; k++) {
+ for (int i = 0; i < n_boundary; i++) {
+ int inext = (i + 1) % n_boundary;
+ for (int k = 0; k <= ns_out; k++) {
get_profile_point(bp, &bndv->profile, k, ns_out, co);
copy_v3_v3(mesh_vert(vm_out, i, 0, k)->co, co);
if (k >= ns_in && k < ns_out) {
@@ -4183,24 +4080,21 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
/* Special case for cube corner, when r is PRO_SQUARE_R, meaning straight sides. */
static VMesh *make_cube_corner_square(MemArena *mem_arena, int nseg)
{
- VMesh *vm;
- float co[3];
- int i, j, k, ns2;
-
- ns2 = nseg / 2;
- vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
+ int ns2 = nseg / 2;
+ VMesh *vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
vm->count = 0; /* Reset, so the following loop will end up with correct count. */
- for (i = 0; i < 3; i++) {
- zero_v3(co);
+ for (int i = 0; i < 3; i++) {
+ float co[3] = {0.0f, 0.0f, 0.0f};
co[i] = 1.0f;
add_new_bound_vert(mem_arena, vm, co);
}
- for (i = 0; i < 3; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns2; k++) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j <= ns2; j++) {
+ for (int k = 0; k <= ns2; k++) {
if (!is_canon(vm, i, j, k)) {
continue;
}
+ float co[3];
co[i] = 1.0f;
co[(i + 1) % 3] = (float)k * 2.0f / (float)nseg;
co[(i + 2) % 3] = (float)j * 2.0f / (float)nseg;
@@ -4220,28 +4114,26 @@ static VMesh *make_cube_corner_square(MemArena *mem_arena, int nseg)
*/
static VMesh *make_cube_corner_square_in(MemArena *mem_arena, int nseg)
{
- VMesh *vm;
- float co[3];
- float b;
- int i, k, ns2, odd;
-
- ns2 = nseg / 2;
- odd = nseg % 2;
- vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
+ int ns2 = nseg / 2;
+ int odd = nseg % 2;
+ VMesh *vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
vm->count = 0; /* Reset, so following loop will end up with correct count. */
- for (i = 0; i < 3; i++) {
- zero_v3(co);
+ for (int i = 0; i < 3; i++) {
+ float co[3] = {0.0f, 0.0f, 0.0f};
co[i] = 1.0f;
add_new_bound_vert(mem_arena, vm, co);
}
+
+ float b;
if (odd) {
b = 2.0f / (2.0f * (float)ns2 + (float)M_SQRT2);
}
else {
b = 2.0f / (float)nseg;
}
- for (i = 0; i < 3; i++) {
- for (k = 0; k <= ns2; k++) {
+ for (int i = 0; i < 3; i++) {
+ for (int k = 0; k <= ns2; k++) {
+ float co[3];
co[i] = 1.0f - (float)k * b;
co[(i + 1) % 3] = 0.0f;
co[(i + 2) % 3] = 0.0f;
@@ -4266,10 +4158,6 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
MemArena *mem_arena = bp->mem_arena;
int nseg = bp->seg;
float r = bp->pro_super_r;
- VMesh *vm0, *vm1;
- BoundVert *bndv;
- int i, j, k, ns2;
- float co[3], coc[3];
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
if (r == PRO_SQUARE_R) {
@@ -4281,15 +4169,16 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
}
/* Initial mesh has 3 sides and 2 segments on each side. */
- vm0 = new_adj_vmesh(mem_arena, 3, 2, NULL);
+ VMesh *vm0 = new_adj_vmesh(mem_arena, 3, 2, NULL);
vm0->count = 0; /* Reset, so the following loop will end up with correct count. */
- for (i = 0; i < 3; i++) {
- zero_v3(co);
+ for (int i = 0; i < 3; i++) {
+ float co[3] = {0.0f, 0.0f, 0.0f};
co[i] = 1.0f;
add_new_bound_vert(mem_arena, vm0, co);
}
- bndv = vm0->boundstart;
- for (i = 0; i < 3; i++) {
+ BoundVert *bndv = vm0->boundstart;
+ for (int i = 0; i < 3; i++) {
+ float coc[3];
/* Get point, 1/2 of the way around profile, on arc between this and next. */
coc[i] = 1.0f;
coc[(i + 1) % 3] = 1.0f;
@@ -4311,6 +4200,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
bndv = bndv->next;
}
/* Center vertex. */
+ float co[3];
copy_v3_fl(co, (float)M_SQRT1_3);
if (nseg > 2) {
@@ -4325,7 +4215,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
vmesh_copy_equiv_verts(vm0);
- vm1 = vm0;
+ VMesh *vm1 = vm0;
while (vm1->seg < nseg) {
vm1 = cubic_subdiv(bp, vm1);
}
@@ -4334,10 +4224,10 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
}
/* Now snap each vertex to the superellipsoid. */
- ns2 = nseg / 2;
- for (i = 0; i < 3; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= nseg; k++) {
+ int ns2 = nseg / 2;
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j <= ns2; j++) {
+ for (int k = 0; k <= nseg; k++) {
snap_to_superellipsoid(mesh_vert(vm1, i, j, k)->co, r, false);
}
}
@@ -4349,9 +4239,6 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
/* Is this a good candidate for using tri_corner_adj_vmesh? */
static int tri_corner_test(BevelParams *bp, BevVert *bv)
{
- float ang, absang, totang, angdiff;
- EdgeHalf *e;
- int i;
int in_plane_e = 0;
/* The superellipse snapping of this case isn't helpful with custom profiles enabled. */
@@ -4365,11 +4252,11 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv)
/* Only use the tri-corner special case if the offset is the same for every edge. */
float offset = bv->edges[0].offset_l;
- totang = 0.0f;
- for (i = 0; i < bv->edgecount; i++) {
- e = &bv->edges[i];
- ang = BM_edge_calc_face_angle_signed_ex(e->e, 0.0f);
- absang = fabsf(ang);
+ float totang = 0.0f;
+ for (int i = 0; i < bv->edgecount; i++) {
+ EdgeHalf *e = &bv->edges[i];
+ float ang = BM_edge_calc_face_angle_signed_ex(e->e, 0.0f);
+ float absang = fabsf(ang);
if (absang <= M_PI_4) {
in_plane_e++;
}
@@ -4386,7 +4273,7 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv)
if (in_plane_e != bv->edgecount - 3) {
return -1;
}
- angdiff = fabsf(fabsf(totang) - 3.0f * (float)M_PI_2);
+ float angdiff = fabsf(fabsf(totang) - 3.0f * (float)M_PI_2);
if ((bp->pro_super_r == PRO_SQUARE_R && angdiff > (float)M_PI / 16.0f) ||
(angdiff > (float)M_PI_4)) {
return -1;
@@ -4399,25 +4286,24 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv)
static VMesh *tri_corner_adj_vmesh(BevelParams *bp, BevVert *bv)
{
- int i, j, k, ns, ns2;
- float co0[3], co1[3], co2[3];
- float mat[4][4], v[4];
- VMesh *vm;
- BoundVert *bndv;
+ BoundVert *bndv = bv->vmesh->boundstart;
- bndv = bv->vmesh->boundstart;
+ float co0[3], co1[3], co2[3];
copy_v3_v3(co0, bndv->nv.co);
bndv = bndv->next;
copy_v3_v3(co1, bndv->nv.co);
bndv = bndv->next;
copy_v3_v3(co2, bndv->nv.co);
+
+ float mat[4][4];
make_unit_cube_map(co0, co1, co2, bv->v->co, mat);
- ns = bp->seg;
- ns2 = ns / 2;
- vm = make_cube_corner_adj_vmesh(bp);
- for (i = 0; i < 3; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns; k++) {
+ int ns = bp->seg;
+ int ns2 = ns / 2;
+ VMesh *vm = make_cube_corner_adj_vmesh(bp);
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j <= ns2; j++) {
+ for (int k = 0; k <= ns; k++) {
+ float v[4];
copy_v3_v3(v, mesh_vert(vm, i, j, k)->co);
v[3] = 1.0f;
mul_m4_v4(mat, v);
@@ -4432,14 +4318,9 @@ static VMesh *tri_corner_adj_vmesh(BevelParams *bp, BevVert *bv)
/* Makes the mesh that replaces the original vertex, bounded by the profiles on the sides. */
static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
{
- int n_bndv, nseg, i;
- VMesh *vm0, *vm1;
- float boundverts_center[3], original_vertex[3], negative_fullest[3], center_direction[3];
- BoundVert *bndv;
MemArena *mem_arena = bp->mem_arena;
- float fullness;
- n_bndv = bv->vmesh->count;
+ int n_bndv = bv->vmesh->count;
/* Same bevel as that of 3 edges of vert in a cube. */
if (n_bndv == 3 && tri_corner_test(bp, bv) != -1 && bp->pro_super_r != PRO_SQUARE_IN_R) {
@@ -4447,13 +4328,13 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
}
/* First construct an initial control mesh, with nseg == 2. */
- nseg = bv->vmesh->seg;
- vm0 = new_adj_vmesh(mem_arena, n_bndv, 2, bv->vmesh->boundstart);
+ int nseg = bv->vmesh->seg;
+ VMesh *vm0 = new_adj_vmesh(mem_arena, n_bndv, 2, bv->vmesh->boundstart);
/* Find the center of the boundverts that make up the vmesh. */
- bndv = vm0->boundstart;
- zero_v3(boundverts_center);
- for (i = 0; i < n_bndv; i++) {
+ BoundVert *bndv = vm0->boundstart;
+ float boundverts_center[3] = {0.0f, 0.0f, 0.0f};
+ for (int i = 0; i < n_bndv; i++) {
/* Boundaries just divide input polygon edges into 2 even segments. */
copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, bndv->nv.co);
get_profile_point(bp, &bndv->profile, 1, 2, mesh_vert(vm0, i, 0, 1)->co);
@@ -4466,12 +4347,14 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
* 'negative_fullest' is the reflection of the original vertex across the boundverts' center.
* 'fullness' is the fraction of the way from the boundvert's centroid to the original vertex
* (if positive) or to negative_fullest (if negative). */
+ float original_vertex[3], negative_fullest[3];
copy_v3_v3(original_vertex, bv->v->co);
sub_v3_v3v3(negative_fullest, boundverts_center, original_vertex);
add_v3_v3(negative_fullest, boundverts_center);
/* Find the vertex mesh's start center with the profile's fullness. */
- fullness = bp->pro_spacing.fullness;
+ float fullness = bp->pro_spacing.fullness;
+ float center_direction[3];
sub_v3_v3v3(center_direction, original_vertex, boundverts_center);
if (len_squared_v3(center_direction) > BEVEL_EPSILON_SQ) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
@@ -4488,7 +4371,7 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
vmesh_copy_equiv_verts(vm0);
/* Do the subdivision process to go from the two segment start mesh to the final vertex mesh. */
- vm1 = vm0;
+ VMesh *vm1 = vm0;
do {
vm1 = cubic_subdiv(bp, vm1);
} while (vm1->seg < nseg);
@@ -4506,35 +4389,38 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
*/
static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
{
- float va[3], vb[3], edir[3], va0[3], vb0[3], vmid0[3];
- float plane[4], m[4][4], minv[4][4], p[3], snap[3];
Profile *pro = &vpipe->profile;
EdgeHalf *e = vpipe->ebev;
- copy_v3_v3(va, pro->start);
- copy_v3_v3(vb, pro->end);
- if (compare_v3v3(va, vb, BEVEL_EPSILON_D)) {
- copy_v3_v3(co, va);
+ if (compare_v3v3(pro->start, pro->end, BEVEL_EPSILON_D)) {
+ copy_v3_v3(co, pro->start);
return;
}
/* Get a plane with the normal pointing along the beveled edge. */
+ float edir[3], plane[4];
sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co);
plane_from_point_normal_v3(plane, co, edir);
- closest_to_plane_v3(va0, plane, va);
- closest_to_plane_v3(vb0, plane, vb);
+ float va0[3], vb0[3], vmid0[3];
+ closest_to_plane_v3(va0, plane, pro->start);
+ closest_to_plane_v3(vb0, plane, pro->end);
closest_to_plane_v3(vmid0, plane, pro->middle);
+
+ float m[4][4], minv[4][4];
if (make_unit_square_map(va0, vmid0, vb0, m) && invert_m4_m4(minv, m)) {
/* Transform co and project it onto superellipse. */
+ float p[3];
mul_v3_m4v3(p, minv, co);
snap_to_superellipsoid(p, pro->super_r, midline);
+ float snap[3];
mul_v3_m4v3(snap, m, p);
copy_v3_v3(co, snap);
}
else {
/* Planar case: just snap to line va0--vb0. */
+ float p[3];
closest_to_line_segment_v3(p, co, va0, vb0);
copy_v3_v3(co, p);
}
@@ -4547,35 +4433,30 @@ static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
*/
static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
{
- int i, j, k, n_bndv, ns, half_ns, ipipe1, ipipe2, ring;
- VMesh *vm;
- bool even, midline;
- float *profile_point_pipe1, *profile_point_pipe2, f;
-
/* Some unnecessary overhead running this subdivision with custom profile snapping later on. */
- vm = adj_vmesh(bp, bv);
+ VMesh *vm = adj_vmesh(bp, bv);
/* Now snap all interior coordinates to be on the epipe profile. */
- n_bndv = bv->vmesh->count;
- ns = bv->vmesh->seg;
- half_ns = ns / 2;
- even = (ns % 2) == 0;
- ipipe1 = vpipe->index;
- ipipe2 = vpipe->next->next->index;
-
- for (i = 0; i < n_bndv; i++) {
- for (j = 1; j <= half_ns; j++) {
- for (k = 0; k <= half_ns; k++) {
+ int n_bndv = bv->vmesh->count;
+ int ns = bv->vmesh->seg;
+ int half_ns = ns / 2;
+ int ipipe1 = vpipe->index;
+ int ipipe2 = vpipe->next->next->index;
+
+ for (int i = 0; i < n_bndv; i++) {
+ for (int j = 1; j <= half_ns; j++) {
+ for (int k = 0; k <= half_ns; k++) {
if (!is_canon(vm, i, j, k)) {
continue;
}
/* With a custom profile just copy the shape of the profile at each ring. */
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Find both profile vertices that correspond to this point. */
+ float *profile_point_pipe1, *profile_point_pipe2, f;
if (i == ipipe1 || i == ipipe2) {
if (n_bndv == 3 && i == ipipe1) {
/* This part of the vmesh is the triangular corner between the two pipe profiles. */
- ring = max_ii(j, k);
+ int ring = max_ii(j, k);
profile_point_pipe2 = mesh_vert(vm, i, 0, ring)->co;
profile_point_pipe1 = mesh_vert(vm, i, ring, 0)->co;
/* End profile index increases with k on one side and j on the other. */
@@ -4601,8 +4482,9 @@ static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
else {
/* A tricky case is for the 'square' profiles and an even nseg: we want certain
* vertices to snap to the midline on the pipe, not just to one plane or the other. */
- midline = even && k == half_ns &&
- ((i == 0 && j == half_ns) || (i == ipipe1 || i == ipipe2));
+ bool even = (ns % 2) == 0;
+ bool midline = even && k == half_ns &&
+ ((i == 0 && j == half_ns) || (i == ipipe1 || i == ipipe2));
snap_to_pipe_profile(vpipe, midline, mesh_vert(vm, i, j, k)->co);
}
}
@@ -4613,14 +4495,14 @@ static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
static void get_incident_edges(BMFace *f, BMVert *v, BMEdge **r_e1, BMEdge **r_e2)
{
- BMIter iter;
- BMEdge *e;
-
*r_e1 = NULL;
*r_e2 = NULL;
if (!f) {
return;
}
+
+ BMIter iter;
+ BMEdge *e;
BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
if (e->v1 == v || e->v2 == v) {
if (*r_e1 == NULL) {
@@ -4635,11 +4517,9 @@ static void get_incident_edges(BMFace *f, BMVert *v, BMEdge **r_e1, BMEdge **r_e
static BMEdge *find_closer_edge(float *co, BMEdge *e1, BMEdge *e2)
{
- float dsq1, dsq2;
-
BLI_assert(e1 != NULL && e2 != NULL);
- dsq1 = dist_squared_to_line_segment_v3(co, e1->v1->co, e1->v2->co);
- dsq2 = dist_squared_to_line_segment_v3(co, e2->v1->co, e2->v2->co);
+ float dsq1 = dist_squared_to_line_segment_v3(co, e1->v1->co, e1->v2->co);
+ float dsq2 = dist_squared_to_line_segment_v3(co, e2->v1->co, e2->v2->co);
if (dsq1 < dsq2) {
return e1;
}
@@ -4651,16 +4531,14 @@ static BMEdge *find_closer_edge(float *co, BMEdge *e1, BMEdge *e2)
* and the distance squared to the snap point as function return */
static float snap_face_dist_squared(float *co, BMFace *f, BMEdge **r_snap_e, float *r_snap_co)
{
- BMIter iter;
BMEdge *beste = NULL;
- float d2, beste_d2;
+ float beste_d2 = 1e20f;
+ BMIter iter;
BMEdge *e;
- float closest[3];
-
- beste_d2 = 1e20f;
BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
+ float closest[3];
closest_to_line_segment_v3(closest, co, e->v1->co, e->v2->co);
- d2 = len_squared_v3v3(closest, co);
+ float d2 = len_squared_v3v3(closest, co);
if (d2 < beste_d2) {
beste_d2 = d2;
beste = e;
@@ -4675,23 +4553,19 @@ static float snap_face_dist_squared(float *co, BMFace *f, BMEdge **r_snap_e, flo
*/
static float interp_poly_area(BevVert *bv, BMFace *frep)
{
- BoundVert *v;
VMesh *vm = bv->vmesh;
- BMEdge *snape;
- int n;
- float(*uv_co)[3] = NULL;
- float area;
BLI_assert(vm != NULL);
- uv_co = BLI_array_alloca(uv_co, vm->count);
- v = vm->boundstart;
- n = 0;
+ float(*uv_co)[3] = BLI_array_alloca(uv_co, vm->count);
+ BoundVert *v = vm->boundstart;
+ int n = 0;
do {
BLI_assert(n < vm->count);
+ BMEdge *snape;
snap_face_dist_squared(v->nv.v->co, frep, &snape, uv_co[n]);
n++;
} while ((v = v->next) != vm->boundstart);
- area = fabsf(area_poly_v3(uv_co, n));
+ float area = fabsf(area_poly_v3(uv_co, n));
return area;
}
@@ -4724,32 +4598,25 @@ static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
*/
static BMFace *frep_for_center_poly(BevelParams *bp, BevVert *bv)
{
- int i, j, fcount;
- BMFace **fchoices, *bmf, *bmf1, *bmf2, *any_bmf;
- BMFace *ftwo[2];
- bool already_there;
- bool consider_all_faces;
-
- fcount = 0;
- any_bmf = NULL;
- consider_all_faces = bv->selcount == 1;
+ int fcount = 0;
+ BMFace *any_bmf = NULL;
+ bool consider_all_faces = bv->selcount == 1;
/* Make an array that can hold maximum possible number of choices. */
- fchoices = BLI_array_alloca(fchoices, bv->edgecount);
- for (i = 0; i < bv->edgecount; i++) {
+ BMFace **fchoices = BLI_array_alloca(fchoices, bv->edgecount);
+ for (int i = 0; i < bv->edgecount; i++) {
if (!bv->edges[i].is_bev && !consider_all_faces) {
continue;
}
- bmf1 = bv->edges[i].fprev;
- bmf2 = bv->edges[i].fnext;
- ftwo[0] = bmf1;
- ftwo[1] = bmf2;
- bmf = choose_rep_face(bp, ftwo, 2);
+ BMFace *bmf1 = bv->edges[i].fprev;
+ BMFace *bmf2 = bv->edges[i].fnext;
+ BMFace *ftwo[2] = {bmf1, bmf2};
+ BMFace *bmf = choose_rep_face(bp, ftwo, 2);
if (bmf != NULL) {
if (any_bmf == NULL) {
any_bmf = bmf;
}
- already_there = false;
- for (j = fcount - 1; j >= 0; j--) {
+ bool already_there = false;
+ for (int j = fcount - 1; j >= 0; j--) {
if (fchoices[j] == bmf) {
already_there = true;
break;
@@ -4774,10 +4641,6 @@ static BMFace *frep_for_center_poly(BevelParams *bp, BevVert *bv)
static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_nr)
{
VMesh *vm = bv->vmesh;
- BoundVert *v;
- int i, ns2;
- BMFace *frep, *f;
- BMEdge *frep_e1, *frep_e2, *frep_e;
BMVert **vv = NULL;
BMFace **vf = NULL;
BMEdge **ve = NULL;
@@ -4785,7 +4648,9 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
- ns2 = vm->seg / 2;
+ int ns2 = vm->seg / 2;
+ BMFace *frep;
+ BMEdge *frep_e1, *frep_e2;
if (bv->any_seam) {
frep = frep_for_center_poly(bp, bv);
get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
@@ -4794,13 +4659,13 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
frep = NULL;
frep_e1 = frep_e2 = NULL;
}
- v = vm->boundstart;
+ BoundVert *v = vm->boundstart;
do {
- i = v->index;
+ int i = v->index;
BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v);
if (frep) {
BLI_array_append(vf, frep);
- frep_e = find_closer_edge(mesh_vert(vm, i, ns2, ns2)->v->co, frep_e1, frep_e2);
+ BMEdge *frep_e = find_closer_edge(mesh_vert(vm, i, ns2, ns2)->v->co, frep_e1, frep_e2);
BLI_array_append(ve, v == vm->boundstart ? NULL : frep_e);
}
else {
@@ -4808,7 +4673,7 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
BLI_array_append(ve, NULL);
}
} while ((v = v->next) != vm->boundstart);
- f = bev_create_ngon(bm, vv, BLI_array_len(vv), vf, frep, ve, mat_nr, true);
+ BMFace *f = bev_create_ngon(bm, vv, BLI_array_len(vv), vf, frep, ve, mat_nr, true);
record_face_kind(bp, f, F_VERT);
BLI_array_free(vv);
@@ -4824,17 +4689,14 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
*/
static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh *vm1)
{
- int n, ns, ns2, odd, i, k;
- VMesh *vm;
-
- vm = bv->vmesh;
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
- odd = ns % 2;
+ VMesh *vm = bv->vmesh;
+ int n = vm->count;
+ int ns = vm->seg;
+ int ns2 = ns / 2;
+ int odd = ns % 2;
- for (i = 0; i < n; i++) {
- for (k = 1; k < ns; k++) {
+ for (int i = 0; i < n; i++) {
+ for (int k = 1; k < ns; k++) {
copy_v3_v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm1, i, 0, k)->co);
if (i > 0 && k <= ns2) {
mesh_vert(vm, i, 0, k)->v = mesh_vert(vm, i - 1, 0, ns - k)->v;
@@ -4848,7 +4710,7 @@ static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh
}
}
if (odd) {
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
mesh_vert(vm, i, ns2, ns2)->v = mesh_vert(vm, i, 0, ns2)->v;
}
build_center_ngon(bp, bm, bv, bp->mat_nr);
@@ -4882,34 +4744,25 @@ static void closer_v3_v3v3v3(float r[3], const float a[3], const float b[3], con
*/
static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
{
- int n_bndv, ns, ns2, odd, i, j, k, ikind, im1, clstride, iprev, ang_kind;
- float bndco[3], dir1[3], dir2[3], co1[3], co2[3], meet1[3], meet2[3], v1co[3], v2co[3];
- float *on_edge_cur, *on_edge_prev, *p;
- float ns2inv, finalfrac, ang;
- BoundVert *bndv;
- EdgeHalf *e1, *e2;
- VMesh *vm;
- float *centerline;
- bool *cset, v1set, v2set;
-
- n_bndv = bv->vmesh->count;
- ns = bv->vmesh->seg;
- ns2 = ns / 2;
- odd = ns % 2;
- ns2inv = 1.0f / (float)ns2;
- vm = new_adj_vmesh(bp->mem_arena, n_bndv, ns, bv->vmesh->boundstart);
- clstride = 3 * (ns2 + 1);
- centerline = MEM_mallocN((size_t)(clstride * n_bndv) * sizeof(float), "bevel");
- cset = MEM_callocN((size_t)n_bndv * sizeof(bool), "bevel");
+ int n_bndv = bv->vmesh->count;
+ int ns = bv->vmesh->seg;
+ int ns2 = ns / 2;
+ int odd = ns % 2;
+ float ns2inv = 1.0f / (float)ns2;
+ VMesh *vm = new_adj_vmesh(bp->mem_arena, n_bndv, ns, bv->vmesh->boundstart);
+ int clstride = 3 * (ns2 + 1);
+ float *centerline = MEM_mallocN(sizeof(float) * clstride * n_bndv, "bevel");
+ bool *cset = MEM_callocN(sizeof(bool) * n_bndv, "bevel");
/* Find on_edge, place on bndv[i]'s elast where offset line would meet,
* taking min-distance-to bv->v with position where next sector's offset line would meet. */
- bndv = vm->boundstart;
- for (i = 0; i < n_bndv; i++) {
+ BoundVert *bndv = vm->boundstart;
+ for (int i = 0; i < n_bndv; i++) {
+ float bndco[3];
copy_v3_v3(bndco, bndv->nv.co);
- e1 = bndv->efirst;
- e2 = bndv->elast;
- ang_kind = ANGLE_STRAIGHT;
+ EdgeHalf *e1 = bndv->efirst;
+ EdgeHalf *e2 = bndv->elast;
+ int ang_kind = ANGLE_STRAIGHT;
if (e1 && e2) {
ang_kind = edges_angle_kind(e1, e2, bv->v);
}
@@ -4934,12 +4787,16 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
/* Leave cset[i] where it was - probably false, unless i == n - 1. */
}
else if (ang_kind == ANGLE_SMALLER) {
+ float dir1[3], dir2[3], co1[3], co2[3];
sub_v3_v3v3(dir1, e1->e->v1->co, e1->e->v2->co);
sub_v3_v3v3(dir2, e2->e->v1->co, e2->e->v2->co);
add_v3_v3v3(co1, bndco, dir1);
add_v3_v3v3(co2, bndco, dir2);
/* Intersect e1 with line through bndv parallel to e2 to get v1co. */
- ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, bndco, co2, meet1, meet2);
+ float meet1[3], meet2[3];
+ int ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, bndco, co2, meet1, meet2);
+ float v1co[3];
+ bool v1set;
if (ikind == 0) {
v1set = false;
}
@@ -4950,6 +4807,8 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
/* Intersect e2 with line through bndv parallel to e1 to get v2co. */
ikind = isect_line_line_v3(e2->e->v1->co, e2->e->v2->co, bndco, co1, meet1, meet2);
+ float v2co[3];
+ bool v2set;
if (ikind == 0) {
v2set = false;
}
@@ -4959,9 +4818,9 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
/* We want on_edge[i] to be min dist to bv->v of v2co and the v1co of next iteration. */
- on_edge_cur = centerline + clstride * i;
- iprev = (i == 0) ? n_bndv - 1 : i - 1;
- on_edge_prev = centerline + clstride * iprev;
+ float *on_edge_cur = centerline + clstride * i;
+ int iprev = (i == 0) ? n_bndv - 1 : i - 1;
+ float *on_edge_prev = centerline + clstride * iprev;
if (v2set) {
if (cset[i]) {
closer_v3_v3v3v3(on_edge_cur, on_edge_cur, v2co, bv->v->co);
@@ -4985,15 +4844,17 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
/* Maybe not everything was set by the previous loop. */
bndv = vm->boundstart;
- for (i = 0; i < n_bndv; i++) {
+ for (int i = 0; i < n_bndv; i++) {
if (!cset[i]) {
- on_edge_cur = centerline + clstride * i;
- e1 = bndv->next->efirst;
+ float *on_edge_cur = centerline + clstride * i;
+ EdgeHalf *e1 = bndv->next->efirst;
+ float co1[3], co2[3];
copy_v3_v3(co1, bndv->nv.co);
copy_v3_v3(co2, bndv->next->nv.co);
if (e1) {
if (bndv->prev->is_arc_start && bndv->next->is_arc_start) {
- ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, co1, co2, meet1, meet2);
+ float meet1[3], meet2[3];
+ int ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, co1, co2, meet1, meet2);
if (ikind != 0) {
copy_v3_v3(on_edge_cur, meet1);
cset[i] = true;
@@ -5018,11 +4879,13 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
}
/* Fill in rest of center-lines by interpolation. */
+ float co1[3], co2[3];
copy_v3_v3(co2, bv->v->co);
bndv = vm->boundstart;
- for (i = 0; i < n_bndv; i++) {
+ for (int i = 0; i < n_bndv; i++) {
if (odd) {
- ang = 0.5f * angle_v3v3v3(bndv->nv.co, co1, bndv->next->nv.co);
+ float ang = 0.5f * angle_v3v3v3(bndv->nv.co, co1, bndv->next->nv.co);
+ float finalfrac;
if (ang > BEVEL_SMALL_ANG) {
/* finalfrac is the length along arms of isosceles triangle with top angle 2*ang
* such that the base of the triangle is 1.
@@ -5039,10 +4902,10 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
ns2inv = 1.0f / (ns2 + finalfrac);
}
- p = centerline + clstride * i;
+ float *p = centerline + clstride * i;
copy_v3_v3(co1, p);
p += 3;
- for (j = 1; j <= ns2; j++) {
+ for (int j = 1; j <= ns2; j++) {
interp_v3_v3v3(p, co1, co2, j * ns2inv);
p += 3;
}
@@ -5051,14 +4914,14 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
/* Coords of edges and mid or near-mid line. */
bndv = vm->boundstart;
- for (i = 0; i < n_bndv; i++) {
+ for (int i = 0; i < n_bndv; i++) {
copy_v3_v3(co1, bndv->nv.co);
copy_v3_v3(co2, centerline + clstride * (i == 0 ? n_bndv - 1 : i - 1));
- for (j = 0; j < ns2 + odd; j++) {
+ for (int j = 0; j < ns2 + odd; j++) {
interp_v3_v3v3(mesh_vert(vm, i, j, 0)->co, co1, co2, j * ns2inv);
}
copy_v3_v3(co2, centerline + clstride * i);
- for (k = 1; k <= ns2; k++) {
+ for (int k = 1; k <= ns2; k++) {
interp_v3_v3v3(mesh_vert(vm, i, 0, k)->co, co1, co2, k * ns2inv);
}
bndv = bndv->next;
@@ -5070,16 +4933,17 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
/* Fill in interior points by interpolation from edges to center-lines. */
bndv = vm->boundstart;
- for (i = 0; i < n_bndv; i++) {
- im1 = (i == 0) ? n_bndv - 1 : i - 1;
- for (j = 1; j < ns2 + odd; j++) {
- for (k = 1; k <= ns2; k++) {
- ikind = isect_line_line_v3(mesh_vert(vm, i, 0, k)->co,
- centerline + clstride * im1 + 3 * k,
- mesh_vert(vm, i, j, 0)->co,
- centerline + clstride * i + 3 * j,
- meet1,
- meet2);
+ for (int i = 0; i < n_bndv; i++) {
+ int im1 = (i == 0) ? n_bndv - 1 : i - 1;
+ for (int j = 1; j < ns2 + odd; j++) {
+ for (int k = 1; k <= ns2; k++) {
+ float meet1[3], meet2[3];
+ int ikind = isect_line_line_v3(mesh_vert(vm, i, 0, k)->co,
+ centerline + clstride * im1 + 3 * k,
+ mesh_vert(vm, i, j, 0)->co,
+ centerline + clstride * i + 3 * j,
+ meet1,
+ meet2);
if (ikind == 0) {
/* How can this happen? fall back on interpolation in one direction if it does. */
interp_v3_v3v3(mesh_vert(vm, i, j, k)->co,
@@ -5112,22 +4976,15 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
*/
static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert *vpipe)
{
- int n_bndv, ns, ns2, odd, i, j, k, ring;
- VMesh *vm1, *vm;
- BoundVert *bndv;
- BMVert *bmv1, *bmv2, *bmv3, *bmv4;
- BMFace *f, *f2, *r_f, *fc;
- BMFace *fchoices[2];
- BMEdge *bme, *bme1, *bme2, *bme3;
- EdgeHalf *e;
int mat_nr = bp->mat_nr;
- n_bndv = bv->vmesh->count;
- ns = bv->vmesh->seg;
- ns2 = ns / 2;
- odd = ns % 2;
+ int n_bndv = bv->vmesh->count;
+ int ns = bv->vmesh->seg;
+ int ns2 = ns / 2;
+ int odd = ns % 2;
BLI_assert(n_bndv >= 3 && ns > 1);
+ VMesh *vm1;
if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd &&
bp->profile_type != BEVEL_PROFILE_CUSTOM) {
vm1 = square_out_adj_vmesh(bp, bv);
@@ -5149,10 +5006,10 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
/* Copy final vmesh into bv->vmesh, make BMVerts and BMFaces. */
- vm = bv->vmesh;
- for (i = 0; i < n_bndv; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns; k++) {
+ VMesh *vm = bv->vmesh;
+ for (int i = 0; i < n_bndv; i++) {
+ for (int j = 0; j <= ns2; j++) {
+ for (int k = 0; k <= ns; k++) {
if (j == 0 && (k == 0 || k == ns)) {
continue; /* Boundary corners already made. */
}
@@ -5166,26 +5023,16 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
vmesh_copy_equiv_verts(vm);
/* Make the polygons. */
- bndv = vm->boundstart;
+ BoundVert *bndv = vm->boundstart;
do {
- i = bndv->index;
- f = boundvert_rep_face(bndv, NULL);
- f2 = boundvert_rep_face(bndv->next, NULL);
- fchoices[0] = f;
- fchoices[1] = f2;
- if (odd) {
- fc = choose_rep_face(bp, fchoices, 2);
- }
- else {
- fc = NULL;
- }
- if (bp->affect_type == BEVEL_AFFECT_VERTICES) {
- e = bndv->efirst;
- }
- else {
- e = bndv->ebev;
- }
- bme = e ? e->e : NULL;
+ int i = bndv->index;
+ BMFace *f = boundvert_rep_face(bndv, NULL);
+ BMFace *f2 = boundvert_rep_face(bndv->next, NULL);
+ BMFace *fchoices[2] = {f, f2};
+ BMFace *fc = odd ? choose_rep_face(bp, fchoices, 2) : NULL;
+
+ EdgeHalf *e = (bp->affect_type == BEVEL_AFFECT_VERTICES) ? bndv->efirst : bndv->ebev;
+ BMEdge *bme = e ? e->e : NULL;
/* For odd ns, make polys with lower left corner at (i,j,k) for
* j in [0, ns2-1], k in [0, ns2]. And then the center ngon.
* For even ns,
@@ -5193,13 +5040,14 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
*
* Recall: j is ring index, k is segment index.
*/
- for (j = 0; j < ns2; j++) {
- for (k = 0; k < ns2 + odd; k++) {
- bmv1 = mesh_vert(vm, i, j, k)->v;
- bmv2 = mesh_vert(vm, i, j, k + 1)->v;
- bmv3 = mesh_vert(vm, i, j + 1, k + 1)->v;
- bmv4 = mesh_vert(vm, i, j + 1, k)->v;
+ for (int j = 0; j < ns2; j++) {
+ for (int k = 0; k < ns2 + odd; k++) {
+ BMVert *bmv1 = mesh_vert(vm, i, j, k)->v;
+ BMVert *bmv2 = mesh_vert(vm, i, j, k + 1)->v;
+ BMVert *bmv3 = mesh_vert(vm, i, j + 1, k + 1)->v;
+ BMVert *bmv4 = mesh_vert(vm, i, j + 1, k)->v;
BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
+ BMFace *r_f;
if (bp->affect_type == BEVEL_AFFECT_VERTICES) {
if (j < k) {
if (k == ns2 && j == ns2 - 1) {
@@ -5255,12 +5103,12 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
}
else {
- bme1 = k == ns2 - 1 ? bme : NULL;
- bme3 = NULL;
+ BMEdge *bme1 = k == ns2 - 1 ? bme : NULL;
+ BMEdge *bme3 = NULL;
if (j == ns2 - 1 && bndv->prev->ebev) {
bme3 = bndv->prev->ebev->e;
}
- bme2 = bme1 != NULL ? bme1 : bme3;
+ BMEdge *bme2 = bme1 != NULL ? bme1 : bme3;
r_f = bev_create_quad_ex(
bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, NULL, bme1, bme2, bme3, f, mat_nr);
}
@@ -5274,9 +5122,9 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
if (!odd) {
bndv = vm->boundstart;
do {
- i = bndv->index;
+ int i = bndv->index;
if (!bndv->any_seam) {
- for (ring = 1; ring < ns2; ring++) {
+ for (int ring = 1; ring < ns2; ring++) {
BMVert *v_uv = mesh_vert(vm, i, ring, ns2)->v;
if (v_uv) {
bev_merge_uvs(bm, v_uv);
@@ -5284,9 +5132,9 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
}
}
} while ((bndv = bndv->next) != vm->boundstart);
- bmv1 = mesh_vert(vm, 0, ns2, ns2)->v;
+ BMVert *bmv = mesh_vert(vm, 0, ns2, ns2)->v;
if (bp->affect_type == BEVEL_AFFECT_VERTICES || count_bound_vert_seams(bv) <= 1) {
- bev_merge_uvs(bm, bmv1);
+ bev_merge_uvs(bm, bmv);
}
}
@@ -5312,33 +5160,27 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
#ifdef DEBUG_CUSTOM_PROFILE_CUTOFF
printf("BEVEL BUILD CUTOFF\n");
# define F3(v) (v)[0], (v)[1], (v)[2]
- int j;
#endif
- int i;
int n_bndv = bv->vmesh->count;
- BoundVert *bndv;
- float length;
- float down_direction[3], new_vert[3];
- bool build_center_face;
- /* BMFace *repface; */
- BMVert **face_bmverts = NULL;
- BMEdge **bmedges = NULL;
- BMFace **bmfaces = NULL;
/* Find the locations for the corner vertices at the bottom of the cutoff faces. */
- bndv = bv->vmesh->boundstart;
+ BoundVert *bndv = bv->vmesh->boundstart;
do {
- i = bndv->index;
+ int i = bndv->index;
/* Find the "down" direction for this side of the cutoff face. */
/* Find the direction along the intersection of the two adjacent profile normals. */
+ float down_direction[3];
cross_v3_v3v3(down_direction, bndv->profile.plane_no, bndv->prev->profile.plane_no);
if (dot_v3v3(down_direction, bv->v->no) > 0.0f) {
negate_v3(down_direction);
}
/* Move down from the boundvert by average profile height from the two adjacent profiles. */
- length = (bndv->profile.height / sqrtf(2.0f) + bndv->prev->profile.height / sqrtf(2.0f)) / 2;
+ float length = (bndv->profile.height / sqrtf(2.0f) +
+ bndv->prev->profile.height / sqrtf(2.0f)) /
+ 2;
+ float new_vert[3];
madd_v3_v3v3fl(new_vert, bndv->nv.co, down_direction, length);
/* Use this location for this profile's first corner vert and the last profile's second. */
@@ -5349,13 +5191,13 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
#ifdef DEBUG_CUSTOM_PROFILE_CUTOFF
printf("Corner vertices:\n");
- for (j = 0; j < n_bndv; j++) {
+ for (int j = 0; j < n_bndv; j++) {
printf(" (%.3f, %.3f, %.3f)\n", F3(mesh_vert(bv->vmesh, j, 1, 0)->co));
}
#endif
/* Disable the center face if the corner vertices share the same location. */
- build_center_face = true;
+ bool build_center_face = true;
if (n_bndv == 3) { /* Vertices only collapse with a 3-way VMesh. */
build_center_face &= len_squared_v3v3(mesh_vert(bv->vmesh, 0, 1, 0)->co,
mesh_vert(bv->vmesh, 1, 1, 0)->co) > BEVEL_EPSILON;
@@ -5371,7 +5213,7 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
/* Create the corner vertex BMVerts. */
if (build_center_face) {
do {
- i = bndv->index;
+ int i = bndv->index;
create_mesh_bmvert(bm, bv->vmesh, i, 1, 0, bv->v);
/* The second corner vertex for the previous profile shares this BMVert. */
mesh_vert(bv->vmesh, bndv->prev->index, 1, 1)->v = mesh_vert(bv->vmesh, i, 1, 0)->v;
@@ -5381,7 +5223,7 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
else {
/* Use the same BMVert for all of the corner vertices. */
create_mesh_bmvert(bm, bv->vmesh, 0, 1, 0, bv->v);
- for (i = 1; i < n_bndv; i++) {
+ for (int i = 1; i < n_bndv; i++) {
mesh_vert(bv->vmesh, i, 1, 0)->v = mesh_vert(bv->vmesh, 0, 1, 0)->v;
}
}
@@ -5392,11 +5234,13 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
#ifdef DEBUG_CUSTOM_PROFILE_CUTOFF
printf("Building profile cutoff faces.\n");
#endif
- face_bmverts = BLI_memarena_alloc(
- bp->mem_arena, ((size_t)max_ii(bp->seg + 2 + build_center_face, n_bndv) * sizeof(BMVert *)));
+ BMVert **face_bmverts = BLI_memarena_alloc(
+ bp->mem_arena, sizeof(BMVert *) * max_ii(bp->seg + 2 + build_center_face, n_bndv));
bndv = bv->vmesh->boundstart;
do {
- i = bndv->index;
+ int i = bndv->index;
+ BMEdge **bmedges = NULL;
+ BMFace **bmfaces = NULL;
BLI_array_staticdeclare(bmedges, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(bmfaces, BM_DEFAULT_NGON_STACK_SIZE);
@@ -5444,11 +5288,13 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
/* Create the bottom face if it should be built, reusing previous face_bmverts allocation. */
if (build_center_face) {
+ BMEdge **bmedges = NULL;
+ BMFace **bmfaces = NULL;
BLI_array_staticdeclare(bmedges, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(bmfaces, BM_DEFAULT_NGON_STACK_SIZE);
/* Add all of the corner vertices to this face. */
- for (i = 0; i < n_bndv; i++) {
+ for (int i = 0; i < n_bndv; i++) {
/* Add verts from each cutoff face. */
face_bmverts[i] = mesh_vert(bv->vmesh, i, 1, 0)->v;
}
@@ -5462,11 +5308,7 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- BMFace *f, *repface;
- int n, k;
VMesh *vm = bv->vmesh;
- BoundVert *bndv;
- BMEdge *repface_e1, *repface_e2, *frep_e;
BMVert **bmverts = NULL;
BMEdge **bmedges = NULL;
BMFace **bmfaces = NULL;
@@ -5474,6 +5316,8 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
BLI_array_staticdeclare(bmedges, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(bmfaces, BM_DEFAULT_NGON_STACK_SIZE);
+ BMFace *repface;
+ BMEdge *repface_e1, *repface_e2;
if (bv->any_seam) {
repface = frep_for_center_poly(bp, bv);
get_incident_edges(repface, bv->v, &repface_e1, &repface_e2);
@@ -5482,15 +5326,15 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
repface = NULL;
repface_e1 = repface_e2 = NULL;
}
- bndv = vm->boundstart;
- n = 0;
+ BoundVert *bndv = vm->boundstart;
+ int n = 0;
do {
/* Accumulate vertices for vertex ngon. */
/* Also accumulate faces in which uv interpolation is to happen for each. */
BLI_array_append(bmverts, bndv->nv.v);
if (repface) {
BLI_array_append(bmfaces, repface);
- frep_e = find_closer_edge(bndv->nv.v->co, repface_e1, repface_e2);
+ BMEdge *frep_e = find_closer_edge(bndv->nv.v->co, repface_e1, repface_e2);
BLI_array_append(bmedges, n > 0 ? frep_e : NULL);
}
else {
@@ -5499,11 +5343,11 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
}
n++;
if (bndv->ebev && bndv->ebev->seg > 1) {
- for (k = 1; k < bndv->ebev->seg; k++) {
+ for (int k = 1; k < bndv->ebev->seg; k++) {
BLI_array_append(bmverts, mesh_vert(vm, bndv->index, 0, k)->v);
if (repface) {
BLI_array_append(bmfaces, repface);
- frep_e = find_closer_edge(
+ BMEdge *frep_e = find_closer_edge(
mesh_vert(vm, bndv->index, 0, k)->v->co, repface_e1, repface_e2);
BLI_array_append(bmedges, k < bndv->ebev->seg / 2 ? NULL : frep_e);
}
@@ -5515,6 +5359,8 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
}
}
} while ((bndv = bndv->next) != vm->boundstart);
+
+ BMFace *f;
if (n > 2) {
f = bev_create_ngon(bm, bmverts, n, bmfaces, repface, bmedges, bp->mat_nr, true);
record_face_kind(bp, f, F_VERT);
@@ -5530,53 +5376,54 @@ static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- BMFace *f;
BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1);
- f = bevel_build_poly(bp, bm, bv);
+ BMFace *f = bevel_build_poly(bp, bm, bv);
- if (f) {
- /* We have a polygon which we know starts at the previous vertex, make it into a fan. */
- BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev;
- BMVert *v_fan = l_fan->v;
-
- while (f->len > 3) {
- BMLoop *l_new;
- BMFace *f_new;
- BLI_assert(v_fan == l_fan->v);
- f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false);
- flag_out_edge(bm, l_new->e);
-
- if (f_new->len > f->len) {
- f = f_new;
- if (l_new->v == v_fan) {
- l_fan = l_new;
- }
- else if (l_new->next->v == v_fan) {
- l_fan = l_new->next;
- }
- else if (l_new->prev->v == v_fan) {
- l_fan = l_new->prev;
- }
- else {
- BLI_assert(0);
- }
+ if (f == NULL) {
+ return;
+ }
+
+ /* We have a polygon which we know starts at the previous vertex, make it into a fan. */
+ BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev;
+ BMVert *v_fan = l_fan->v;
+
+ while (f->len > 3) {
+ BMLoop *l_new;
+ BMFace *f_new;
+ BLI_assert(v_fan == l_fan->v);
+ f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false);
+ flag_out_edge(bm, l_new->e);
+
+ if (f_new->len > f->len) {
+ f = f_new;
+ if (l_new->v == v_fan) {
+ l_fan = l_new;
+ }
+ else if (l_new->next->v == v_fan) {
+ l_fan = l_new->next;
+ }
+ else if (l_new->prev->v == v_fan) {
+ l_fan = l_new->prev;
}
else {
- if (l_fan->v == v_fan) { /* l_fan = l_fan. */
- }
- else if (l_fan->next->v == v_fan) {
- l_fan = l_fan->next;
- }
- else if (l_fan->prev->v == v_fan) {
- l_fan = l_fan->prev;
- }
- else {
- BLI_assert(0);
- }
+ BLI_assert(0);
}
- record_face_kind(bp, f_new, F_VERT);
}
+ else {
+ if (l_fan->v == v_fan) { /* l_fan = l_fan. */
+ }
+ else if (l_fan->next->v == v_fan) {
+ l_fan = l_fan->next;
+ }
+ else if (l_fan->prev->v == v_fan) {
+ l_fan = l_fan->prev;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ record_face_kind(bp, f_new, F_VERT);
}
}
@@ -5588,23 +5435,17 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
{
VMesh *vm = bv->vmesh;
- BMVert *v1, *v2;
- BMEdge *e_eg, *bme;
- Profile *pro;
- float co[3];
- BoundVert *bndv;
- int ns, k;
BLI_assert(vm->count == 2 && bp->affect_type == BEVEL_AFFECT_VERTICES);
- v1 = mesh_vert(vm, 0, 0, 0)->v;
- v2 = mesh_vert(vm, 1, 0, 0)->v;
+ BMVert *v1 = mesh_vert(vm, 0, 0, 0)->v;
+ BMVert *v2 = mesh_vert(vm, 1, 0, 0)->v;
- ns = vm->seg;
+ int ns = vm->seg;
if (ns > 1) {
/* Set up profile parameters. */
- bndv = vm->boundstart;
- pro = &bndv->profile;
+ BoundVert *bndv = vm->boundstart;
+ Profile *pro = &bndv->profile;
pro->super_r = bp->pro_super_r;
copy_v3_v3(pro->start, v1->co);
copy_v3_v3(pro->end, v2->co);
@@ -5614,25 +5455,26 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
zero_v3(pro->plane_no);
zero_v3(pro->proj_dir);
- for (k = 1; k < ns; k++) {
+ for (int k = 1; k < ns; k++) {
+ float co[3];
get_profile_point(bp, pro, k, ns, co);
copy_v3_v3(mesh_vert(vm, 0, 0, k)->co, co);
create_mesh_bmvert(bm, vm, 0, 0, k, bv->v);
}
copy_v3_v3(mesh_vert(vm, 0, 0, ns)->co, v2->co);
- for (k = 1; k < ns; k++) {
+ for (int k = 1; k < ns; k++) {
copy_mesh_vert(vm, 1, 0, ns - k, 0, 0, k);
}
}
if (BM_vert_face_check(bv->v) == false) {
- e_eg = bv->edges[0].e;
+ BMEdge *e_eg = bv->edges[0].e;
BLI_assert(e_eg != NULL);
- for (k = 0; k < ns; k++) {
+ for (int k = 0; k < ns; k++) {
v1 = mesh_vert(vm, 0, 0, k)->v;
v2 = mesh_vert(vm, 0, 0, k + 1)->v;
BLI_assert(v1 != NULL && v2 != NULL);
- bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+ BMEdge *bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
if (bme) {
flag_out_edge(bm, bme);
}
@@ -5645,25 +5487,24 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
{
VMesh *vm = bv->vmesh;
- BoundVert *bndv, *weld1, *weld2, *vpipe;
- int n, ns, ns2, i, k, weld;
- float *v_weld1, *v_weld2, co[3];
+ float co[3];
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
+ int n = vm->count;
+ int ns = vm->seg;
+ int ns2 = ns / 2;
vm->mesh = (NewVert *)BLI_memarena_alloc(bp->mem_arena,
- (size_t)(n * (ns2 + 1) * (ns + 1)) * sizeof(NewVert));
+ sizeof(NewVert) * n * (ns2 + 1) * (ns + 1));
/* Special case: just two beveled edges welded together. */
- weld = (bv->selcount == 2) && (vm->count == 2);
- weld1 = weld2 = NULL; /* Will hold two BoundVerts involved in weld. */
+ const bool weld = (bv->selcount == 2) && (vm->count == 2);
+ BoundVert *weld1 = NULL; /* Will hold two BoundVerts involved in weld. */
+ BoundVert *weld2 = NULL;
/* Make (i, 0, 0) mesh verts for all i boundverts. */
- bndv = vm->boundstart;
+ BoundVert *bndv = vm->boundstart;
do {
- i = bndv->index;
+ int i = bndv->index;
copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, bndv->nv.co); /* Mesh NewVert to boundary NewVert. */
create_mesh_bmvert(bm, vm, i, 0, 0, bv->v); /* Create BMVert for that NewVert. */
bndv->nv.v = mesh_vert(vm, i, 0, 0)->v; /* Use the BMVert for the BoundVert's NewVert. */
@@ -5690,12 +5531,12 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
/* Copy other ends to (i, 0, ns) for all i, and fill in profiles for edges. */
bndv = vm->boundstart;
do {
- i = bndv->index;
+ int i = bndv->index;
/* bndv's last vert along the boundary arc is the first of the next BoundVert's arc. */
copy_mesh_vert(vm, i, 0, ns, bndv->next->index, 0, 0);
if (vm->mesh_kind != M_ADJ) {
- for (k = 1; k < ns; k++) {
+ for (int k = 1; k < ns; k++) {
if (bndv->ebev) {
get_profile_point(bp, &bndv->profile, k, ns, co);
copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
@@ -5716,9 +5557,9 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
/* Build the profile for the weld case (just a connection between the two boundverts). */
if (weld) {
bv->vmesh->mesh_kind = M_NONE;
- for (k = 1; k < ns; k++) {
- v_weld1 = mesh_vert(bv->vmesh, weld1->index, 0, k)->co;
- v_weld2 = mesh_vert(bv->vmesh, weld2->index, 0, ns - k)->co;
+ for (int k = 1; k < ns; k++) {
+ float *v_weld1 = mesh_vert(bv->vmesh, weld1->index, 0, k)->co;
+ float *v_weld2 = mesh_vert(bv->vmesh, weld2->index, 0, ns - k)->co;
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Don't bother with special case profile check from below. */
mid_v3_v3v3(co, v_weld1, v_weld2);
@@ -5739,13 +5580,13 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
copy_v3_v3(mesh_vert(bv->vmesh, weld1->index, 0, k)->co, co);
create_mesh_bmvert(bm, bv->vmesh, weld1->index, 0, k, bv->v);
}
- for (k = 1; k < ns; k++) {
+ for (int k = 1; k < ns; k++) {
copy_mesh_vert(bv->vmesh, weld2->index, 0, ns - k, weld1->index, 0, k);
}
}
/* Make sure the pipe case ADJ mesh is used for both the "Grid Fill" (ADJ) and cutoff options. */
- vpipe = NULL;
+ BoundVert *vpipe = NULL;
if ((vm->count == 3 || vm->count == 4) && bp->seg > 1) {
/* Result is passed to bevel_build_rings to avoid overhead. */
vpipe = pipe_test(bv);
@@ -5801,44 +5642,43 @@ static float edge_face_angle(EdgeHalf *e)
*/
static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
{
- BMEdge *bme, *bme2, *nextbme;
- BMLoop *l;
- BMIter iter;
- int j, tryj, bestj, nsucs, sucindex, k;
BMEdge **sucs = NULL;
BMEdge **save_path = NULL;
BLI_array_staticdeclare(sucs, 4); /* Likely very few faces attached to same edge. */
BLI_array_staticdeclare(save_path, BM_DEFAULT_NGON_STACK_SIZE);
- bme = bv->edges[i].e;
/* Fill sucs with all unmarked edges of bmesh. */
+ BMEdge *bme = bv->edges[i].e;
+ BMIter iter;
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, bme, BM_LOOPS_OF_EDGE) {
- bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
+ BMEdge *bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
BLI_array_append(sucs, bme2);
}
}
- nsucs = BLI_array_len(sucs);
+ int nsucs = BLI_array_len(sucs);
- bestj = j = i;
- for (sucindex = 0; sucindex < nsucs; sucindex++) {
- nextbme = sucs[sucindex];
+ int bestj = i;
+ int j = i;
+ for (int sucindex = 0; sucindex < nsucs; sucindex++) {
+ BMEdge *nextbme = sucs[sucindex];
BLI_assert(nextbme != NULL);
BLI_assert(!BM_BEVEL_EDGE_TAG_TEST(nextbme));
BLI_assert(j + 1 < bv->edgecount);
bv->edges[j + 1].e = nextbme;
BM_BEVEL_EDGE_TAG_ENABLE(nextbme);
- tryj = bevel_edge_order_extend(bm, bv, j + 1);
+ int tryj = bevel_edge_order_extend(bm, bv, j + 1);
if (tryj > bestj ||
(tryj == bestj && edges_face_connected_at_vert(bv->edges[tryj].e, bv->edges[0].e))) {
bestj = tryj;
BLI_array_clear(save_path);
- for (k = j + 1; k <= bestj; k++) {
+ for (int k = j + 1; k <= bestj; k++) {
BLI_array_append(save_path, bv->edges[k].e);
}
}
/* Now reset to path only-going-to-j state. */
- for (k = j + 1; k <= tryj; k++) {
+ for (int k = j + 1; k <= tryj; k++) {
BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
bv->edges[k].e = NULL;
}
@@ -5847,7 +5687,7 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
if (bestj > j) {
/* Save_path should have from j + 1 to bestj inclusive.
* Edges to add to edges[] before returning. */
- for (k = j + 1; k <= bestj; k++) {
+ for (int k = j + 1; k <= bestj; k++) {
BLI_assert(save_path[k - (j + 1)] != NULL);
bv->edges[k].e = save_path[k - (j + 1)];
BM_BEVEL_EDGE_TAG_ENABLE(bv->edges[k].e);
@@ -5873,17 +5713,14 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
* so for now will continue to use the legacy code. */
static bool fast_bevel_edge_order(BevVert *bv)
{
- int j, k, nsucs;
- BMEdge *bme, *bme2, *bmenext;
- BMIter iter;
- BMLoop *l;
-
- for (j = 1; j < bv->edgecount; j++) {
- bme = bv->edges[j - 1].e;
- bmenext = NULL;
- nsucs = 0;
+ for (int j = 1; j < bv->edgecount; j++) {
+ BMEdge *bme = bv->edges[j - 1].e;
+ BMEdge *bmenext = NULL;
+ int nsucs = 0;
+ BMIter iter;
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, bme, BM_LOOPS_OF_EDGE) {
- bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
+ BMEdge *bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
nsucs++;
if (bmenext == NULL) {
@@ -5893,7 +5730,7 @@ static bool fast_bevel_edge_order(BevVert *bv)
}
if (nsucs == 0 || (nsucs == 2 && j != 1) || nsucs > 2 ||
(j == bv->edgecount - 1 && !edges_face_connected_at_vert(bmenext, bv->edges[0].e))) {
- for (k = 1; k < j; k++) {
+ for (int k = 1; k < j; k++) {
BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
bv->edges[k].e = NULL;
}
@@ -5907,29 +5744,29 @@ static bool fast_bevel_edge_order(BevVert *bv)
#else
static bool fast_bevel_edge_order(BevVert *bv)
{
- BMEdge *bme, *bme2, *first_suc;
- BMIter iter, iter2;
- BMFace *f;
- EdgeHalf *e;
- int i, k, ntot, num_shared_face;
-
- ntot = bv->edgecount;
+ int ntot = bv->edgecount;
/* Add edges to bv->edges in order that keeps adjacent edges sharing
* a unique face, if possible. */
- e = &bv->edges[0];
- bme = e->e;
+ EdgeHalf *e = &bv->edges[0];
+ BMEdge *bme = e->e;
if (!bme->l) {
return false;
}
- for (i = 1; i < ntot; i++) {
+
+ for (int i = 1; i < ntot; i++) {
/* Find an unflagged edge bme2 that shares a face f with previous bme. */
- num_shared_face = 0;
- first_suc = NULL; /* Keep track of first successor to match legacy behavior. */
+ int num_shared_face = 0;
+ BMEdge *first_suc = NULL; /* Keep track of first successor to match legacy behavior. */
+ BMIter iter;
+ BMEdge *bme2;
BM_ITER_ELEM (bme2, &iter, bv->v, BM_EDGES_OF_VERT) {
if (BM_BEVEL_EDGE_TAG_TEST(bme2)) {
continue;
}
+
+ BMIter iter2;
+ BMFace *f;
BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) {
if (BM_face_edge_share_loop(f, bme)) {
num_shared_face++;
@@ -5948,7 +5785,7 @@ static bool fast_bevel_edge_order(BevVert *bv)
BM_BEVEL_EDGE_TAG_ENABLE(bme);
}
else {
- for (k = 1; k < i; k++) {
+ for (int k = 1; k < i; k++) {
BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
bv->edges[k].e = NULL;
}
@@ -5964,17 +5801,8 @@ static bool fast_bevel_edge_order(BevVert *bv)
* first_bme is a good edge to start with. */
static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
{
- BMEdge *bme, *bme2;
- BMIter iter;
- BMFace *f, *bestf;
- EdgeHalf *e;
- EdgeHalf *e2;
- BMLoop *l;
- int i, ntot;
-
- ntot = bv->edgecount;
- i = 0;
- for (;;) {
+ int ntot = bv->edgecount;
+ for (int i = 0;;) {
BLI_assert(first_bme != NULL);
bv->edges[i].e = first_bme;
BM_BEVEL_EDGE_TAG_ENABLE(first_bme);
@@ -5988,6 +5816,8 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
}
/* Not done yet: find a new first_bme. */
first_bme = NULL;
+ BMIter iter;
+ BMEdge *bme;
BM_ITER_ELEM (bme, &iter, bv->v, BM_EDGES_OF_VERT) {
if (BM_BEVEL_EDGE_TAG_TEST(bme)) {
continue;
@@ -6002,11 +5832,11 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
}
}
/* Now fill in the faces. */
- for (i = 0; i < ntot; i++) {
- e = &bv->edges[i];
- e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1];
- bme = e->e;
- bme2 = e2->e;
+ for (int i = 0; i < ntot; i++) {
+ EdgeHalf *e = &bv->edges[i];
+ EdgeHalf *e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1];
+ BMEdge *bme = e->e;
+ BMEdge *bme2 = e2->e;
BLI_assert(bme != NULL);
if (e->fnext != NULL || e2->fprev != NULL) {
continue;
@@ -6014,9 +5844,11 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
/* Which faces have successive loops that are for bme and bme2?
* There could be more than one. E.g., in manifold ntot==2 case.
* Prefer one that has loop in same direction as e. */
- bestf = NULL;
+ BMFace *bestf = NULL;
+ BMIter iter;
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, bme, BM_LOOPS_OF_EDGE) {
- f = l->f;
+ BMFace *f = l->f;
if ((l->prev->e == bme2 || l->next->e == bme2)) {
if (!bestf || l->v == bv->v) {
bestf = f;
@@ -6032,19 +5864,6 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
/* Construction around the vertex. */
static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
{
- BMEdge *bme;
- BevVert *bv;
- BMEdge *first_bme;
- BMVert *v1, *v2;
- BMIter iter;
- EdgeHalf *e;
- float weight, z;
- float vert_axis[3] = {0, 0, 0};
- int i, ccw_test_sum;
- int nsel = 0;
- int tot_edges = 0;
- int tot_wire = 0;
-
/* Gather input selected edges.
* Only bevel selected edges that have exactly two incident faces.
* Want edges to be ordered so that they share faces.
@@ -6053,7 +5872,12 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
* Want to ignore wire edges completely for edge beveling.
* TODO: make following work when more than one gap. */
- first_bme = NULL;
+ int nsel = 0;
+ int tot_edges = 0;
+ int tot_wire = 0;
+ BMEdge *first_bme = NULL;
+ BMIter iter;
+ BMEdge *bme;
BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
int face_count = BM_edge_face_count(bme);
BM_BEVEL_EDGE_TAG_DISABLE(bme);
@@ -6091,15 +5915,15 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
return NULL;
}
- bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, (sizeof(BevVert)));
+ BevVert *bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, sizeof(BevVert));
bv->v = v;
bv->edgecount = tot_edges;
bv->selcount = nsel;
bv->wirecount = tot_wire;
bv->offset = bp->offset;
- bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, tot_edges * sizeof(EdgeHalf));
+ bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, sizeof(EdgeHalf) * tot_edges);
if (tot_wire) {
- bv->wire_edges = (BMEdge **)BLI_memarena_alloc(bp->mem_arena, tot_wire * sizeof(BMEdge *));
+ bv->wire_edges = (BMEdge **)BLI_memarena_alloc(bp->mem_arena, sizeof(BMEdge *) * tot_wire);
}
else {
bv->wire_edges = NULL;
@@ -6112,8 +5936,8 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
find_bevel_edge_order(bm, bv, first_bme);
/* Fill in other attributes of EdgeHalfs. */
- for (i = 0; i < tot_edges; i++) {
- e = &bv->edges[i];
+ for (int i = 0; i < tot_edges; i++) {
+ EdgeHalf *e = &bv->edges[i];
bme = e->e;
if (BM_elem_flag_test(bme, BM_ELEM_TAG) && bp->affect_type != BEVEL_AFFECT_VERTICES) {
e->is_bev = true;
@@ -6136,24 +5960,26 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
/* If edge array doesn't go CCW around vertex from average normal side,
* reverse the array, being careful to reverse face pointers too. */
if (tot_edges > 1) {
- ccw_test_sum = 0;
- for (i = 0; i < tot_edges; i++) {
+ int ccw_test_sum = 0;
+ for (int i = 0; i < tot_edges; i++) {
ccw_test_sum += bev_ccw_test(
bv->edges[i].e, bv->edges[(i + 1) % tot_edges].e, bv->edges[i].fnext);
}
if (ccw_test_sum < 0) {
- for (i = 0; i <= (tot_edges / 2) - 1; i++) {
+ for (int i = 0; i <= (tot_edges / 2) - 1; i++) {
SWAP(EdgeHalf, bv->edges[i], bv->edges[tot_edges - i - 1]);
SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
SWAP(BMFace *, bv->edges[tot_edges - i - 1].fprev, bv->edges[tot_edges - i - 1].fnext);
}
if (tot_edges % 2 == 1) {
- i = tot_edges / 2;
+ int i = tot_edges / 2;
SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
}
}
}
+ float weight;
+ float vert_axis[3] = {0, 0, 0};
if (bp->affect_type == BEVEL_AFFECT_VERTICES) {
/* Modify the offset by the vertex group or bevel weight if they are specified. */
if (bp->dvert != NULL && bp->vertex_group != -1) {
@@ -6167,8 +5993,9 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
/* Find center axis. Note: Don't use vert normal, can give unwanted results. */
if (ELEM(bp->offset_type, BEVEL_AMT_WIDTH, BEVEL_AMT_DEPTH)) {
float edge_dir[3];
- for (i = 0, e = bv->edges; i < tot_edges; i++, e++) {
- v2 = BM_edge_other_vert(e->e, bv->v);
+ EdgeHalf *e = bv->edges;
+ for (int i = 0; i < tot_edges; i++, e++) {
+ BMVert *v2 = BM_edge_other_vert(e->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, v2->co);
normalize_v3(edge_dir);
add_v3_v3v3(vert_axis, vert_axis, edge_dir);
@@ -6177,7 +6004,8 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
/* Set offsets for each beveled edge. */
- for (i = 0, e = bv->edges; i < tot_edges; i++, e++) {
+ EdgeHalf *e = bv->edges;
+ for (int i = 0; i < tot_edges; i++, e++) {
e->next = &bv->edges[(i + 1) % tot_edges];
e->prev = &bv->edges[(i + tot_edges - 1) % tot_edges];
@@ -6187,11 +6015,12 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
* Except for percent method, offset will be same on each side. */
switch (bp->offset_type) {
- case BEVEL_AMT_OFFSET:
+ case BEVEL_AMT_OFFSET: {
e->offset_l_spec = bp->offset;
break;
- case BEVEL_AMT_WIDTH:
- z = fabsf(2.0f * sinf(edge_face_angle(e) / 2.0f));
+ }
+ case BEVEL_AMT_WIDTH: {
+ float z = fabsf(2.0f * sinf(edge_face_angle(e) / 2.0f));
if (z < BEVEL_EPSILON) {
e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
@@ -6199,8 +6028,9 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->offset_l_spec = bp->offset / z;
}
break;
- case BEVEL_AMT_DEPTH:
- z = fabsf(cosf(edge_face_angle(e) / 2.0f));
+ }
+ case BEVEL_AMT_DEPTH: {
+ float z = fabsf(cosf(edge_face_angle(e) / 2.0f));
if (z < BEVEL_EPSILON) {
e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
@@ -6208,32 +6038,36 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->offset_l_spec = bp->offset / z;
}
break;
- case BEVEL_AMT_PERCENT:
+ }
+ case BEVEL_AMT_PERCENT: {
/* Offset needs to meet adjacent edges at percentage of their lengths. */
- v1 = BM_edge_other_vert(e->prev->e, v);
- v2 = BM_edge_other_vert(e->e, v);
- z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
+ BMVert *v1 = BM_edge_other_vert(e->prev->e, v);
+ BMVert *v2 = BM_edge_other_vert(e->e, v);
+ float z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
e->offset_l_spec = BM_edge_calc_length(e->prev->e) * bp->offset * z / 100.0f;
v1 = BM_edge_other_vert(e->e, v);
v2 = BM_edge_other_vert(e->next->e, v);
z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
e->offset_r_spec = BM_edge_calc_length(e->next->e) * bp->offset * z / 100.0f;
break;
- case BEVEL_AMT_ABSOLUTE:
+ }
+ case BEVEL_AMT_ABSOLUTE: {
/* Like Percent, but the amount gives the absolute distance along adjacent edges. */
- v1 = BM_edge_other_vert(e->prev->e, v);
- v2 = BM_edge_other_vert(e->e, v);
- z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
+ BMVert *v1 = BM_edge_other_vert(e->prev->e, v);
+ BMVert *v2 = BM_edge_other_vert(e->e, v);
+ float z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
e->offset_l_spec = bp->offset * z;
v1 = BM_edge_other_vert(e->e, v);
v2 = BM_edge_other_vert(e->next->e, v);
z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
e->offset_r_spec = bp->offset * z;
break;
- default:
+ }
+ default: {
BLI_assert(!"bad bevel offset kind");
e->offset_l_spec = bp->offset;
break;
+ }
}
if (bp->offset_type != BEVEL_AMT_PERCENT && bp->offset_type != BEVEL_AMT_ABSOLUTE) {
e->offset_r_spec = e->offset_l_spec;
@@ -6254,9 +6088,9 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
break;
}
case BEVEL_AMT_WIDTH: {
- v2 = BM_edge_other_vert(e->e, bv->v);
+ BMVert *v2 = BM_edge_other_vert(e->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, v2->co);
- z = fabsf(2.0f * sinf(angle_v3v3(vert_axis, edge_dir)));
+ float z = fabsf(2.0f * sinf(angle_v3v3(vert_axis, edge_dir)));
if (z < BEVEL_EPSILON) {
e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
@@ -6266,9 +6100,9 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
break;
}
case BEVEL_AMT_DEPTH: {
- v2 = BM_edge_other_vert(e->e, bv->v);
+ BMVert *v2 = BM_edge_other_vert(e->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, v2->co);
- z = fabsf(cosf(angle_v3v3(vert_axis, edge_dir)));
+ float z = fabsf(cosf(angle_v3v3(vert_axis, edge_dir)));
if (z < BEVEL_EPSILON) {
e->offset_l_spec = 0.01f * bp->offset; /* Undefined behavior, so tiny bevel. */
}
@@ -6303,8 +6137,8 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
/* Collect wire edges if we found any earlier. */
- if (tot_wire) {
- i = 0;
+ if (tot_wire != 0) {
+ int i = 0;
BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
if (BM_edge_is_wire(bme)) {
BLI_assert(i < bv->wirecount);
@@ -6320,18 +6154,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
/* Face f has at least one beveled vertex. Rebuild f. */
static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
{
- BMIter liter, eiter, fiter;
- BMLoop *l, *lprev;
- BevVert *bv;
- BoundVert *v, *vstart, *vend;
- EdgeHalf *e, *eprev;
- VMesh *vm;
- int i, k, n, kstart, kend;
bool do_rebuild = false;
- bool go_ccw, corner3special, keep, on_profile_start;
- BMVert *bmv;
- BMEdge *bme, *bme_new, *bme_prev;
- BMFace *f_new, *f_other;
BMVert **vv = NULL;
BMVert **vv_fix = NULL;
BMEdge **ee = NULL;
@@ -6339,18 +6162,21 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
BLI_array_staticdeclare(vv_fix, BM_DEFAULT_NGON_STACK_SIZE);
BLI_array_staticdeclare(ee, BM_DEFAULT_NGON_STACK_SIZE);
+ BMIter liter;
+ BMLoop *l;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- lprev = l->prev;
- bv = find_bevvert(bp, l->v);
- vm = bv->vmesh;
- e = find_edge_half(bv, l->e);
+ BMLoop *lprev = l->prev;
+ BevVert *bv = find_bevvert(bp, l->v);
+ VMesh *vm = bv->vmesh;
+ EdgeHalf *e = find_edge_half(bv, l->e);
BLI_assert(e != NULL);
- bme = e->e;
- eprev = find_edge_half(bv, lprev->e);
+ BMEdge *bme = e->e;
+ EdgeHalf *eprev = find_edge_half(bv, lprev->e);
BLI_assert(eprev != NULL);
/* Which direction around our vertex do we travel to match orientation of f? */
+ bool go_ccw;
if (e->prev == eprev) {
if (eprev->prev == e) {
/* Valence 2 vertex: use f is one of e->fnext or e->fprev to break tie. */
@@ -6375,7 +6201,9 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
go_ccw = false;
}
}
- on_profile_start = false;
+ bool on_profile_start = false;
+ BoundVert *vstart;
+ BoundVert *vend;
if (go_ccw) {
vstart = eprev->rightv;
vend = e->leftv;
@@ -6393,16 +6221,17 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
}
BLI_assert(vstart != NULL && vend != NULL);
- v = vstart;
+ BoundVert *v = vstart;
if (!on_profile_start) {
BLI_array_append(vv, v->nv.v);
BLI_array_append(ee, bme);
}
while (v != vend) {
/* Check for special case: multisegment 3rd face opposite a beveled edge with no vmesh. */
- corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
+ bool corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
if (go_ccw) {
- i = v->index;
+ int i = v->index;
+ int kstart, kend;
if (on_profile_start) {
kstart = e->profile_index;
on_profile_start = false;
@@ -6416,8 +6245,8 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
else {
kend = vm->seg;
}
- for (k = kstart; k <= kend; k++) {
- bmv = mesh_vert(vm, i, 0, k)->v;
+ for (int k = kstart; k <= kend; k++) {
+ BMVert *bmv = mesh_vert(vm, i, 0, k)->v;
if (bmv) {
BLI_array_append(vv, bmv);
BLI_array_append(ee, bme); /* TODO: Maybe better edge here. */
@@ -6430,7 +6259,8 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
else {
/* Going cw. */
- i = v->prev->index;
+ int i = v->prev->index;
+ int kstart, kend;
if (on_profile_start) {
kstart = eprev->profile_index;
on_profile_start = false;
@@ -6444,8 +6274,8 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
else {
kend = 0;
}
- for (k = kstart; k >= kend; k--) {
- bmv = mesh_vert(vm, i, 0, k)->v;
+ for (int k = kstart; k >= kend; k--) {
+ BMVert *bmv = mesh_vert(vm, i, 0, k)->v;
if (bmv) {
BLI_array_append(vv, bmv);
BLI_array_append(ee, bme);
@@ -6465,18 +6295,18 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
}
if (do_rebuild) {
- n = BLI_array_len(vv);
- f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true);
+ int n = BLI_array_len(vv);
+ BMFace *f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true);
- for (k = 0; k < BLI_array_len(vv_fix); k++) {
+ for (int k = 0; k < BLI_array_len(vv_fix); k++) {
bev_merge_uvs(bm, vv_fix[k]);
}
/* Copy attributes from old edges. */
BLI_assert(n == BLI_array_len(ee));
- bme_prev = ee[n - 1];
- for (k = 0; k < n; k++) {
- bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]);
+ BMEdge *bme_prev = ee[n - 1];
+ for (int k = 0; k < n; k++) {
+ BMEdge *bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]);
BLI_assert(ee[k] && bme_new);
if (ee[k] != bme_new) {
BM_elem_attrs_copy(bm, bm, ee[k], bme_new);
@@ -6504,8 +6334,12 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
record_face_kind(bp, f_new, F_RECON);
BM_elem_flag_disable(f_new, BM_ELEM_TAG);
/* Also don't want new edges that aren't part of a new bevel face. */
+ BMIter eiter;
+ BMEdge *bme;
BM_ITER_ELEM (bme, &eiter, f_new, BM_EDGES_OF_FACE) {
- keep = false;
+ bool keep = false;
+ BMIter fiter;
+ BMFace *f_other;
BM_ITER_ELEM (f_other, &fiter, bme, BM_FACES_OF_EDGE) {
if (BM_elem_flag_test(f_other, BM_ELEM_TAG)) {
keep = true;
@@ -6550,38 +6384,31 @@ static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *
/* If there were any wire edges, they need to be reattached somewhere. */
static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
{
- BMEdge *e;
- BMVert *vclosest, *vother, *votherclosest;
- BevVert *bv, *bvother;
- BoundVert *bndv, *bndvother;
- float d, dclosest;
- int i;
-
- bv = find_bevvert(bp, v);
+ BevVert *bv = find_bevvert(bp, v);
if (!bv || bv->wirecount == 0 || !bv->vmesh) {
return;
}
- for (i = 0; i < bv->wirecount; i++) {
- e = bv->wire_edges[i];
+ for (int i = 0; i < bv->wirecount; i++) {
+ BMEdge *e = bv->wire_edges[i];
/* Look for the new vertex closest to the other end of e. */
- vclosest = NULL;
- dclosest = FLT_MAX;
- votherclosest = NULL;
- vother = BM_edge_other_vert(e, v);
- bvother = NULL;
+ BMVert *vclosest = NULL;
+ float dclosest = FLT_MAX;
+ BMVert *votherclosest = NULL;
+ BMVert *vother = BM_edge_other_vert(e, v);
+ BevVert *bvother = NULL;
if (BM_elem_flag_test(vother, BM_ELEM_TAG)) {
bvother = find_bevvert(bp, vother);
if (!bvother || !bvother->vmesh) {
return; /* Shouldn't happen. */
}
}
- bndv = bv->vmesh->boundstart;
+ BoundVert *bndv = bv->vmesh->boundstart;
do {
if (bvother) {
- bndvother = bvother->vmesh->boundstart;
+ BoundVert *bndvother = bvother->vmesh->boundstart;
do {
- d = len_squared_v3v3(bndvother->nv.co, bndv->nv.co);
+ float d = len_squared_v3v3(bndvother->nv.co, bndv->nv.co);
if (d < dclosest) {
vclosest = bndv->nv.v;
votherclosest = bndvother->nv.v;
@@ -6590,7 +6417,7 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
} while ((bndvother = bndvother->next) != bvother->vmesh->boundstart);
}
else {
- d = len_squared_v3v3(vother->co, bndv->nv.co);
+ float d = len_squared_v3v3(vother->co, bndv->nv.co);
if (d < dclosest) {
vclosest = bndv->nv.v;
votherclosest = vother;
@@ -6607,11 +6434,10 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
static void bev_merge_end_uvs(BMesh *bm, BevVert *bv, EdgeHalf *e)
{
VMesh *vm = bv->vmesh;
- int i, k, nseg;
- nseg = e->seg;
- i = e->leftv->index;
- for (k = 1; k < nseg; k++) {
+ int nseg = e->seg;
+ int i = e->leftv->index;
+ for (int k = 1; k < nseg; k++) {
bev_merge_uvs(bm, mesh_vert(vm, i, 0, k)->v);
}
}
@@ -6648,12 +6474,9 @@ static bool bevvert_is_weld_cross(BevVert *bv)
*/
static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex, EdgeHalf *e)
{
- BMEdge *bme_prev, *bme_next, *bme;
- int i, nseg;
- bool disable_seam, enable_smooth;
-
- bme_prev = bme_next = NULL;
- for (i = 0; i < 4; i++) {
+ BMEdge *bme_prev = NULL;
+ BMEdge *bme_next = NULL;
+ for (int i = 0; i < 4; i++) {
if (&bv->edges[i] == e) {
bme_prev = bv->edges[(i + 3) % 4].e;
bme_next = bv->edges[(i + 1) % 4].e;
@@ -6663,14 +6486,15 @@ static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex
BLI_assert(bme_prev && bme_next);
/* Want seams and sharp edges to cross only if that way on both sides. */
- disable_seam = BM_elem_flag_test(bme_prev, BM_ELEM_SEAM) !=
- BM_elem_flag_test(bme_next, BM_ELEM_SEAM);
- enable_smooth = BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH) !=
- BM_elem_flag_test(bme_next, BM_ELEM_SMOOTH);
-
- nseg = e->seg;
- for (i = 0; i < nseg; i++) {
- bme = BM_edge_exists(mesh_vert(vm, vmindex, 0, i)->v, mesh_vert(vm, vmindex, 0, i + 1)->v);
+ bool disable_seam = BM_elem_flag_test(bme_prev, BM_ELEM_SEAM) !=
+ BM_elem_flag_test(bme_next, BM_ELEM_SEAM);
+ bool enable_smooth = BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH) !=
+ BM_elem_flag_test(bme_next, BM_ELEM_SMOOTH);
+
+ int nseg = e->seg;
+ for (int i = 0; i < nseg; i++) {
+ BMEdge *bme = BM_edge_exists(mesh_vert(vm, vmindex, 0, i)->v,
+ mesh_vert(vm, vmindex, 0, i + 1)->v);
BLI_assert(bme);
BM_elem_attrs_copy(bm, bm, bme_prev, bme);
if (disable_seam) {
@@ -6687,31 +6511,19 @@ static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex
*/
static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
{
- BevVert *bv1, *bv2;
- BMVert *bmv1, *bmv2, *bmv3, *bmv4;
- VMesh *vm1, *vm2;
- EdgeHalf *e1, *e2;
- BMEdge *bme1, *bme2, *center_bme;
- BMFace *f1, *f2, *f, *r_f, *f_choice;
- BMVert *verts[4];
- BMFace *faces[4];
- BMEdge *edges[4];
- BMLoop *l;
- BMIter iter;
- int k, nseg, i1, i2, odd, mid;
int mat_nr = bp->mat_nr;
if (!BM_edge_is_manifold(bme)) {
return;
}
- bv1 = find_bevvert(bp, bme->v1);
- bv2 = find_bevvert(bp, bme->v2);
+ BevVert *bv1 = find_bevvert(bp, bme->v1);
+ BevVert *bv2 = find_bevvert(bp, bme->v2);
BLI_assert(bv1 && bv2);
- e1 = find_edge_half(bv1, bme);
- e2 = find_edge_half(bv2, bme);
+ EdgeHalf *e1 = find_edge_half(bv1, bme);
+ EdgeHalf *e2 = find_edge_half(bv2, bme);
BLI_assert(e1 && e2);
@@ -6725,40 +6537,43 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
* \ | /
* bme->v2
*/
- nseg = e1->seg;
+ int nseg = e1->seg;
BLI_assert(nseg > 0 && nseg == e2->seg);
- bmv1 = e1->leftv->nv.v;
- bmv4 = e1->rightv->nv.v;
- bmv2 = e2->rightv->nv.v;
- bmv3 = e2->leftv->nv.v;
+ BMVert *bmv1 = e1->leftv->nv.v;
+ BMVert *bmv4 = e1->rightv->nv.v;
+ BMVert *bmv2 = e2->rightv->nv.v;
+ BMVert *bmv3 = e2->leftv->nv.v;
BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
- f1 = e1->fprev;
- f2 = e1->fnext;
- faces[0] = faces[1] = f1;
- faces[2] = faces[3] = f2;
- i1 = e1->leftv->index;
- i2 = e2->leftv->index;
- vm1 = bv1->vmesh;
- vm2 = bv2->vmesh;
+ BMFace *f1 = e1->fprev;
+ BMFace *f2 = e1->fnext;
+ BMFace *faces[4] = {f1, f1, f2, f2};
+
+ int i1 = e1->leftv->index;
+ int i2 = e2->leftv->index;
+ VMesh *vm1 = bv1->vmesh;
+ VMesh *vm2 = bv2->vmesh;
+ BMVert *verts[4];
verts[0] = bmv1;
verts[1] = bmv2;
- odd = nseg % 2;
- mid = nseg / 2;
- center_bme = NULL;
- for (k = 1; k <= nseg; k++) {
+ int odd = nseg % 2;
+ int mid = nseg / 2;
+ BMEdge *center_bme = NULL;
+ for (int k = 1; k <= nseg; k++) {
verts[3] = mesh_vert(vm1, i1, 0, k)->v;
verts[2] = mesh_vert(vm2, i2, 0, nseg - k)->v;
+ BMFace *r_f;
if (odd && k == mid + 1) {
BMFace *fchoices[2] = {f1, f2};
- f_choice = choose_rep_face(bp, fchoices, 2);
+ BMFace *f_choice = choose_rep_face(bp, fchoices, 2);
if (e1->is_seam) {
/* Straddles a seam: choose to interpolate in f_choice and snap the loops whose verts
* are in the non-chosen face to bme for interpolation purposes.
*/
+ BMEdge *edges[4];
if (f_choice == f1) {
edges[0] = edges[1] = NULL;
edges[2] = edges[3] = bme;
@@ -6776,25 +6591,25 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
}
else if (!odd && k == mid) {
/* Left poly that touches an even center line on right. */
- edges[0] = edges[1] = NULL;
- edges[2] = edges[3] = bme;
+ BMEdge *edges[4] = {NULL, NULL, bme, bme};
r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
center_bme = BM_edge_exists(verts[2], verts[3]);
BLI_assert(center_bme != NULL);
}
else if (!odd && k == mid + 1) {
/* Right poly that touches an even center line on left. */
- edges[0] = edges[1] = bme;
- edges[2] = edges[3] = NULL;
+ BMEdge *edges[4] = {bme, bme, NULL, NULL};
r_f = bev_create_ngon(bm, verts, 4, NULL, f2, edges, mat_nr, true);
}
else {
/* Doesn't cross or touch the center line, so interpolate in appropriate f1 or f2. */
- f = (k <= mid) ? f1 : f2;
+ BMFace *f = (k <= mid) ? f1 : f2;
r_f = bev_create_ngon(bm, verts, 4, NULL, f, NULL, mat_nr, true);
}
record_face_kind(bp, r_f, F_EDGE);
/* Tag the long edges: those out of verts[0] and verts[2]. */
+ BMIter iter;
+ BMLoop *l;
BM_ITER_ELEM (l, &iter, r_f, BM_LOOPS_OF_FACE) {
if (l->v == verts[0] || l->v == verts[2]) {
BM_elem_flag_enable(l, BM_ELEM_LONG_TAG);
@@ -6822,8 +6637,8 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
}
/* Copy edge data to first and last edge. */
- bme1 = BM_edge_exists(bmv1, bmv2);
- bme2 = BM_edge_exists(bmv3, bmv4);
+ BMEdge *bme1 = BM_edge_exists(bmv1, bmv2);
+ BMEdge *bme2 = BM_edge_exists(bmv3, bmv4);
BLI_assert(bme1 && bme2);
BM_elem_attrs_copy(bm, bm, bme, bme1);
BM_elem_attrs_copy(bm, bm, bme, bme2);
@@ -6843,34 +6658,32 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
* Assumes that the gradient is always between 1 and -1 for x in [x0, x0+dtarget]. */
static double find_superellipse_chord_endpoint(double x0, double dtarget, float r, bool rbig)
{
- double xmin, xmax, ymin, ymax, dmaxerr, dminerr, dnewerr, xnew, ynew;
double y0 = superellipse_co(x0, r, rbig);
const double tol = 1e-13; /* accumulates for many segments so use low value. */
const int maxiter = 10;
- bool lastupdated_upper;
/* For gradient between -1 and 1, xnew can only be in [x0 + sqrt(2)/2*dtarget, x0 + dtarget]. */
- xmin = x0 + M_SQRT2 / 2.0 * dtarget;
+ double xmin = x0 + M_SQRT2 / 2.0 * dtarget;
if (xmin > 1.0) {
xmin = 1.0;
}
- xmax = x0 + dtarget;
+ double xmax = x0 + dtarget;
if (xmax > 1.0) {
xmax = 1.0;
}
- ymin = superellipse_co(xmin, r, rbig);
- ymax = superellipse_co(xmax, r, rbig);
+ double ymin = superellipse_co(xmin, r, rbig);
+ double ymax = superellipse_co(xmax, r, rbig);
/* Note: using distance**2 (no sqrt needed) does not converge that well. */
- dmaxerr = sqrt(pow((xmax - x0), 2) + pow((ymax - y0), 2)) - dtarget;
- dminerr = sqrt(pow((xmin - x0), 2) + pow((ymin - y0), 2)) - dtarget;
+ double dmaxerr = sqrt(pow((xmax - x0), 2) + pow((ymax - y0), 2)) - dtarget;
+ double dminerr = sqrt(pow((xmin - x0), 2) + pow((ymin - y0), 2)) - dtarget;
- xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
- lastupdated_upper = true;
+ double xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
+ bool lastupdated_upper = true;
for (int iter = 0; iter < maxiter; iter++) {
- ynew = superellipse_co(xnew, r, rbig);
- dnewerr = sqrt(pow((xnew - x0), 2) + pow((ynew - y0), 2)) - dtarget;
+ double ynew = superellipse_co(xnew, r, rbig);
+ double dnewerr = sqrt(pow((xnew - x0), 2) + pow((ynew - y0), 2)) - dtarget;
if (fabs(dnewerr) < tol) {
break;
}
@@ -6915,19 +6728,12 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
{
const int smoothitermax = 10;
const double error_tol = 1e-7;
- int i;
int imax = (seg + 1) / 2 - 1; /* Ceiling division - 1. */
- double d, dmin, dmax;
- double davg;
- double mx;
- double sum;
- double temp;
-
- bool precision_reached = true;
bool seg_odd = seg % 2;
- bool rbig;
+ bool rbig;
+ double mx;
if (r > 1.0f) {
rbig = true;
mx = pow(0.5, 1.0 / r);
@@ -6938,7 +6744,7 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
}
/* Initial positions, linear spacing along x axis. */
- for (i = 0; i <= imax; i++) {
+ for (int i = 0; i <= imax; i++) {
xvals[i] = i * mx / seg * 2;
yvals[i] = superellipse_co(xvals[i], r, rbig);
}
@@ -6946,14 +6752,14 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
/* Smooth distance loop. */
for (int iter = 0; iter < smoothitermax; iter++) {
- sum = 0.0;
- dmin = 2.0;
- dmax = 0.0;
+ double sum = 0.0;
+ double dmin = 2.0;
+ double dmax = 0.0;
/* Update distances between neighbor points. Store the highest and
* lowest to see if the maximum error to average distance (which isn't
* known yet) is below required precision. */
- for (i = 0; i < imax; i++) {
- d = sqrt(pow((xvals[i + 1] - xvals[i]), 2) + pow((yvals[i + 1] - yvals[i]), 2));
+ for (int i = 0; i < imax; i++) {
+ double d = sqrt(pow((xvals[i + 1] - xvals[i]), 2) + pow((yvals[i + 1] - yvals[i]), 2));
sum += d;
if (d > dmax) {
dmax = d;
@@ -6963,6 +6769,7 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
}
}
/* For last distance, weight with 1/2 if seg_odd. */
+ double davg;
if (seg_odd) {
sum += M_SQRT2 / 2 * (yvals[imax] - xvals[imax]);
davg = sum / (imax + 0.5);
@@ -6972,6 +6779,7 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
davg = sum / (imax + 1.0);
}
/* Max error in tolerance? -> Quit. */
+ bool precision_reached = true;
if (dmax - davg > error_tol) {
precision_reached = false;
}
@@ -6983,7 +6791,7 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
}
/* Update new coordinates. */
- for (i = 1; i <= imax; i++) {
+ for (int i = 1; i <= imax; i++) {
xvals[i] = find_superellipse_chord_endpoint(xvals[i - 1], davg, r, rbig);
yvals[i] = superellipse_co(xvals[i], r, rbig);
}
@@ -6994,14 +6802,14 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
xvals[imax + 1] = mx;
yvals[imax + 1] = mx;
}
- for (i = imax + 1; i <= seg; i++) {
+ for (int i = imax + 1; i <= seg; i++) {
yvals[i] = xvals[seg - i];
xvals[i] = yvals[seg - i];
}
if (!rbig) {
- for (i = 0; i <= seg; i++) {
- temp = xvals[i];
+ for (int i = 0; i <= seg; i++) {
+ double temp = xvals[i];
xvals[i] = 1.0 - yvals[i];
yvals[i] = 1.0 - temp;
}
@@ -7018,25 +6826,22 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
*/
static void find_even_superellipse_chords(int n, float r, double *xvals, double *yvals)
{
- int i, n2;
- double temp;
bool seg_odd = n % 2;
-
- n2 = n / 2;
+ int n2 = n / 2;
/* Special cases. */
if (r == PRO_LINE_R) {
/* Linear spacing. */
- for (i = 0; i <= n; i++) {
+ for (int i = 0; i <= n; i++) {
xvals[i] = (double)i / n;
yvals[i] = 1.0 - (double)i / n;
}
return;
}
if (r == PRO_CIRCLE_R) {
- temp = (M_PI / 2) / n;
+ double temp = (M_PI / 2) / n;
/* Angle spacing. */
- for (i = 0; i <= n; i++) {
+ for (int i = 0; i <= n; i++) {
xvals[i] = sin(i * temp);
yvals[i] = cos(i * temp);
}
@@ -7045,7 +6850,7 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
if (r == PRO_SQUARE_IN_R) {
/* n is even, distribute first and second half linear. */
if (!seg_odd) {
- for (i = 0; i <= n2; i++) {
+ for (int i = 0; i <= n2; i++) {
xvals[i] = 0.0;
yvals[i] = 1.0 - (double)i / n2;
xvals[n - i] = yvals[i];
@@ -7054,8 +6859,8 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
}
/* n is odd, so get one corner-cut chord. */
else {
- temp = 1.0 / (n2 + M_SQRT2 / 2.0);
- for (i = 0; i <= n2; i++) {
+ double temp = 1.0 / (n2 + M_SQRT2 / 2.0);
+ for (int i = 0; i <= n2; i++) {
xvals[i] = 0.0;
yvals[i] = 1.0 - (double)i * temp;
xvals[n - i] = yvals[i];
@@ -7067,7 +6872,7 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
if (r == PRO_SQUARE_R) {
/* n is even, distribute first and second half linear. */
if (!seg_odd) {
- for (i = 0; i <= n2; i++) {
+ for (int i = 0; i <= n2; i++) {
xvals[i] = (double)i / n2;
yvals[i] = 1.0;
xvals[n - i] = yvals[i];
@@ -7076,8 +6881,8 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
}
/* n is odd, so get one corner-cut chord. */
else {
- temp = 1.0 / (n2 + M_SQRT2 / 2);
- for (i = 0; i <= n2; i++) {
+ double temp = 1.0 / (n2 + M_SQRT2 / 2);
+ for (int i = 0; i <= n2; i++) {
xvals[i] = (double)i * temp;
yvals[i] = 1.0;
xvals[n - i] = yvals[i];
@@ -7097,7 +6902,6 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
*/
static float find_profile_fullness(BevelParams *bp)
{
- float fullness;
int nseg = bp->seg;
/* Precalculated fullness for circle profile radius and more common low seg values. */
@@ -7116,6 +6920,7 @@ static float find_profile_fullness(BevelParams *bp)
0.647f, /* 11 */
};
+ float fullness;
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Set fullness to the average "height" of the profile's sampled points. */
fullness = 0.0f;
@@ -7244,19 +7049,15 @@ static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bo
*/
static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
{
- EdgeHalf *ea, *ec, *ebother;
- BevVert *bvc;
- BMLoop *lb;
- BMVert *va, *vb, *vc, *vd;
- float ka, kb, kc, g, h, t, den, no_collide_offset, th1, th2, sin1, sin2, tan1, tan2, limit;
-
- limit = no_collide_offset = bp->offset + 1e6;
+ float no_collide_offset = bp->offset + 1e6;
+ float limit = no_collide_offset;
if (bp->offset == 0.0f) {
return no_collide_offset;
}
- kb = eb->offset_l_spec;
- ea = eb->next; /* Note: this is in direction b --> a. */
- ka = ea->offset_r_spec;
+ float kb = eb->offset_l_spec;
+ EdgeHalf *ea = eb->next; /* Note: this is in direction b --> a. */
+ float ka = ea->offset_r_spec;
+ BMVert *vb, *vc;
if (eb->is_rev) {
vc = eb->e->v1;
vb = eb->e->v2;
@@ -7265,9 +7066,12 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
vb = eb->e->v1;
vc = eb->e->v2;
}
- va = ea->is_rev ? ea->e->v1 : ea->e->v2;
- bvc = NULL;
- ebother = find_other_end_edge_half(bp, eb, &bvc);
+ BMVert *va = ea->is_rev ? ea->e->v1 : ea->e->v2;
+ BevVert *bvc = NULL;
+ EdgeHalf *ebother = find_other_end_edge_half(bp, eb, &bvc);
+ EdgeHalf *ec;
+ BMVert *vd;
+ float kc;
if (ebother != NULL) {
ec = ebother->prev; /* Note: this is in direction c --> d. */
vc = bvc->v;
@@ -7279,7 +7083,7 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
kc = 0.0f;
ec = NULL;
/* Find an edge from c that has same face. */
- lb = BM_face_edge_share_loop(eb->fnext, eb->e);
+ BMLoop *lb = BM_face_edge_share_loop(eb->fnext, eb->e);
if (!lb) {
return no_collide_offset;
}
@@ -7299,22 +7103,22 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
ka = ka / bp->offset;
kb = kb / bp->offset;
kc = kc / bp->offset;
- th1 = angle_v3v3v3(va->co, vb->co, vc->co);
- th2 = angle_v3v3v3(vb->co, vc->co, vd->co);
+ float th1 = angle_v3v3v3(va->co, vb->co, vc->co);
+ float th2 = angle_v3v3v3(vb->co, vc->co, vd->co);
/* First calculate offset at which edge B collapses, which happens
* when advancing clones of A, B, C all meet at a point.
* This only happens if at least two of those three edges have non-zero k's. */
- sin1 = sinf(th1);
- sin2 = sinf(th2);
+ float sin1 = sinf(th1);
+ float sin2 = sinf(th2);
if ((ka > 0.0f) + (kb > 0.0f) + (kc > 0.0f) >= 2) {
- tan1 = tanf(th1);
- tan2 = tanf(th2);
- g = tan1 * tan2;
- h = sin1 * sin2;
- den = g * (ka * sin2 + kc * sin1) + kb * h * (tan1 + tan2);
+ float tan1 = tanf(th1);
+ float tan2 = tanf(th2);
+ float g = tan1 * tan2;
+ float h = sin1 * sin2;
+ float den = g * (ka * sin2 + kc * sin1) + kb * h * (tan1 + tan2);
if (den != 0.0f) {
- t = BM_edge_calc_length(eb->e);
+ float t = BM_edge_calc_length(eb->e);
t *= g * h / den;
if (t >= 0.0f) {
limit = t;
@@ -7324,14 +7128,14 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
/* Now check edge slide cases. */
if (kb > 0.0f && ka == 0.0f /*&& bvb->selcount == 1 && bvb->edgecount > 2 */) {
- t = BM_edge_calc_length(ea->e);
+ float t = BM_edge_calc_length(ea->e);
t *= sin1 / kb;
if (t >= 0.0f && t < limit) {
limit = t;
}
}
if (kb > 0.0f && kc == 0.0f /* && bvc && ec && bvc->selcount == 1 && bvc->edgecount > 2 */) {
- t = BM_edge_calc_length(ec->e);
+ float t = BM_edge_calc_length(ec->e);
t *= sin2 / kb;
if (t >= 0.0f && t < limit) {
limit = t;
@@ -7347,18 +7151,16 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
*/
static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
{
- float limit, ka, kb, no_collide_offset, la, kab;
- EdgeHalf *eb;
-
- limit = no_collide_offset = bp->offset + 1e6;
+ float no_collide_offset = bp->offset + 1e6;
+ float limit = no_collide_offset;
if (bp->offset == 0.0f) {
return no_collide_offset;
}
- ka = ea->offset_l_spec / bp->offset;
- eb = find_other_end_edge_half(bp, ea, NULL);
- kb = eb ? eb->offset_l_spec / bp->offset : 0.0f;
- kab = ka + kb;
- la = BM_edge_calc_length(ea->e);
+ float ka = ea->offset_l_spec / bp->offset;
+ EdgeHalf *eb = find_other_end_edge_half(bp, ea, NULL);
+ float kb = eb ? eb->offset_l_spec / bp->offset : 0.0f;
+ float kab = ka + kb;
+ float la = BM_edge_calc_length(ea->e);
if (kab <= 0.0f) {
return no_collide_offset;
}
@@ -7373,32 +7175,27 @@ static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
*/
static void bevel_limit_offset(BevelParams *bp, BMesh *bm)
{
- BevVert *bv;
- EdgeHalf *eh;
+ float limited_offset = bp->offset;
BMIter iter;
BMVert *bmv;
- float limited_offset, offset_factor, collision_offset;
- int i;
-
- limited_offset = bp->offset;
BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
continue;
}
- bv = find_bevvert(bp, bmv);
+ BevVert *bv = find_bevvert(bp, bmv);
if (!bv) {
continue;
}
- for (i = 0; i < bv->edgecount; i++) {
- eh = &bv->edges[i];
+ for (int i = 0; i < bv->edgecount; i++) {
+ EdgeHalf *eh = &bv->edges[i];
if (bp->affect_type == BEVEL_AFFECT_VERTICES) {
- collision_offset = vertex_collide_offset(bp, eh);
+ float collision_offset = vertex_collide_offset(bp, eh);
if (collision_offset < limited_offset) {
limited_offset = collision_offset;
}
}
else {
- collision_offset = geometry_collide_offset(bp, eh);
+ float collision_offset = geometry_collide_offset(bp, eh);
if (collision_offset < limited_offset) {
limited_offset = collision_offset;
}
@@ -7412,17 +7209,17 @@ static void bevel_limit_offset(BevelParams *bp, BMesh *bm)
* of the offset to have the effect of recalculating the specs
* with the new limited_offset.
*/
- offset_factor = limited_offset / bp->offset;
+ float offset_factor = limited_offset / bp->offset;
BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
continue;
}
- bv = find_bevvert(bp, bmv);
+ BevVert *bv = find_bevvert(bp, bmv);
if (!bv) {
continue;
}
- for (i = 0; i < bv->edgecount; i++) {
- eh = &bv->edges[i];
+ for (int i = 0; i < bv->edgecount; i++) {
+ EdgeHalf *eh = &bv->edges[i];
eh->offset_l_spec *= offset_factor;
eh->offset_r_spec *= offset_factor;
eh->offset_l *= offset_factor;
@@ -7475,34 +7272,38 @@ void BM_mesh_bevel(BMesh *bm,
BMFace *f;
BMLoop *l;
BevVert *bv;
- BevelParams bp = {NULL};
-
- bp.offset = offset;
- bp.offset_type = offset_type;
- bp.seg = segments;
- bp.profile = profile;
- bp.pro_super_r = -logf(2.0) / logf(sqrtf(profile)); /* Convert to superellipse exponent. */
- bp.affect_type = affect_type;
- bp.use_weights = use_weights;
- bp.loop_slide = loop_slide;
- bp.limit_offset = limit_offset;
- bp.offset_adjust = bp.affect_type != BEVEL_AFFECT_VERTICES &&
- !ELEM(offset_type, BEVEL_AMT_PERCENT, BEVEL_AMT_ABSOLUTE);
- bp.dvert = dvert;
- bp.vertex_group = vertex_group;
- bp.mat_nr = mat;
- bp.mark_seam = mark_seam;
- bp.mark_sharp = mark_sharp;
- bp.harden_normals = harden_normals;
- bp.face_strength_mode = face_strength_mode;
- bp.miter_outer = miter_outer;
- bp.miter_inner = miter_inner;
- bp.spread = spread;
- bp.smoothresh = smoothresh;
- bp.face_hash = NULL;
- bp.profile_type = profile_type;
- bp.custom_profile = custom_profile;
- bp.vmesh_method = vmesh_method;
+ BevelParams bp = {
+ .offset = offset,
+ .offset_type = offset_type,
+ .seg = max_ii(segments, 1),
+ .profile = profile,
+ .pro_super_r = -logf(2.0) / logf(sqrtf(profile)), /* Convert to superellipse exponent. */
+ .affect_type = affect_type,
+ .use_weights = use_weights,
+ .loop_slide = loop_slide,
+ .limit_offset = limit_offset,
+ .offset_adjust = (bp.affect_type != BEVEL_AFFECT_VERTICES) &&
+ !ELEM(offset_type, BEVEL_AMT_PERCENT, BEVEL_AMT_ABSOLUTE),
+ .dvert = dvert,
+ .vertex_group = vertex_group,
+ .mat_nr = mat,
+ .mark_seam = mark_seam,
+ .mark_sharp = mark_sharp,
+ .harden_normals = harden_normals,
+ .face_strength_mode = face_strength_mode,
+ .miter_outer = miter_outer,
+ .miter_inner = miter_inner,
+ .spread = spread,
+ .smoothresh = smoothresh,
+ .face_hash = NULL,
+ .profile_type = profile_type,
+ .custom_profile = custom_profile,
+ .vmesh_method = vmesh_method,
+ };
+
+ if (bp.offset <= 0) {
+ return;
+ }
#ifdef BEVEL_DEBUG_TIME
double start_time = PIL_check_seconds_timer();
@@ -7514,10 +7315,6 @@ void BM_mesh_bevel(BMesh *bm,
bp.miter_inner = BEVEL_MITER_SHARP;
}
- if (bp.seg <= 1) {
- bp.seg = 1;
- }
-
if (profile >= 0.950f) { /* r ~ 692, so PRO_SQUARE_R is 1e4 */
bp.pro_super_r = PRO_SQUARE_R;
}
@@ -7531,151 +7328,150 @@ void BM_mesh_bevel(BMesh *bm,
bp.pro_super_r = PRO_SQUARE_IN_R;
}
- if (bp.offset > 0) {
- /* Primary alloc. */
- bp.vert_hash = BLI_ghash_ptr_new(__func__);
- bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__);
- BLI_memarena_use_calloc(bp.mem_arena);
-
- /* Get the 2D profile point locations from either the superellipse or the custom profile. */
- set_profile_spacing(&bp, &bp.pro_spacing, bp.profile_type == BEVEL_PROFILE_CUSTOM);
+ /* Primary alloc. */
+ bp.vert_hash = BLI_ghash_ptr_new(__func__);
+ bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__);
+ BLI_memarena_use_calloc(bp.mem_arena);
- /* Get the 'fullness' of the profile for the ADJ vertex mesh method. */
- if (bp.seg > 1) {
- bp.pro_spacing.fullness = find_profile_fullness(&bp);
- }
-
- /* Get separate non-custom profile samples for the miter profiles if they are needed */
- if (bp.profile_type == BEVEL_PROFILE_CUSTOM &&
- (bp.miter_inner != BEVEL_MITER_SHARP || bp.miter_outer != BEVEL_MITER_SHARP)) {
- set_profile_spacing(&bp, &bp.pro_spacing_miter, false);
- }
+ /* Get the 2D profile point locations from either the superellipse or the custom profile. */
+ set_profile_spacing(&bp, &bp.pro_spacing, bp.profile_type == BEVEL_PROFILE_CUSTOM);
- bp.face_hash = BLI_ghash_ptr_new(__func__);
- BLI_ghash_flag_set(bp.face_hash, GHASH_FLAG_ALLOW_DUPES);
+ /* Get the 'fullness' of the profile for the ADJ vertex mesh method. */
+ if (bp.seg > 1) {
+ bp.pro_spacing.fullness = find_profile_fullness(&bp);
+ }
- math_layer_info_init(&bp, bm);
+ /* Get separate non-custom profile samples for the miter profiles if they are needed */
+ if (bp.profile_type == BEVEL_PROFILE_CUSTOM &&
+ (bp.miter_inner != BEVEL_MITER_SHARP || bp.miter_outer != BEVEL_MITER_SHARP)) {
+ set_profile_spacing(&bp, &bp.pro_spacing_miter, false);
+ }
- /* Analyze input vertices, sorting edges and assigning initial new vertex positions. */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bv = bevel_vert_construct(bm, &bp, v);
- if (!limit_offset && bv) {
- build_boundary(&bp, bv, true);
- }
- }
- }
+ bp.face_hash = BLI_ghash_ptr_new(__func__);
+ BLI_ghash_flag_set(bp.face_hash, GHASH_FLAG_ALLOW_DUPES);
- /* Perhaps clamp offset to avoid geometry colliisions. */
- if (limit_offset) {
- bevel_limit_offset(&bp, bm);
+ math_layer_info_init(&bp, bm);
- /* Assign initial new vertex positions. */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bv = find_bevvert(&bp, v);
- if (bv) {
- build_boundary(&bp, bv, true);
- }
- }
+ /* Analyze input vertices, sorting edges and assigning initial new vertex positions. */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = bevel_vert_construct(bm, &bp, v);
+ if (!limit_offset && bv) {
+ build_boundary(&bp, bv, true);
}
}
+ }
- /* Perhaps do a pass to try to even out widths. */
- if (bp.offset_adjust) {
- adjust_offsets(&bp, bm);
- }
-
- /* Maintain consistent orientations for the asymmetrical custom profiles. */
- if (bp.profile_type == BEVEL_PROFILE_CUSTOM) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- regularize_profile_orientation(&bp, e);
- }
- }
- }
+ /* Perhaps clamp offset to avoid geometry colliisions. */
+ if (limit_offset) {
+ bevel_limit_offset(&bp, bm);
- /* Build the meshes around vertices, now that positions are final. */
+ /* Assign initial new vertex positions. */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
bv = find_bevvert(&bp, v);
if (bv) {
- build_vmesh(&bp, bm, bv);
+ build_boundary(&bp, bv, true);
}
}
}
+ }
- /* Build polygons for edges. */
- if (bp.affect_type != BEVEL_AFFECT_VERTICES) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- bevel_build_edge_polygons(bm, &bp, e);
- }
+ /* Perhaps do a pass to try to even out widths. */
+ if (bp.offset_adjust) {
+ adjust_offsets(&bp, bm);
+ }
+
+ /* Maintain consistent orientations for the asymmetrical custom profiles. */
+ if (bp.profile_type == BEVEL_PROFILE_CUSTOM) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ regularize_profile_orientation(&bp, e);
}
}
+ }
- /* Extend edge data like sharp edges and precompute normals for harden. */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bv = find_bevvert(&bp, v);
- if (bv) {
- bevel_extend_edge_data(bv);
- }
+ /* Build the meshes around vertices, now that positions are final. */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = find_bevvert(&bp, v);
+ if (bv) {
+ build_vmesh(&bp, bm, bv);
}
}
+ }
- /* Rebuild face polygons around affected vertices. */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bevel_rebuild_existing_polygons(bm, &bp, v);
- bevel_reattach_wires(bm, &bp, v);
+ /* Build polygons for edges. */
+ if (bp.affect_type != BEVEL_AFFECT_VERTICES) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ bevel_build_edge_polygons(bm, &bp, e);
}
}
+ }
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BLI_assert(find_bevvert(&bp, v) != NULL);
- BM_vert_kill(bm, v);
+ /* Extend edge data like sharp edges and precompute normals for harden. */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = find_bevvert(&bp, v);
+ if (bv) {
+ bevel_extend_edge_data(bv);
}
}
+ }
- if (bp.harden_normals) {
- bevel_harden_normals(&bp, bm);
- }
- if (bp.face_strength_mode != BEVEL_FACE_STRENGTH_NONE) {
- bevel_set_weighted_normal_face_strength(bm, &bp);
+ /* Rebuild face polygons around affected vertices. */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bevel_rebuild_existing_polygons(bm, &bp, v);
+ bevel_reattach_wires(bm, &bp, v);
}
+ }
- /* When called from operator (as opposed to modifier), bm->use_toolflags
- * will be set, and we need to transfer the oflags to BM_ELEM_TAGs. */
- if (bm->use_toolflags) {
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, VERT_OUT)) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
- }
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test(bm, e, EDGE_OUT)) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- }
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BLI_assert(find_bevvert(&bp, v) != NULL);
+ BM_vert_kill(bm, v);
}
+ }
- /* Clear the BM_ELEM_LONG_TAG tags, which were only set on some edges in F_EDGE faces. */
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (get_face_kind(&bp, f) != F_EDGE) {
- continue;
+ if (bp.harden_normals) {
+ bevel_harden_normals(&bp, bm);
+ }
+ if (bp.face_strength_mode != BEVEL_FACE_STRENGTH_NONE) {
+ bevel_set_weighted_normal_face_strength(bm, &bp);
+ }
+
+ /* When called from operator (as opposed to modifier), bm->use_toolflags
+ * will be set, and we need to transfer the oflags to BM_ELEM_TAGs. */
+ if (bm->use_toolflags) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, VERT_OUT)) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
}
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_elem_flag_disable(l, BM_ELEM_LONG_TAG);
+ }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, EDGE_OUT)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
}
}
+ }
- /* Primary free. */
- BLI_ghash_free(bp.vert_hash, NULL, NULL);
- BLI_ghash_free(bp.face_hash, NULL, NULL);
- BLI_memarena_free(bp.mem_arena);
+ /* Clear the BM_ELEM_LONG_TAG tags, which were only set on some edges in F_EDGE faces. */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (get_face_kind(&bp, f) != F_EDGE) {
+ continue;
+ }
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_elem_flag_disable(l, BM_ELEM_LONG_TAG);
+ }
}
+
+ /* Primary free. */
+ BLI_ghash_free(bp.vert_hash, NULL, NULL);
+ BLI_ghash_free(bp.face_hash, NULL, NULL);
+ BLI_memarena_free(bp.mem_arena);
+
#ifdef BEVEL_DEBUG_TIME
double end_time = PIL_check_seconds_timer();
printf("BMESH BEVEL TIME = %.3f\n", end_time - start_time);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
index b853ecd8e56..cab20dadc50 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
@@ -127,7 +127,7 @@ Relation *DepsgraphRelationBuilder::add_node_handle_relation(const KeyType &key_
return nullptr;
}
-static bool rigidbody_object_depends_on_evaluated_geometry(const RigidBodyOb *rbo)
+static inline bool rigidbody_object_depends_on_evaluated_geometry(const RigidBodyOb *rbo)
{
if (rbo == nullptr) {
return false;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index ec18b429c2e..18b24179edf 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -311,7 +311,11 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
contains(prop_identifier, "rotation_axis_angle") ||
contains(prop_identifier, "rotation_euler") ||
contains(prop_identifier, "rotation_mode") ||
- contains(prop_identifier, "rotation_quaternion") || contains(prop_identifier, "scale")) {
+ contains(prop_identifier, "rotation_quaternion") || contains(prop_identifier, "scale") ||
+ contains(prop_identifier, "delta_location") ||
+ contains(prop_identifier, "delta_rotation_euler") ||
+ contains(prop_identifier, "delta_rotation_quaternion") ||
+ contains(prop_identifier, "delta_scale")) {
node_identifier.type = NodeType::TRANSFORM;
return node_identifier;
}
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index c475e5287c2..e18c43fc643 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -29,6 +29,7 @@
#include "BKE_duplilist.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
@@ -42,15 +43,20 @@
static void eevee_motion_blur_mesh_data_free(void *val)
{
EEVEE_GeometryMotionData *geom_mb = (EEVEE_GeometryMotionData *)val;
+ EEVEE_HairMotionData *hair_mb = (EEVEE_HairMotionData *)val;
switch (geom_mb->type) {
- case EEVEE_HAIR_GEOM_MOTION_DATA:
- for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
- GPU_VERTBUF_DISCARD_SAFE(geom_mb->hair_pos[i]);
- DRW_TEXTURE_FREE_SAFE(geom_mb->hair_pos_tx[i]);
+ case EEVEE_MOTION_DATA_HAIR:
+ for (int j = 0; j < hair_mb->psys_len; j++) {
+ for (int i = 0; i < ARRAY_SIZE(hair_mb->psys[0].hair_pos); i++) {
+ GPU_VERTBUF_DISCARD_SAFE(hair_mb->psys[j].hair_pos[i]);
+ }
+ for (int i = 0; i < ARRAY_SIZE(hair_mb->psys[0].hair_pos); i++) {
+ DRW_TEXTURE_FREE_SAFE(hair_mb->psys[j].hair_pos_tx[i]);
+ }
}
break;
- case EEVEE_MESH_GEOM_MOTION_DATA:
+ case EEVEE_MOTION_DATA_MESH:
for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
GPU_VERTBUF_DISCARD_SAFE(geom_mb->vbo[i]);
}
@@ -64,7 +70,7 @@ static uint eevee_object_key_hash(const void *key)
EEVEE_ObjectKey *ob_key = (EEVEE_ObjectKey *)key;
uint hash = BLI_ghashutil_ptrhash(ob_key->ob);
hash = BLI_ghashutil_combine_hash(hash, BLI_ghashutil_ptrhash(ob_key->parent));
- for (int i = 0; i < 16; i++) {
+ for (int i = 0; i < MAX_DUPLI_RECUR; i++) {
if (ob_key->id[i] != 0) {
hash = BLI_ghashutil_combine_hash(hash, BLI_ghashutil_inthash(ob_key->id[i]));
}
@@ -148,18 +154,40 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *
return ob_step;
}
-static EEVEE_GeometryMotionData *motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb,
- void *key,
- bool hair)
+static void *motion_blur_deform_data_get(EEVEE_MotionBlurData *mb, Object *ob, bool hair)
{
if (mb->geom == NULL) {
return NULL;
}
+ DupliObject *dup = DRW_object_get_dupli(ob);
+ void *key;
+ if (dup) {
+ key = dup->ob;
+ }
+ else {
+ key = ob;
+ }
+ /* Only use data for object that have no modifiers. */
+ if (!BKE_object_is_modified(DRW_context_state_get()->scene, ob)) {
+ key = ob->data;
+ }
key = (char *)key + (int)hair;
EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, key);
if (geom_step == NULL) {
- geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
- geom_step->type = hair ? EEVEE_HAIR_GEOM_MOTION_DATA : EEVEE_MESH_GEOM_MOTION_DATA;
+ if (hair) {
+ EEVEE_HairMotionData *hair_step;
+ /* Ugly, we allocate for each modifiers and just fill based on modifier index in the list. */
+ int psys_len = (ob->type != OB_HAIR) ? BLI_listbase_count(&ob->modifiers) : 1;
+ hair_step = MEM_callocN(sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]) * psys_len,
+ __func__);
+ hair_step->psys_len = psys_len;
+ geom_step = (EEVEE_GeometryMotionData *)hair_step;
+ geom_step->type = EEVEE_MOTION_DATA_HAIR;
+ }
+ else {
+ geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
+ geom_step->type = EEVEE_MOTION_DATA_MESH;
+ }
BLI_ghash_insert(mb->geom, key, geom_step);
}
return geom_step;
@@ -167,25 +195,12 @@ static EEVEE_GeometryMotionData *motion_blur_geometry_data_get(EEVEE_MotionBlurD
EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, Object *ob)
{
- /* Use original data as key to ensure matching accross update. */
- return motion_blur_geometry_data_get(mb, DEG_get_original_object(ob)->data, false);
+ return motion_blur_deform_data_get(mb, ob, false);
}
-EEVEE_GeometryMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb,
- Object *ob,
- ModifierData *md)
+EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb, Object *ob)
{
- void *key;
- if (md) {
- /* Particle system. */
- key = BKE_modifier_get_original(md);
- }
- else {
- /* Hair object. */
- key = DEG_get_original_object(ob)->data;
- }
-
- return motion_blur_geometry_data_get(mb, key, true);
+ return motion_blur_deform_data_get(mb, ob, true);
}
/* View Layer data. */
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 365ba0afaac..4a03ef69d45 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -147,6 +147,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
if (!stl->effects) {
stl->effects = MEM_callocN(sizeof(EEVEE_EffectsInfo), "EEVEE_EffectsInfo");
+ stl->effects->taa_render_sample = 1;
}
effects = stl->effects;
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index 2a315927015..fa517e2d5c9 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -289,8 +289,14 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
/* Store transform */
DRW_hair_duplimat_get(ob, psys, md, mb_data->obmat[mb_step]);
- EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_hair_data_get(
- &effects->motion_blur, ob, md);
+ EEVEE_HairMotionData *mb_hair = EEVEE_motion_blur_hair_data_get(&effects->motion_blur, ob);
+ int psys_id = (md != NULL) ? BLI_findindex(&ob->modifiers, md) : 0;
+
+ if (psys_id >= mb_hair->psys_len) {
+ /* This should never happen. It means the modifier list was changed by frame evaluation. */
+ BLI_assert(0);
+ return;
+ }
if (mb_step == MB_CURR) {
/* Fill missing matrices if the object was hidden in previous or next frame. */
@@ -301,18 +307,21 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]);
}
+ GPUTexture *tex_prev = mb_hair->psys[psys_id].hair_pos_tx[MB_PREV];
+ GPUTexture *tex_next = mb_hair->psys[psys_id].hair_pos_tx[MB_NEXT];
+
grp = DRW_shgroup_hair_create_sub(ob, psys, md, effects->motion_blur.hair_grp);
DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]);
DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]);
DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]);
- DRW_shgroup_uniform_texture(grp, "prvBuffer", mb_geom->hair_pos_tx[MB_PREV]);
- DRW_shgroup_uniform_texture(grp, "nxtBuffer", mb_geom->hair_pos_tx[MB_NEXT]);
- DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1);
+ DRW_shgroup_uniform_texture(grp, "prvBuffer", tex_prev);
+ DRW_shgroup_uniform_texture(grp, "nxtBuffer", tex_next);
+ DRW_shgroup_uniform_bool(grp, "useDeform", &mb_hair->use_deform, 1);
}
else {
/* Store vertex position buffer. */
- mb_geom->hair_pos[mb_step] = DRW_hair_pos_buffer_get(ob, psys, md);
- mb_geom->use_deform = true;
+ mb_hair->psys[psys_id].hair_pos[mb_step] = DRW_hair_pos_buffer_get(ob, psys, md);
+ mb_hair->use_deform = true;
}
}
}
@@ -339,7 +348,8 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
const bool is_dupli = (ob->base_flag & BASE_FROM_DUPLI) != 0;
const bool object_moves = is_dupli || has_rigidbody || BKE_object_moves_in_time(ob, true);
#else
- /* BKE_object_moves_in_time does not work in some cases. Better */
+ /* BKE_object_moves_in_time does not work in some cases.
+ * Better detect non moving object after evaluation. */
const bool object_moves = true;
#endif
const bool is_deform = BKE_object_is_deform_modified(DRW_context_state_get()->scene, ob) ||
@@ -375,17 +385,6 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
}
if (mb_geom->use_deform) {
- EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
- if (!oedata->geom_update) {
- /* FIXME(fclem) There can be false positive where the actual mesh is not updated.
- * This avoids a crash but removes the motion blur from some object.
- * Maybe an issue with depsgraph tagging. */
- mb_geom->use_deform = false;
- oedata->geom_update = false;
-
- GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]);
- GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]);
- }
/* Keep to modify later (after init). */
mb_geom->batch = batch;
}
@@ -445,29 +444,36 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
BLI_ghashIterator_done(&ghi) == false;
BLI_ghashIterator_step(&ghi)) {
EEVEE_GeometryMotionData *mb_geom = BLI_ghashIterator_getValue(&ghi);
+ EEVEE_HairMotionData *mb_hair = (EEVEE_HairMotionData *)mb_geom;
if (!mb_geom->use_deform) {
continue;
}
switch (mb_geom->type) {
- case EEVEE_HAIR_GEOM_MOTION_DATA:
+ case EEVEE_MOTION_DATA_HAIR:
if (mb_step == MB_CURR) {
/* TODO(fclem) Check if vertex count mismatch. */
- mb_geom->use_deform = true;
+ mb_hair->use_deform = true;
}
else {
- mb_geom->hair_pos[mb_step] = GPU_vertbuf_duplicate(mb_geom->hair_pos[mb_step]);
+ for (int i = 0; i < mb_hair->psys_len; i++) {
+ if (mb_hair->psys[i].hair_pos[mb_step] == NULL) {
+ continue;
+ }
+ mb_hair->psys[i].hair_pos[mb_step] = GPU_vertbuf_duplicate(
+ mb_hair->psys[i].hair_pos[mb_step]);
- /* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(mb_geom->hair_pos[mb_step]);
+ /* Create vbo immediately to bind to texture buffer. */
+ GPU_vertbuf_use(mb_hair->psys[i].hair_pos[mb_step]);
- mb_geom->hair_pos_tx[mb_step] = GPU_texture_create_from_vertbuf(
- mb_geom->hair_pos[mb_step]);
+ mb_hair->psys[i].hair_pos_tx[mb_step] = GPU_texture_create_from_vertbuf(
+ mb_hair->psys[i].hair_pos[mb_step]);
+ }
}
break;
- case EEVEE_MESH_GEOM_MOTION_DATA:
+ case EEVEE_MOTION_DATA_MESH:
if (mb_step == MB_CURR) {
/* Modify batch to have data from adjacent frames. */
GPUBatch *batch = mb_geom->batch;
@@ -485,15 +491,7 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
break;
}
- /* Modify the batch to include the previous & next position. */
- if (i == MB_PREV) {
- GPU_batch_vertbuf_add_ex(batch, vbo, true);
- mb_geom->vbo[i] = NULL;
- }
- else {
- /* This VBO can be reuse by next time step. Don't pass ownership. */
- GPU_batch_vertbuf_add_ex(batch, vbo, false);
- }
+ GPU_batch_vertbuf_add_ex(batch, vbo, false);
}
}
}
@@ -548,16 +546,28 @@ void EEVEE_motion_blur_swap_data(EEVEE_Data *vedata)
BLI_ghashIterator_done(&ghi) == false;
BLI_ghashIterator_step(&ghi)) {
EEVEE_GeometryMotionData *mb_geom = BLI_ghashIterator_getValue(&ghi);
+ EEVEE_HairMotionData *mb_hair = (EEVEE_HairMotionData *)mb_geom;
switch (mb_geom->type) {
- case EEVEE_HAIR_GEOM_MOTION_DATA:
- GPU_VERTBUF_DISCARD_SAFE(mb_geom->hair_pos[MB_PREV]);
- DRW_TEXTURE_FREE_SAFE(mb_geom->hair_pos_tx[MB_PREV]);
- mb_geom->hair_pos[MB_PREV] = mb_geom->hair_pos[MB_NEXT];
- mb_geom->hair_pos_tx[MB_PREV] = mb_geom->hair_pos_tx[MB_NEXT];
+ case EEVEE_MOTION_DATA_HAIR:
+ for (int i = 0; i < mb_hair->psys_len; i++) {
+ GPU_VERTBUF_DISCARD_SAFE(mb_hair->psys[i].hair_pos[MB_PREV]);
+ DRW_TEXTURE_FREE_SAFE(mb_hair->psys[i].hair_pos_tx[MB_PREV]);
+ mb_hair->psys[i].hair_pos[MB_PREV] = mb_hair->psys[i].hair_pos[MB_NEXT];
+ mb_hair->psys[i].hair_pos_tx[MB_PREV] = mb_hair->psys[i].hair_pos_tx[MB_NEXT];
+ }
break;
- case EEVEE_MESH_GEOM_MOTION_DATA:
+ case EEVEE_MOTION_DATA_MESH:
+ if (mb_geom->batch != NULL) {
+ for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN; i++) {
+ if (mb_geom->batch->verts[i] == mb_geom->vbo[MB_PREV] ||
+ mb_geom->batch->verts[i] == mb_geom->vbo[MB_NEXT]) {
+ /* Avoid double reference of the VBOs. */
+ mb_geom->batch->verts[i] = NULL;
+ }
+ }
+ }
GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]);
mb_geom->vbo[MB_PREV] = mb_geom->vbo[MB_NEXT];
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 34cd22ad13c..1e2de521cdf 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -595,25 +595,30 @@ typedef struct EEVEE_ObjectMotionData {
} EEVEE_ObjectMotionData;
typedef enum eEEVEEMotionData {
- EEVEE_MESH_GEOM_MOTION_DATA = 0,
- EEVEE_HAIR_GEOM_MOTION_DATA,
+ EEVEE_MOTION_DATA_MESH = 0,
+ EEVEE_MOTION_DATA_HAIR,
} eEEVEEMotionData;
+typedef struct EEVEE_HairMotionData {
+ /** Needs to be first to ensure casting. */
+ eEEVEEMotionData type;
+ int use_deform;
+ /** Allocator will alloc enough slot for all particle systems. Or 1 if it's a hair object. */
+ int psys_len;
+ struct {
+ struct GPUVertBuf *hair_pos[2]; /* Position buffer for time = t +/- step. */
+ struct GPUTexture *hair_pos_tx[2]; /* Buffer Texture of the corresponding VBO. */
+ } psys[0];
+} EEVEE_HairMotionData;
+
typedef struct EEVEE_GeometryMotionData {
+ /** Needs to be first to ensure casting. */
eEEVEEMotionData type;
- int use_deform; /* To disable deform mb if vertcount mismatch. */
- union {
- struct {
- /* Mesh */
- struct GPUBatch *batch; /* Batch for time = t. */
- struct GPUVertBuf *vbo[2]; /* Vbo for time = t +/- step. */
- };
- struct {
- /* Hair */
- struct GPUVertBuf *hair_pos[2]; /* Position buffer for time = t +/- step. */
- struct GPUTexture *hair_pos_tx[2]; /* Buffer Texture of the corresponding VBO. */
- };
- };
+ /** To disable deform mb if vertcount mismatch. */
+ int use_deform;
+
+ struct GPUBatch *batch; /* Batch for time = t. */
+ struct GPUVertBuf *vbo[2]; /* Vbo for time = t +/- step. */
} EEVEE_GeometryMotionData;
/* ************ EFFECTS DATA ************* */
@@ -914,6 +919,9 @@ typedef struct EEVEE_PrivateData {
float camtexcofac[4];
float size_orig[2];
+ /* Cached original camera when rendering for motion blur (see T79637). */
+ struct Object *cam_original_ob;
+
/* Mist Settings */
float mist_start, mist_inv_dist, mist_falloff;
@@ -971,9 +979,7 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *
bool hair);
EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb,
Object *ob);
-EEVEE_GeometryMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb,
- Object *ob,
- struct ModifierData *md);
+EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb, Object *ob);
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob);
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob);
EEVEE_LightEngineData *EEVEE_light_data_get(Object *ob);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 62698bc5da3..21a4013e309 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -126,6 +126,9 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
GPU_framebuffer_ensure_config(&fbl->main_color_fb,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->color)});
+ /* Camera could change because of Motion blur. */
+ g_data->cam_original_ob = RE_GetCamera(engine->re);
+
return true;
}
@@ -135,9 +138,10 @@ void EEVEE_render_modules_init(EEVEE_Data *vedata,
{
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *g_data = vedata->stl->g_data;
EEVEE_FramebufferList *fbl = vedata->fbl;
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
- struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+ struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, g_data->cam_original_ob);
EEVEE_render_view_sync(vedata, engine, depsgraph);
/* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`.
@@ -156,7 +160,7 @@ void EEVEE_render_view_sync(EEVEE_Data *vedata, RenderEngine *engine, struct Dep
/* Set the pers & view matrix. */
float winmat[4][4], viewmat[4][4], viewinv[4][4];
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
- struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+ struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, g_data->cam_original_ob);
RE_GetCameraWindow(engine->re, ob_camera_eval, winmat);
RE_GetCameraWindowWithOverscan(engine->re, g_data->overscan, winmat);
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 12b50030435..5976a9505e8 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -212,7 +212,9 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
* Reset for each "redraw". When rendering using ogl render,
* we accumulate the redraw inside the drawing loop in eevee_draw_scene().
**/
- effects->taa_render_sample = 1;
+ if (DRW_state_is_opengl_render()) {
+ effects->taa_render_sample = 1;
+ }
effects->bypass_drawing = false;
EEVEE_temporal_sampling_create_view(vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index e1e65c29b4f..f8c7a6e16db 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -62,6 +62,7 @@ static struct {
GPUTexture *dummy_density;
GPUTexture *dummy_color;
GPUTexture *dummy_flame;
+ GPUTexture *dummy_missing;
GPUTexture *dummy_scatter;
GPUTexture *dummy_transmit;
@@ -141,6 +142,9 @@ static void eevee_create_shader_volumes(void)
const float flame = 0.0f;
e_data.dummy_flame = DRW_texture_create_3d(1, 1, 1, GPU_R8, DRW_TEX_WRAP, &flame);
+
+ const float missing[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ e_data.dummy_missing = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, missing);
}
void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
@@ -355,7 +359,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) {
- DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
+ DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_missing);
}
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -443,7 +447,7 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS
NULL;
DRW_shgroup_uniform_texture(
- grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_density);
+ grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_missing);
if (drw_grid && multiple_transforms) {
/* Specify per-volume transform matrix that is applied after the
@@ -830,6 +834,7 @@ void EEVEE_volumes_free(void)
DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_color);
+ DRW_TEXTURE_FREE_SAFE(e_data.dummy_missing);
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
DRW_SHADER_FREE_SAFE(e_data.scatter_sh);
diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
index ebc8a2f97ef..728b3d510fa 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
@@ -75,8 +75,6 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 ||
pd->edit_mesh.do_zbufclip;
- pd->edit_mesh.ghost_ob = 0;
- pd->edit_mesh.edit_ob = 0;
pd->edit_mesh.do_faces = true;
pd->edit_mesh.do_edges = true;
@@ -312,9 +310,6 @@ void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob)
overlay_edit_mesh_add_ob_to_pass(pd, ob, do_in_front);
}
- pd->edit_mesh.ghost_ob += (ob->dtx & OB_DRAW_IN_FRONT) ? 1 : 0;
- pd->edit_mesh.edit_ob += 1;
-
if (DRW_state_show_text() && (pd->edit_mesh.flag & OVERLAY_EDIT_TEXT)) {
const DRWContextState *draw_ctx = DRW_context_state_get();
DRW_text_edit_mesh_measure_stats(draw_ctx->region, draw_ctx->v3d, ob, &draw_ctx->scene->unit);
@@ -375,18 +370,11 @@ void OVERLAY_edit_mesh_draw(OVERLAY_Data *vedata)
DRW_draw_pass(psl->edit_mesh_verts_ps[NOT_IN_FRONT]);
}
else {
- const DRWContextState *draw_ctx = DRW_context_state_get();
- View3D *v3d = draw_ctx->v3d;
-
DRW_draw_pass(psl->edit_mesh_normals_ps);
overlay_edit_mesh_draw_components(psl, pd, false);
- if (!DRW_state_is_depth() && v3d->shading.type == OB_SOLID && pd->edit_mesh.ghost_ob == 1 &&
- pd->edit_mesh.edit_ob == 1) {
- /* In the case of single ghost object edit (common case for retopology):
- * we clear the depth buffer so that only the depth of the retopo mesh
- * is occluding the edit cage. */
- GPU_framebuffer_clear_depth(fbl->overlay_default_fb, 1.0f);
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(fbl->overlay_in_front_fb);
}
if (!DRW_pass_is_empty(psl->edit_mesh_depth_ps[IN_FRONT])) {
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 5e5aba713f0..5cf8cb12aa0 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -309,8 +309,6 @@ typedef struct OVERLAY_PrivateData {
float overlay_color[4];
} edit_text;
struct {
- int ghost_ob;
- int edit_ob;
bool do_zbufclip;
bool do_faces;
bool do_edges;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 8c2f4216aa9..66d4882cf9d 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -3025,8 +3025,11 @@ bool ED_autokeyframe_property(
bool special;
bool changed = false;
+ /* for entire array buttons we check the first component, it's not perfect
+ * but works well enough in typical cases */
+ const int rnaindex_check = (rnaindex == -1) ? 0 : rnaindex;
fcu = BKE_fcurve_find_by_rna_context_ui(
- C, ptr, prop, rnaindex, NULL, &action, &driven, &special);
+ C, ptr, prop, rnaindex_check, NULL, &action, &driven, &special);
if (fcu == NULL) {
return changed;
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 04e3a0dd5b6..e636e755430 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -594,35 +594,9 @@ static int gpencil_stroke_merge_material_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- bool changed = BKE_gpencil_merge_materials_table_get(
- ob, hue_threshold, sat_threshold, val_threshold, mat_table);
-
- int removed = BLI_ghash_len(mat_table);
-
- /* Update stroke material index. */
- if (changed) {
- CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
- continue;
- }
-
- if (BLI_ghash_haskey(mat_table, POINTER_FROM_INT(gps->mat_nr))) {
- int *idx = BLI_ghash_lookup(mat_table, POINTER_FROM_INT(gps->mat_nr));
- gps->mat_nr = POINTER_AS_INT(idx);
- }
- }
- }
- }
- CTX_DATA_END;
- }
-
- /* Free hash memory. */
- BLI_ghash_free(mat_table, NULL, NULL);
+ int removed;
+ bool changed = BKE_gpencil_merge_materials(
+ ob, hue_threshold, sat_threshold, val_threshold, &removed);
/* notifiers */
if (changed) {
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index c02b4da3599..5d936cdfaa3 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1715,7 +1715,7 @@ struct Panel *UI_panel_add_instanced(struct ScrArea *area,
char *panel_idname,
int list_index,
struct PointerRNA *custom_data);
-void UI_panels_free_instanced(struct bContext *C, struct ARegion *region);
+void UI_panels_free_instanced(const struct bContext *C, struct ARegion *region);
#define LIST_PANEL_UNIQUE_STR_LEN 4
void UI_list_panel_unique_str(struct Panel *panel, char *r_name);
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index cc58082cb02..56df49981e0 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -312,8 +312,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
{
- const int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex;
- ED_autokeyframe_property(C, scene, &but->rnapoin, but->rnaprop, rnaindex, cfra);
+ ED_autokeyframe_property(C, scene, &but->rnapoin, but->rnaprop, but->rnaindex, cfra);
}
void ui_but_anim_copy_driver(bContext *C)
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 799a3b7fd5e..d334007a097 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -117,7 +117,9 @@ typedef struct PanelSort {
static int get_panel_real_size_y(const Panel *panel);
static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state);
static int compare_panel(const void *a1, const void *a2);
-static bool panel_type_context_poll(PanelType *panel_type, const char *context);
+static bool panel_type_context_poll(ARegion *region,
+ const PanelType *panel_type,
+ const char *context);
static void panel_title_color_get(bool show_background, uchar color[4])
{
@@ -370,7 +372,7 @@ static void panel_delete(const bContext *C, ARegion *region, ListBase *panels, P
* \note Can be called with NULL \a C, but it should be avoided because
* handlers might not be removed.
*/
-void UI_panels_free_instanced(bContext *C, ARegion *region)
+void UI_panels_free_instanced(const bContext *C, ARegion *region)
{
/* Delete panels with the instanced flag. */
LISTBASE_FOREACH_MUTABLE (Panel *, panel, &region->panels) {
@@ -460,14 +462,17 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr
return;
}
- char *context = drag_panel->type->context;
+ char *context = NULL;
+ if (!UI_panel_category_is_visible(region)) {
+ context = drag_panel->type->context;
+ }
/* Find how many instanced panels with this context string. */
int list_panels_len = 0;
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
if (panel->type) {
- if (panel_type_context_poll(panel->type, context)) {
- if (panel->type->flag & PNL_INSTANCED) {
+ if (panel->type->flag & PNL_INSTANCED) {
+ if (panel_type_context_poll(region, panel->type, context)) {
list_panels_len++;
}
}
@@ -479,8 +484,8 @@ static void reorder_instanced_panel_list(bContext *C, ARegion *region, Panel *dr
PanelSort *sort_index = panel_sort;
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
if (panel->type) {
- if (panel_type_context_poll(panel->type, context)) {
- if (panel->type->flag & PNL_INSTANCED) {
+ if (panel->type->flag & PNL_INSTANCED) {
+ if (panel_type_context_poll(region, panel->type, context)) {
sort_index->panel = MEM_dupallocN(panel);
sort_index->orig = panel;
sort_index++;
@@ -657,11 +662,18 @@ static void panels_collapse_all(const bContext *C,
set_panels_list_data_expand_flag(C, region);
}
-static bool panel_type_context_poll(PanelType *panel_type, const char *context)
+static bool panel_type_context_poll(ARegion *region,
+ const PanelType *panel_type,
+ const char *context)
{
+ if (UI_panel_category_is_visible(region)) {
+ return STREQ(panel_type->category, UI_panel_category_active_get(region, false));
+ }
+
if (panel_type->context[0] && STREQ(panel_type->context, context)) {
return true;
}
+
return false;
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 56807621358..cdfe6120eee 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -572,6 +572,15 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
if (override_id != NULL) {
BKE_main_id_clear_newpoins(bmain);
+ if (GS(override_id->name) == ID_OB) {
+ Scene *scene = CTX_data_scene(C);
+ if (!BKE_collection_has_object_recursive(scene->master_collection,
+ (Object *)override_id)) {
+ BKE_collection_object_add_from(
+ bmain, scene, (Object *)id, (Object *)override_id);
+ }
+ }
+
/* Assign new pointer, takes care of updates/notifiers */
RNA_id_pointer_create(override_id, &idptr);
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 81b8cd70353..197c1c3bdbe 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -2647,7 +2647,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
ob_gpencil = ED_gpencil_add_object(C, ob->loc, local_view_bits);
copy_v3_v3(ob_gpencil->rot, ob->rot);
copy_v3_v3(ob_gpencil->scale, ob->scale);
- BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, false, true);
+ BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, false, 1.0f, 0.0f);
gpencilConverted = true;
}
}
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 5a0656ee916..8bec200cb40 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -766,7 +766,7 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
static bool datalayout_transfer_poll(bContext *C)
{
- return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH), true) ||
+ return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH), true, false) ||
data_transfer_poll(C));
}
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index 019ab2c345b..cfa55c68a56 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -412,28 +412,30 @@ void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
/********** generic functions for operators using mod names and data context *********************/
-static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
+static bool gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
+ GpencilModifierData *mod = ptr.data; /* May be NULL. */
if (!ob || ID_IS_LINKED(ob)) {
- return 0;
+ return false;
}
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
- return 0;
+ return false;
}
if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
- return 0;
+ return false;
}
if (ID_IS_OVERRIDE_LIBRARY(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
- return (((GpencilModifierData *)ptr.data)->flag &
- eGpencilModifierFlag_OverrideLibrary_Local) != 0;
+ if ((mod == NULL) || (mod->flag & eGpencilModifierFlag_OverrideLibrary_Local) == 0) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
+ return false;
+ }
}
- return 1;
+ return true;
}
static bool gpencil_edit_modifier_poll(bContext *C)
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index bc3c263e0a3..50825ae1ae4 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -149,8 +149,8 @@ void COLLECTION_OT_objects_remove_active(struct wmOperatorType *ot);
bool edit_modifier_poll_generic(struct bContext *C,
struct StructRNA *rna_type,
int obtype_flag,
- const bool is_editmode_allowed);
-bool edit_modifier_poll(struct bContext *C);
+ const bool is_editmode_allowed,
+ const bool is_liboverride_allowed);
void edit_modifier_properties(struct wmOperatorType *ot);
bool edit_modifier_invoke_properties(struct bContext *C,
struct wmOperator *op,
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 8d6d2e3e31d..ceb6553bdf6 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -895,6 +895,8 @@ int ED_object_modifier_copy(
BLI_insertlinkafter(&ob->modifiers, md, nmd);
BKE_modifier_unique_name(&ob->modifiers, nmd);
+ nmd->flag |= eModifierFlag_OverrideLibrary_Local;
+
return 1;
}
@@ -1005,7 +1007,8 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
bool edit_modifier_poll_generic(bContext *C,
StructRNA *rna_type,
int obtype_flag,
- const bool is_editmode_allowed)
+ const bool is_editmode_allowed,
+ const bool is_liboverride_allowed)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
@@ -1021,8 +1024,8 @@ bool edit_modifier_poll_generic(bContext *C,
return false;
}
- if (ID_IS_OVERRIDE_LIBRARY(ob)) {
- if ((mod != NULL) && (mod->flag & eModifierFlag_OverrideLibrary_Local) == 0) {
+ if (ID_IS_OVERRIDE_LIBRARY(ob) && !is_liboverride_allowed) {
+ if ((mod == NULL) || (mod->flag & eModifierFlag_OverrideLibrary_Local) == 0) {
CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
return false;
}
@@ -1036,9 +1039,16 @@ bool edit_modifier_poll_generic(bContext *C,
return true;
}
-bool edit_modifier_poll(bContext *C)
+static bool edit_modifier_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_Modifier, 0, true);
+ return edit_modifier_poll_generic(C, &RNA_Modifier, 0, true, false);
+}
+
+/* Used by operators performing actions allowed also on modifiers from the overridden linked object
+ * (not only from added 'local' ones). */
+static bool edit_modifier_liboverride_allowed_poll(bContext *C)
+{
+ return edit_modifier_poll_generic(C, &RNA_Modifier, 0, true, true);
}
void edit_modifier_properties(wmOperatorType *ot)
@@ -1282,11 +1292,6 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
/** \name Move to Index Modifier Operator
* \{ */
-static bool modifier_move_to_index_poll(bContext *C)
-{
- return edit_modifier_poll(C);
-}
-
static int modifier_move_to_index_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
@@ -1321,7 +1326,7 @@ void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
ot->invoke = modifier_move_to_index_invoke;
ot->exec = modifier_move_to_index_exec;
- ot->poll = modifier_move_to_index_poll;
+ ot->poll = edit_modifier_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -1338,7 +1343,7 @@ void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
{
- if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false)) {
+ if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false, false)) {
return false;
}
@@ -1583,7 +1588,7 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot)
ot->invoke = modifier_copy_invoke;
ot->exec = modifier_copy_exec;
- ot->poll = edit_modifier_poll;
+ ot->poll = edit_modifier_liboverride_allowed_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -1598,7 +1603,7 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot)
static bool multires_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH), true);
+ return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH), true, false);
}
static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
@@ -2107,13 +2112,14 @@ static void modifier_skin_customdata_delete(Object *ob)
static bool skin_poll(bContext *C)
{
- return (edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), false));
+ return (edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), false, false));
}
static bool skin_edit_poll(bContext *C)
{
Object *ob = CTX_data_edit_object(C);
- return (ob != NULL && edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true) &&
+ return (ob != NULL &&
+ edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true, false) &&
!ID_IS_OVERRIDE_LIBRARY(ob) && !ID_IS_OVERRIDE_LIBRARY(ob->data));
}
@@ -2469,7 +2475,7 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
static bool correctivesmooth_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0, true);
+ return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0, true, false);
}
static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
@@ -2549,7 +2555,7 @@ void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
static bool meshdeform_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0, true);
+ return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0, true, false);
}
static int meshdeform_bind_exec(bContext *C, wmOperator *op)
@@ -2624,7 +2630,7 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
static bool explode_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0, true);
+ return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0, true, false);
}
static int explode_refresh_exec(bContext *C, wmOperator *op)
@@ -2676,7 +2682,7 @@ void OBJECT_OT_explode_refresh(wmOperatorType *ot)
static bool ocean_bake_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0, true);
+ return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0, true, false);
}
typedef struct OceanBakeJob {
@@ -2884,7 +2890,7 @@ void OBJECT_OT_ocean_bake(wmOperatorType *ot)
static bool laplaciandeform_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0, false);
+ return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0, false, false);
}
static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
@@ -2961,7 +2967,7 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
static bool surfacedeform_bind_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0, true);
+ return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0, true, false);
}
static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
index 977d4abd4d4..e2a30c4ce98 100644
--- a/source/blender/editors/object/object_shader_fx.c
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -332,23 +332,26 @@ static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obt
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
+ ShaderFxData *fx = ptr.data; /* May be NULL. */
if (!ob || ID_IS_LINKED(ob)) {
- return 0;
+ return false;
}
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
- return 0;
+ return false;
}
if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
- return 0;
+ return false;
}
if (ID_IS_OVERRIDE_LIBRARY(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs coming from library override");
- return (((ShaderFxData *)ptr.data)->flag & eShaderFxFlag_OverrideLibrary_Local) != 0;
+ if ((fx == NULL) || (fx->flag & eShaderFxFlag_OverrideLibrary_Local) == 0) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs coming from library override");
+ return false;
+ }
}
- return 1;
+ return true;
}
static bool edit_shaderfx_poll(bContext *C)
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 150141eed3a..af146942b2e 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2662,29 +2662,35 @@ void ED_region_panels_layout_ex(const bContext *C,
if (has_instanced_panel) {
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
if (panel->type == NULL) {
- continue; /* Some panels don't have a type.. */
+ continue; /* Some panels don't have a type. */
}
- if (panel->type->flag & PNL_INSTANCED) {
- if (panel && UI_panel_is_dragging(panel)) {
- /* Prevent View2d.tot rectangle size changes while dragging panels. */
- update_tot_size = false;
- }
-
- /* Use a unique identifier for instanced panels, otherwise an old block for a different
- * panel of the same type might be found. */
- char unique_panel_str[8];
- UI_list_panel_unique_str(panel, unique_panel_str);
- ed_panel_draw(C,
- area,
- region,
- &region->panels,
- panel->type,
- panel,
- (panel->type->flag & PNL_DRAW_BOX) ? w_box_panel : w,
- em,
- vertical,
- unique_panel_str);
+ if (!(panel->type->flag & PNL_INSTANCED)) {
+ continue;
}
+ if (use_category_tabs && panel->type->category[0] &&
+ !STREQ(category, panel->type->category)) {
+ continue;
+ }
+
+ if (panel && UI_panel_is_dragging(panel)) {
+ /* Prevent View2d.tot rectangle size changes while dragging panels. */
+ update_tot_size = false;
+ }
+
+ /* Use a unique identifier for instanced panels, otherwise an old block for a different
+ * panel of the same type might be found. */
+ char unique_panel_str[8];
+ UI_list_panel_unique_str(panel, unique_panel_str);
+ ed_panel_draw(C,
+ area,
+ region,
+ &region->panels,
+ panel->type,
+ panel,
+ (panel->type->flag & PNL_DRAW_BOX) ? w_box_panel : w,
+ em,
+ vertical,
+ unique_panel_str);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index c87189997f2..d68b1226b40 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -109,7 +109,7 @@
* For multi-resolution, the same vertex in multiple grids is counted multiple times, with
* different index for each grid. */
-void SCULPT_vertex_random_access_init(SculptSession *ss)
+void SCULPT_vertex_random_access_ensure(SculptSession *ss)
{
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
@@ -204,6 +204,27 @@ const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index)
return SCULPT_vertex_co_get(ss, index);
}
+void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3])
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ case PBVH_BMESH:
+ copy_v3_v3(r_co, SCULPT_vertex_co_get(ss, index));
+ break;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int vertex_index = index - grid_index * key->grid_area;
+
+ SubdivCCGCoord coord = {.grid_index = grid_index,
+ .x = vertex_index % key->grid_size,
+ .y = vertex_index / key->grid_size};
+ BKE_subdiv_ccg_eval_limit_point(ss->subdiv_ccg, &coord, r_co);
+ break;
+ }
+ }
+}
+
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3])
{
if (ss->persistent_base) {
@@ -1000,7 +1021,7 @@ bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3],
void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
{
int vertex_count = SCULPT_vertex_count_get(ss);
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
flood->queue = BLI_gsqueue_new(sizeof(int));
flood->visited_vertices = BLI_BITMAP_NEW(vertex_count, "visited vertices");
@@ -1921,8 +1942,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
if (use_area_cos && area_test_r) {
/* Weight the coordinates towards the center. */
float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius);
- float afactor = 3.0f * p * p - 2.0f * p * p * p;
- CLAMP(afactor, 0.0f, 1.0f);
+ const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f);
float disp[3];
sub_v3_v3v3(disp, co, area_test.location);
@@ -1935,8 +1955,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
if (use_area_nos && normal_test_r) {
/* Weight the normals towards the center. */
float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius);
- float nfactor = 3.0f * p * p - 2.0f * p * p * p;
- CLAMP(nfactor, 0.0f, 1.0f);
+ const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f);
mul_v3_fl(no, nfactor);
add_v3_v3(anctd->area_nos[flip_index], no);
@@ -1997,8 +2016,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
if (use_area_cos && area_test_r) {
/* Weight the coordinates towards the center. */
float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius);
- float afactor = 3.0f * p * p - 2.0f * p * p * p;
- CLAMP(afactor, 0.0f, 1.0f);
+ const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f);
float disp[3];
sub_v3_v3v3(disp, co, area_test.location);
@@ -2011,8 +2029,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
if (use_area_nos && normal_test_r) {
/* Weight the normals towards the center. */
float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius);
- float nfactor = 3.0f * p * p - 2.0f * p * p * p;
- CLAMP(nfactor, 0.0f, 1.0f);
+ const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f);
mul_v3_fl(no, nfactor);
add_v3_v3(anctd->area_nos[flip_index], no);
@@ -2240,6 +2257,8 @@ static float brush_strength(const Sculpt *sd,
case SCULPT_TOOL_DRAW_SHARP:
case SCULPT_TOOL_LAYER:
return alpha * flip * pressure * overlap * feather;
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ return alpha * pressure * overlap * feather;
case SCULPT_TOOL_CLOTH:
if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
/* Grab deform uses the same falloff as a regular grab brush. */
@@ -2778,8 +2797,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
return;
}
- float bstrength = data->strength;
- CLAMP(bstrength, 0.0f, 1.0f);
+ const float bstrength = clamp_f(data->strength, 0.0f, 1.0f);
SculptBrushTest test;
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
@@ -2818,14 +2836,14 @@ static void bmesh_topology_rake(
Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength)
{
Brush *brush = BKE_paint_brush(&sd->paint);
- CLAMP(bstrength, 0.0f, 1.0f);
+ const float strength = clamp_f(bstrength, 0.0f, 1.0f);
/* Interactions increase both strength and quality. */
const int iterations = 3;
int iteration;
- const int count = iterations * bstrength + 1;
- const float factor = iterations * bstrength / count;
+ const int count = iterations * strength + 1;
+ const float factor = iterations * strength / count;
for (iteration = 0; iteration <= count; iteration++) {
@@ -2871,7 +2889,7 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
else {
(*vd.mask) += fade * bstrength * (*vd.mask);
}
- CLAMP(*vd.mask, 0.0f, 1.0f);
+ *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
@@ -2913,6 +2931,73 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
}
}
+/** \name Sculpt Multires Displacement Eraser Brush
+ * \{ */
+
+static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ SculptThreadedTaskData *data = userdata;
+ SculptSession *ss = data->ob->sculpt;
+ const Brush *brush = data->brush;
+ const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f);
+
+ float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, data->brush->falloff_shape);
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+ const float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ vd.co,
+ sqrtf(test.dist),
+ vd.no,
+ vd.fno,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ float limit_co[3];
+ float disp[3];
+ SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co);
+ sub_v3_v3v3(disp, limit_co, vd.co);
+ mul_v3_v3fl(proxy[vd.i], disp, fade);
+
+ if (vd.mvert) {
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_displacement_eraser_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ Brush *brush = BKE_paint_brush(&sd->paint);
+ BKE_curvemapping_init(brush->curve);
+
+ /* Threaded loop over nodes. */
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .brush = brush,
+ .nodes = nodes,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+ BLI_task_parallel_range(0, totnode, &data, do_displacement_eraser_brush_task_cb_ex, &settings);
+}
+
+/** \} */
+
static void do_draw_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
@@ -3193,7 +3278,7 @@ void SCULPT_relax_vertex(SculptSession *ss,
}
if (avg_count > 0) {
- mul_v3_fl(smooth_pos, 1.0f / (float)avg_count);
+ mul_v3_fl(smooth_pos, 1.0f / avg_count);
}
else {
copy_v3_v3(r_final_pos, vd->co);
@@ -4335,10 +4420,10 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
}
if (vd.mask) {
const float clamp_mask = 1.0f - *vd.mask;
- CLAMP(*disp_factor, -clamp_mask, clamp_mask);
+ *disp_factor = clamp_f(*disp_factor, -clamp_mask, clamp_mask);
}
else {
- CLAMP(*disp_factor, -1.0f, 1.0f);
+ *disp_factor = clamp_f(*disp_factor, -1.0f, 1.0f);
}
float final_co[3];
@@ -5188,7 +5273,7 @@ static float sculpt_clay_thumb_get_stabilized_pressure(StrokeCache *cache)
for (int i = 0; i < SCULPT_CLAY_STABILIZER_LEN; i++) {
final_pressure += cache->clay_pressure_stabilizer[i];
}
- return final_pressure / (float)SCULPT_CLAY_STABILIZER_LEN;
+ return final_pressure / SCULPT_CLAY_STABILIZER_LEN;
}
static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
@@ -5229,7 +5314,7 @@ static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
* stroke. */
if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) {
ss->cache->clay_thumb_front_angle += 0.8f;
- CLAMP(ss->cache->clay_thumb_front_angle, 0.0f, 60.0f);
+ ss->cache->clay_thumb_front_angle = clamp_f(ss->cache->clay_thumb_front_angle, 0.0f, 60.0f);
}
if (is_zero_v3(ss->cache->grab_delta_symmetry)) {
@@ -5705,6 +5790,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
case SCULPT_TOOL_DRAW_FACE_SETS:
SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode);
break;
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ do_displacement_eraser_brush(sd, ob, nodes, totnode);
+ break;
case SCULPT_TOOL_PAINT:
SCULPT_do_paint_brush(sd, ob, nodes, totnode);
break;
@@ -5914,7 +6002,7 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- if (is_proxy_used) {
+ if (is_proxy_used && ss->deform_modifiers_active) {
/* This brushes aren't using proxies, so sculpt_combine_proxies() wouldn't propagate needed
* deformation to original base. */
@@ -6256,6 +6344,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
return "Cloth Brush";
case SCULPT_TOOL_DRAW_FACE_SETS:
return "Draw Face Sets";
+ case SCULPT_TOOL_DISPLACEMENT_ERASER:
+ return "Multires Displacement Eraser";
case SCULPT_TOOL_PAINT:
return "Paint Brush";
case SCULPT_TOOL_SMEAR:
@@ -6441,9 +6531,12 @@ static void sculpt_update_cache_invariants(
mul_m3_v3(mat, viewDir);
normalize_v3_v3(cache->true_view_normal, viewDir);
- cache->supports_gravity =
- (!ELEM(brush->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY) &&
- (sd->gravity_factor > 0.0f));
+ cache->supports_gravity = (!ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_MASK,
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_SIMPLIFY,
+ SCULPT_TOOL_DISPLACEMENT_ERASER) &&
+ (sd->gravity_factor > 0.0f));
/* Get gravity vector in world space. */
if (cache->supports_gravity) {
if (sd->gravity_object) {
@@ -7466,7 +7559,7 @@ static void sculpt_stroke_update_step(bContext *C,
else {
BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
(ss->cache->radius / ss->cache->dyntopo_pixel_radius) *
- (float)(sd->detail_size * U.pixelsize) / 0.4f);
+ (sd->detail_size * U.pixelsize) / 0.4f);
}
if (SCULPT_stroke_is_dynamic_topology(ss, brush)) {
@@ -7701,7 +7794,7 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
SculptSession *ss = ob->sculpt;
if (ss) {
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
MEM_SAFE_FREE(ss->persistent_base);
@@ -8931,7 +9024,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
return OPERATOR_CANCELLED;
}
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
/* Tools that are not brushes do not have the brush gizmo to update the vertex as the mouse move,
* so it needs to be updated here. */
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
index c475259623a..eef090f484e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -338,23 +338,23 @@ void SCULPT_automasking_init(Sculpt *sd, Object *ob)
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
SCULPT_topology_automasking_init(sd, ob, ss->cache->automask_factor);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
sculpt_face_sets_automasking_init(sd, ob, ss->cache->automask_factor);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_automasking_init(ob,
AUTOMASK_INIT_BOUNDARY_EDGES,
brush->automasking_boundary_edges_propagation_steps,
ss->cache->automask_factor);
}
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_automasking_init(ob,
AUTOMASK_INIT_BOUNDARY_FACE_SETS,
brush->automasking_boundary_edges_propagation_steps,
diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c
index a368214cb0b..c86e922a347 100644
--- a/source/blender/editors/sculpt_paint/sculpt_boundary.c
+++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c
@@ -428,7 +428,7 @@ SculptBoundary *SCULPT_boundary_data_init(Object *object,
{
SculptSession *ss = object->sculpt;
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_info_ensure(object);
const int boundary_initial_vertex = sculpt_boundary_get_closest_boundary_vertex(
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 7d318760476..2637cb45906 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -1137,7 +1137,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
float len = event->prevclickx - event->mval[0];
filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
@@ -1185,7 +1185,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
mouse[1] = event->mval[1];
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
/* Needs mask data to be available as it is used when solving the constraints. */
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
@@ -1232,7 +1232,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
void SCULPT_OT_cloth_filter(struct wmOperatorType *ot)
{
/* Identifiers. */
- ot->name = "Filter cloth";
+ ot->name = "Filter Cloth";
ot->idname = "SCULPT_OT_cloth_filter";
ot->description = "Applies a cloth simulation deformation to the entire mesh";
diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c
index e08f477c981..69c92f2baeb 100644
--- a/source/blender/editors/sculpt_paint/sculpt_detail.c
+++ b/source/blender/editors/sculpt_paint/sculpt_detail.c
@@ -176,7 +176,7 @@ static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my)
SculptSession *ss = ob->sculpt;
SculptCursorGeometryInfo sgi;
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
/* Update the active vertex. */
const float mouse[2] = {mx, my};
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index a8de3be3baf..2afa3556dd9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -1082,7 +1082,7 @@ static void sculpt_face_set_apply_edit(Object *ob,
MEM_SAFE_FREE(prev_face_sets);
}
-static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
@@ -1096,8 +1096,21 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven
return OPERATOR_CANCELLED;
}
+ /* Ignore other events to avoid repeated operations. */
+ if (event->val != KM_PRESS) {
+ return OPERATOR_CANCELLED;
+ }
+
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
+ /* Update the current active Face Set and Vertex as the operator can be used directly from the
+ * tool without brush cursor. */
+ SculptCursorGeometryInfo sgi;
+ float mouse[2];
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index 912dfd808b0..576536cac03 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -127,7 +127,7 @@ static void color_filter_task_cb(void *__restrict userdata,
float fill_color_rgba[4];
copy_v3_v3(fill_color_rgba, data->filter_fill_color);
fill_color_rgba[3] = 1.0f;
- CLAMP(fade, 0.0f, 1.0f);
+ fade = clamp_f(fade, 0.0f, 1.0f);
mul_v4_fl(fill_color_rgba, fade);
blend_color_mix_float(final_color, orig_data.col, fill_color_rgba);
break;
@@ -140,33 +140,28 @@ static void color_filter_task_cb(void *__restrict userdata,
break;
case COLOR_FILTER_SATURATION:
rgb_to_hsv_v(orig_color, hsv_color);
- hsv_color[1] = hsv_color[1] + fade;
- CLAMP(hsv_color[1], 0.0f, 1.0f);
+ hsv_color[1] = clamp_f(hsv_color[1] + fade, 0.0f, 1.0f);
hsv_to_rgb_v(hsv_color, final_color);
break;
case COLOR_FILTER_VALUE:
rgb_to_hsv_v(orig_color, hsv_color);
- hsv_color[2] = hsv_color[2] + fade;
- CLAMP(hsv_color[2], 0.0f, 1.0f);
+ hsv_color[2] = clamp_f(hsv_color[2] + fade, 0.0f, 1.0f);
hsv_to_rgb_v(hsv_color, final_color);
break;
case COLOR_FILTER_RED:
- orig_color[0] = orig_color[0] + fade;
- CLAMP(orig_color[0], 0.0f, 1.0f);
+ orig_color[0] = clamp_f(orig_color[0] + fade, 0.0f, 1.0f);
copy_v3_v3(final_color, orig_color);
break;
case COLOR_FILTER_GREEN:
- orig_color[1] = orig_color[1] + fade;
- CLAMP(orig_color[1], 0.0f, 1.0f);
+ orig_color[1] = clamp_f(orig_color[1] + fade, 0.0f, 1.0f);
copy_v3_v3(final_color, orig_color);
break;
case COLOR_FILTER_BLUE:
- orig_color[2] = orig_color[2] + fade;
- CLAMP(orig_color[2], 0.0f, 1.0f);
+ orig_color[2] = clamp_f(orig_color[2] + fade, 0.0f, 1.0f);
copy_v3_v3(final_color, orig_color);
break;
case COLOR_FILTER_BRIGHTNESS:
- CLAMP(fade, -1.0f, 1.0f);
+ fade = clamp_f(fade, -1.0f, 1.0f);
brightness = fade;
contrast = 0;
delta = contrast / 2.0f;
@@ -174,12 +169,11 @@ static void color_filter_task_cb(void *__restrict userdata,
delta *= -1;
offset = gain * (brightness + delta);
for (int i = 0; i < 3; i++) {
- final_color[i] = gain * orig_color[i] + offset;
- CLAMP(final_color[i], 0.0f, 1.0f);
+ final_color[i] = clamp_f(gain * orig_color[i] + offset, 0.0f, 1.0f);
}
break;
case COLOR_FILTER_CONTRAST:
- CLAMP(fade, -1.0f, 1.0f);
+ fade = clamp_f(fade, -1.0f, 1.0f);
brightness = 0;
contrast = fade;
delta = contrast / 2.0f;
@@ -193,12 +187,11 @@ static void color_filter_task_cb(void *__restrict userdata,
offset = gain * (brightness + delta);
}
for (int i = 0; i < 3; i++) {
- final_color[i] = gain * orig_color[i] + offset;
- CLAMP(final_color[i], 0.0f, 1.0f);
+ final_color[i] = clamp_f(gain * orig_color[i] + offset, 0.0f, 1.0f);
}
break;
case COLOR_FILTER_SMOOTH: {
- CLAMP(fade, -1.0f, 1.0f);
+ fade = clamp_f(fade, -1.0f, 1.0f);
float smooth_color[4];
SCULPT_neighbor_color_average(ss, smooth_color, vd.index);
blend_color_interpolate_float(final_color, vd.col, smooth_color, fade);
@@ -305,7 +298,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
void SCULPT_OT_color_filter(struct wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Filter color";
+ ot->name = "Filter Color";
ot->idname = "SCULPT_OT_color_filter";
ot->description = "Applies a filter to modify the current sculpt vertex colors";
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
index 83145f5600f..e764df78c88 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
@@ -175,7 +175,7 @@ static void mask_filter_task_cb(void *__restrict userdata,
*vd.mask = gain * (*vd.mask) + offset;
break;
}
- CLAMP(*vd.mask, 0.0f, 1.0f);
+ *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f);
if (*vd.mask != prev_val) {
update = true;
}
@@ -204,7 +204,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
if (!ob->sculpt->pmap) {
return OPERATOR_CANCELLED;
@@ -434,7 +434,7 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op)
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
if (!ob->sculpt->pmap) {
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index ebf511c7fd3..f9ae91fce7f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -261,7 +261,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
switch (filter_type) {
case MESH_FILTER_SMOOTH:
- CLAMP(fade, -1.0f, 1.0f);
+ fade = clamp_f(fade, -1.0f, 1.0f);
SCULPT_neighbor_coords_average_interior(ss, avg, vd.index);
sub_v3_v3v3(val, avg, orig_co);
madd_v3_v3v3fl(val, orig_co, val, fade);
@@ -306,7 +306,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
const uint *hash_co = (const uint *)orig_co;
const uint hash = BLI_hash_int_2d(hash_co[0], hash_co[1]) ^
BLI_hash_int_2d(hash_co[2], ss->filter_cache->random_seed);
- mul_v3_fl(normal, hash * (1.0f / (float)0xFFFFFFFF) - 0.5f);
+ mul_v3_fl(normal, hash * (1.0f / 0xFFFFFFFF) - 0.5f);
mul_v3_v3fl(disp, normal, fade);
break;
}
@@ -435,9 +435,8 @@ static void mesh_filter_sharpen_init_factors(SculptSession *ss)
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (total > 0) {
- mul_v3_v3fl(
- ss->filter_cache->sharpen_detail_directions[i], direction_avg, 1.0f / (float)total);
- ss->filter_cache->sharpen_factor[i] = sharpen_avg / (float)total;
+ mul_v3_v3fl(ss->filter_cache->sharpen_detail_directions[i], direction_avg, 1.0f / total);
+ ss->filter_cache->sharpen_factor[i] = sharpen_avg / total;
}
}
}
@@ -500,7 +499,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
float len = event->prevclickx - event->mval[0];
filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false);
@@ -566,7 +565,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets);
BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_topology_info, false, false);
@@ -628,7 +627,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
{
/* Identifiers. */
- ot->name = "Filter mesh";
+ ot->name = "Filter Mesh";
ot->idname = "SCULPT_OT_mesh_filter";
ot->description = "Applies a filter to modify the current mesh";
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 79b1a5bde7b..b11a7005fb5 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -89,7 +89,7 @@ float SCULPT_raycast_init(struct ViewContext *vc,
bool original);
/* Sculpt PBVH abstraction API */
-void SCULPT_vertex_random_access_init(struct SculptSession *ss);
+void SCULPT_vertex_random_access_ensure(struct SculptSession *ss);
int SCULPT_vertex_count_get(struct SculptSession *ss);
const float *SCULPT_vertex_co_get(struct SculptSession *ss, int index);
@@ -100,6 +100,10 @@ const float *SCULPT_vertex_color_get(SculptSession *ss, int index);
const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index);
void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3]);
+/* Returs the info of the limit surface when Multires is available, otherwise it returns the
+ * current coordinate of the vertex. */
+void SCULPT_vertex_limit_surface_get(SculptSession *ss, int index, float r_co[3]);
+
#define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
typedef struct SculptVertexNeighborIter {
/* Storage */
diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
index aaa61ee9ed3..0ae9baf7e2e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
@@ -357,7 +357,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
op->customdata = MEM_mallocN(sizeof(float[2]), "initial mouse position");
copy_v2_v2(op->customdata, mouse);
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
index ed33542967b..000b7afdf55 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
@@ -327,7 +327,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
if (swptd.tot_samples > 0 && is_finite_v4(swptd.color)) {
copy_v4_v4(wet_color, swptd.color);
- mul_v4_fl(wet_color, 1.0f / (float)swptd.tot_samples);
+ mul_v4_fl(wet_color, 1.0f / swptd.tot_samples);
CLAMP4(wet_color, 0.0f, 1.0f);
if (ss->cache->first_time) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index 8a288877d43..4d41d069155 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -549,7 +549,7 @@ void SCULPT_pose_calc_pose_data(Sculpt *sd,
float *r_pose_origin,
float *r_pose_factor)
{
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
/* Calculate the pose rotation point based on the boundaries of the brush factor. */
SculptFloodFill flood;
diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c
index 9a64830cc20..2b93298ac4a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_smooth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c
@@ -150,7 +150,7 @@ void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int inde
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (total > 0) {
- mul_v3_v3fl(result, avg, 1.0f / (float)total);
+ mul_v3_v3fl(result, avg, 1.0f / total);
}
else {
copy_v3_v3(result, SCULPT_vertex_co_get(ss, index));
@@ -170,7 +170,7 @@ float SCULPT_neighbor_mask_average(SculptSession *ss, int index)
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (total > 0) {
- return avg / (float)total;
+ return avg / total;
}
return SCULPT_vertex_mask_get(ss, index);
}
@@ -188,7 +188,7 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (total > 0) {
- mul_v4_v4fl(result, avg, 1.0f / (float)total);
+ mul_v4_v4fl(result, avg, 1.0f / total);
}
else {
copy_v4_v4(result, SCULPT_vertex_color_get(ss, index));
@@ -276,7 +276,7 @@ void SCULPT_smooth(Sculpt *sd,
return;
}
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
SCULPT_boundary_info_ensure(ob);
for (iteration = 0; iteration <= count; iteration++) {
@@ -343,7 +343,7 @@ void SCULPT_surface_smooth_displace_step(SculptSession *ss,
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
if (total > 0) {
- mul_v3_v3fl(b_current_vertex, b_avg, (1.0f - beta) / (float)total);
+ mul_v3_v3fl(b_current_vertex, b_avg, (1.0f - beta) / total);
madd_v3_v3fl(b_current_vertex, laplacian_disp[v_index], beta);
mul_v3_fl(b_current_vertex, clamp_f(fade, 0.0f, 1.0f));
sub_v3_v3(co, b_current_vertex);
diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c
index f616817c330..4c54a0465b9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_transform.c
+++ b/source/blender/editors/sculpt_paint/sculpt_transform.c
@@ -75,7 +75,7 @@ void ED_sculpt_init_transform(struct bContext *C)
ss->pivot_rot[3] = 1.0f;
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
SCULPT_filter_cache_init(ob, sd, SCULPT_UNDO_COORDS);
}
@@ -126,7 +126,7 @@ void ED_sculpt_update_modal_transform(struct bContext *C)
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
- SCULPT_vertex_random_access_init(ss);
+ SCULPT_vertex_random_access_ensure(ss);
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
SculptThreadedTaskData data = {
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index dd422f2443a..f6485fdef5d 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -190,6 +190,9 @@ typedef struct PChart {
LinearSolver *context;
float *abf_alpha;
PVert *pin1, *pin2;
+ PVert *single_pin;
+ float single_pin_area;
+ float single_pin_uv[2];
} lscm;
struct PChartPack {
float rescale, area;
@@ -467,6 +470,17 @@ static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2])
}
}
+static float p_chart_uv_area(PChart *chart)
+{
+ float area = 0.0f;
+
+ for (PFace *f = chart->faces; f; f = f->nextlink) {
+ area += fabsf(p_face_uv_area_signed(f));
+ }
+
+ return area;
+}
+
static void p_chart_uv_scale(PChart *chart, float scale)
{
PVert *v;
@@ -3176,7 +3190,7 @@ static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
}
}
- if ((live && (!select || !deselect)) || (npins == 1)) {
+ if ((live && (!select || !deselect))) {
chart->u.lscm.context = NULL;
}
else {
@@ -3185,6 +3199,16 @@ static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
p_chart_topological_sanity_check(chart);
#endif
+ if (npins == 1) {
+ chart->u.lscm.single_pin_area = p_chart_uv_area(chart);
+ for (v = chart->verts; v; v = v->nextlink) {
+ if (v->flag & PVERT_PIN) {
+ chart->u.lscm.single_pin = v;
+ break;
+ }
+ }
+ }
+
if (abf) {
if (!p_chart_abf_solve(chart)) {
param_warning("ABF solving failed: falling back to LSCM.\n");
@@ -3192,12 +3216,12 @@ static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
}
if (npins <= 1) {
- /* not enough pins, lets find some ourself */
+ /* No pins, let's find some ourself. */
PEdge *outer;
p_chart_boundaries(chart, NULL, &outer);
- /* outer can be NULL with non-finite coords. */
+ /* Outer can be NULL with non-finite coords. */
if (!(outer && p_chart_symmetry_pins(chart, outer, &pin1, &pin2))) {
p_chart_extrema_verts(chart, &pin1, &pin2);
}
@@ -3235,6 +3259,11 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
}
}
+ if (chart->u.lscm.single_pin) {
+ /* If only one pin, save area and pin for transform later. */
+ copy_v2_v2(chart->u.lscm.single_pin_uv, chart->u.lscm.single_pin->uv);
+ }
+
if (chart->u.lscm.pin1) {
EIG_linear_solver_variable_lock(context, 2 * pin1->u.id);
EIG_linear_solver_variable_lock(context, 2 * pin1->u.id + 1);
@@ -3358,6 +3387,25 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
return P_FALSE;
}
+static void p_chart_lscm_transform_single_pin(PChart *chart)
+{
+ PVert *pin = chart->u.lscm.single_pin;
+
+ /* If only one pin, keep UV area the same. */
+ const float new_area = p_chart_uv_area(chart);
+ if (new_area > 0.0f) {
+ const float scale = chart->u.lscm.single_pin_area / new_area;
+ if (scale > 0.0f) {
+ p_chart_uv_scale(chart, sqrtf(scale));
+ }
+ }
+
+ /* Translate to keep the pinned vertex in place. */
+ float offset[2];
+ sub_v2_v2v2(offset, chart->u.lscm.single_pin_uv, pin->uv);
+ p_chart_uv_translate(chart, offset);
+}
+
static void p_chart_lscm_end(PChart *chart)
{
if (chart->u.lscm.context) {
@@ -3372,6 +3420,8 @@ static void p_chart_lscm_end(PChart *chart)
chart->u.lscm.context = NULL;
chart->u.lscm.pin1 = NULL;
chart->u.lscm.pin2 = NULL;
+ chart->u.lscm.single_pin = NULL;
+ chart->u.lscm.single_pin_area = 0.0f;
}
/* Stretch */
@@ -3781,6 +3831,23 @@ static void p_chart_rotate_minimum_area(PChart *chart)
}
}
+static void p_chart_rotate_fit_aabb(PChart *chart)
+{
+ float(*points)[2] = MEM_mallocN(sizeof(*points) * chart->nverts, __func__);
+
+ p_chart_uv_to_array(chart, points);
+
+ float angle = BLI_convexhull_aabb_fit_points_2d(points, chart->nverts);
+
+ MEM_freeN(points);
+
+ if (angle != 0.0f) {
+ float mat[2][2];
+ angle_to_mat2(mat, angle);
+ p_chart_uv_transform(chart, mat);
+ }
+}
+
/* Area Smoothing */
/* 2d bsp tree for inverse mapping - that's a bit silly */
@@ -4576,8 +4643,12 @@ void param_lscm_solve(ParamHandle *handle)
if (result && !(chart->flag & PCHART_HAS_PINS)) {
p_chart_rotate_minimum_area(chart);
}
+ else if (result && chart->u.lscm.single_pin) {
+ p_chart_rotate_fit_aabb(chart);
+ p_chart_lscm_transform_single_pin(chart);
+ }
- if (!result || (chart->u.lscm.pin1)) {
+ if (!result || !(chart->flag & PCHART_HAS_PINS)) {
p_chart_lscm_end(chart);
}
}
@@ -4692,28 +4763,13 @@ static void param_pack_rotate(ParamHandle *handle, bool ignore_pinned)
PHandle *phandle = (PHandle *)handle;
for (i = 0; i < phandle->ncharts; i++) {
- float(*points)[2];
- float angle;
-
chart = phandle->charts[i];
if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
continue;
}
- points = MEM_mallocN(sizeof(*points) * chart->nverts, __func__);
-
- p_chart_uv_to_array(chart, points);
-
- angle = BLI_convexhull_aabb_fit_points_2d(points, chart->nverts);
-
- MEM_freeN(points);
-
- if (angle != 0.0f) {
- float mat[2][2];
- angle_to_mat2(mat, angle);
- p_chart_uv_transform(chart, mat);
- }
+ p_chart_rotate_fit_aabb(chart);
}
}
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index 85a4d643a0c..283784aec20 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -280,11 +280,9 @@ void GPU_backend_init(eGPUBackendType backend_type)
void GPU_backend_exit(void)
{
- if (g_backend) {
- /* TODO assert no resource left. Currently UI textures are still not freed in their context
- * correctly. */
- delete g_backend;
- }
+ /* TODO assert no resource left. Currently UI textures are still not freed in their context
+ * correctly. */
+ delete g_backend;
}
GPUBackend *gpu_backend_get(void)
diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc
index 14ef285ad01..a45bd222664 100644
--- a/source/blender/gpu/intern/gpu_texture.cc
+++ b/source/blender/gpu/intern/gpu_texture.cc
@@ -614,6 +614,13 @@ static float *GPU_texture_rescale_3d(
static bool gpu_texture_check_capacity(
GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum data_format, GLenum data_type)
{
+ if (proxy == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB &&
+ GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_MAC, GPU_DRIVER_ANY)) {
+ /* Special fix for T79703. */
+ /* Depth has already been checked. */
+ return tex->w <= GPU_max_cube_map_size();
+ }
+
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY) ||
GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_OFFICIAL) ||
GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL)) {
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 503dba776a7..5d8eddaf5e1 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -810,6 +810,7 @@ typedef enum eBrushSculptTool {
SCULPT_TOOL_PAINT = 28,
SCULPT_TOOL_SMEAR = 29,
SCULPT_TOOL_BOUNDARY = 30,
+ SCULPT_TOOL_DISPLACEMENT_ERASER = 31,
} eBrushSculptTool;
/* Brush.uv_sculpt_tool */
@@ -847,6 +848,7 @@ typedef enum eBrushUVSculptTool {
SCULPT_TOOL_CLOTH, \
SCULPT_TOOL_THUMB, \
SCULPT_TOOL_LAYER, \
+ SCULPT_TOOL_DISPLACEMENT_ERASER, \
SCULPT_TOOL_DRAW_SHARP, \
SCULPT_TOOL_SLIDE_RELAX, \
SCULPT_TOOL_ELASTIC_DEFORM, \
@@ -866,6 +868,7 @@ typedef enum eBrushUVSculptTool {
SCULPT_TOOL_ROTATE, \
SCULPT_TOOL_THUMB, \
SCULPT_TOOL_DRAW_SHARP, \
+ SCULPT_TOOL_DISPLACEMENT_ERASER, \
SCULPT_TOOL_SLIDE_RELAX, \
SCULPT_TOOL_MASK) == 0)
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 852ddf32607..38916e2a45a 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -100,6 +100,7 @@ const EnumPropertyItem rna_enum_brush_sculpt_tool_items[] = {
{SCULPT_TOOL_CLOTH, "CLOTH", ICON_BRUSH_SCULPT_DRAW, "Cloth", ""},
{SCULPT_TOOL_SIMPLIFY, "SIMPLIFY", ICON_BRUSH_DATA, "Simplify", ""},
{SCULPT_TOOL_MASK, "MASK", ICON_BRUSH_MASK, "Mask", ""},
+ {SCULPT_TOOL_DISPLACEMENT_ERASER, "DISPLACEMENT_ERASER", ICON_BRUSH_SCULPT_DRAW, "Multires Displacement Eraser", ""},
{SCULPT_TOOL_PAINT, "PAINT", ICON_BRUSH_SCULPT_DRAW, "Paint", ""},
{SCULPT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SCULPT_DRAW, "Smear", ""},
{SCULPT_TOOL_DRAW_FACE_SETS, "DRAW_FACE_SETS", ICON_BRUSH_MASK, "Draw Face Sets", ""},
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 05e11ffc919..f95899262d3 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -5539,7 +5539,8 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "octree_depth", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "depth");
- RNA_def_property_range(prop, 1, 12);
+ RNA_def_property_range(prop, 1, 24);
+ RNA_def_property_ui_range(prop, 1, 12, 1, 3);
RNA_def_property_ui_text(
prop, "Octree Depth", "Resolution of the octree; higher values give finer details");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 3b80714bcc5..609340888e1 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -714,7 +714,9 @@ bool rna_Object_generate_gpencil_strokes(Object *ob,
ReportList *reports,
Object *ob_gpencil,
bool gpencil_lines,
- bool use_collections)
+ bool use_collections,
+ float scale_thickness,
+ float sample)
{
if (ob->type != OB_CURVE) {
BKE_reportf(reports,
@@ -726,7 +728,8 @@ bool rna_Object_generate_gpencil_strokes(Object *ob,
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, gpencil_lines, use_collections, false);
+ BKE_gpencil_convert_curve(
+ bmain, scene, ob_gpencil, ob, gpencil_lines, use_collections, scale_thickness, sample);
WM_main_add_notifier(NC_GPENCIL | ND_DATA, NULL);
@@ -1190,12 +1193,18 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(func, "Convert a curve object to grease pencil strokes.");
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(
- func, "ob_gpencil", "Object", "", "Grease Pencil object used to create new strokes");
+ parm = RNA_def_pointer(func,
+ "grease_pencil_object",
+ "Object",
+ "",
+ "Grease Pencil object used to create new strokes");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_boolean(func, "gpencil_lines", 0, "", "Create Lines");
- parm = RNA_def_boolean(func, "use_collections", 1, "", "Use Collections");
-
+ parm = RNA_def_boolean(func, "gpencil_lines", false, "", "Create Lines");
+ parm = RNA_def_boolean(func, "use_collections", true, "", "Use Collections");
+ parm = RNA_def_float(
+ func, "scale_thickness", 1.0f, 0.0f, FLT_MAX, "", "Thickness scaling factor", 0.0f, 100.0f);
+ parm = RNA_def_float(
+ func, "sample", 0.0f, 0.0f, FLT_MAX, "", "Sample distance, zero to disable", 0.0f, 100.0f);
parm = RNA_def_boolean(func, "result", 0, "", "Result");
RNA_def_function_return(func, parm);
}
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index f091385ff8e..98a348bfbfc 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -487,7 +487,7 @@ static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = modifier_panel_register(region_type, eModifierType_Multires, panel_draw);
modifier_subpanel_register(
- region_type, "subdivide", "Subdivions", NULL, subdivisions_panel_draw, panel_type);
+ region_type, "subdivide", "Subdivision", NULL, subdivisions_panel_draw, panel_type);
modifier_subpanel_register(region_type, "shape", "Shape", NULL, shape_panel_draw, panel_type);
modifier_subpanel_register(
region_type, "generate", "Generate", NULL, generate_panel_draw, panel_type);
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index a0c4799a46f..797d9e9e251 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -772,6 +772,11 @@ static EMat *build_edge_mats(const MVertSkin *vs,
*has_valid_root = true;
}
+ else if (totedge == 0) {
+ /* Vertex-only mesh is valid, mark valid root as well (will display error otherwise). */
+ *has_valid_root = true;
+ break;
+ }
}
}
diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c
index 83558bc9192..953fb9fed79 100644
--- a/source/blender/windowmanager/intern/wm_keymap_utils.c
+++ b/source/blender/windowmanager/intern/wm_keymap_utils.c
@@ -217,7 +217,6 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
* FLUID_OT
* TEXTURE_OT
* UI_OT
- * VIEW2D_OT
* WORLD_OT
*/
@@ -344,6 +343,10 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
break;
}
}
+ /* General 2D View, not bound to a specific spacetype. */
+ else if (STRPREFIX(opname, "VIEW2D_OT")) {
+ km = WM_keymap_find_all(wm, "View2D", 0, 0);
+ }
/* Image Editor */
else if (STRPREFIX(opname, "IMAGE_OT")) {
km = WM_keymap_find_all(wm, "Image", sl->spacetype, 0);