Fix #119909: Unkeyable custom properties receive keyframes #119914

Merged
Christoph Lendenfeld merged 13 commits from ChrisLend/blender:fix_more_selective_when_keying_custom_props into main 2024-04-12 14:48:20 +02:00
230 changed files with 9878 additions and 1422 deletions
Showing only changes of commit ab99bbf56e - Show all commits

View File

@ -32,6 +32,7 @@ endif()
add_subdirectory(rangetree)
add_subdirectory(nanosvg)
add_subdirectory(wcwidth)
add_subdirectory(xxhash)
if(WITH_BULLET)
if(NOT WITH_SYSTEM_BULLET)

21
extern/xxhash/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2024 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
PUBLIC .
)
set(INC_SYS
)
set(SRC
xxhash.c
xxhash.h
)
set(LIB
)
blender_add_lib(extern_xxhash "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
add_library(bf::extern::xxhash ALIAS extern_xxhash)

26
extern/xxhash/LICENSE vendored Normal file
View File

@ -0,0 +1,26 @@
xxHash Library
Copyright (c) 2012-2021 Yann Collet
All rights reserved.
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* 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.
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.

6
extern/xxhash/README.blender vendored Normal file
View File

@ -0,0 +1,6 @@
Project: xxHash
URL: https://xxhash.com/
License: BSD 2-Clause
Upstream version: v0.8.2 (2023-07-21)
Local modifications:
* None

43
extern/xxhash/xxhash.c vendored Normal file
View File

@ -0,0 +1,43 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2012-2021 Yann Collet
*
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
*
* 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
* OWNER 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.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* xxhash.c instantiates functions defined in xxhash.h
*/
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
#define XXH_IMPLEMENTATION /* access definitions */
#include "xxhash.h"

6773
extern/xxhash/xxhash.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -175,9 +175,8 @@ static void clg_str_vappendf(CLogStringBuf *cstr, const char *fmt, va_list args)
{
/* Use limit because windows may use '-1' for a formatting error. */
const uint len_max = 65535;
uint len_avail = cstr->len_alloc - cstr->len;
while (true) {
uint len_avail = cstr->len_alloc - cstr->len;
va_list args_cpy;
va_copy(args_cpy, args);
int retval = vsnprintf(cstr->data + cstr->len, len_avail, fmt, args_cpy);
@ -188,22 +187,23 @@ static void clg_str_vappendf(CLogStringBuf *cstr, const char *fmt, va_list args)
* message. */
break;
}
else if ((uint)retval <= len_avail) {
if ((uint)retval <= len_avail) {
/* Copy was successful. */
cstr->len += (uint)retval;
break;
}
else {
/* vsnprintf was not successful, due to lack of allocated space, retval contains expected
* length of the formatted string, use it to allocate required amount of memory. */
uint len_alloc = cstr->len + (uint)retval;
if (len_alloc >= len_max) {
/* Safe upper-limit, just in case... */
break;
}
clg_str_reserve(cstr, len_alloc);
len_avail = cstr->len_alloc - cstr->len;
/* `vsnprintf` was not successful, due to lack of allocated space, `retval` contains expected
* length of the formatted string, use it to allocate required amount of memory. */
uint len_alloc = cstr->len + (uint)retval;
if (len_alloc >= len_max) {
/* Safe upper-limit, just in case... */
break;
}
clg_str_reserve(cstr, len_alloc);
len_avail = cstr->len_alloc - cstr->len;
}
}

View File

@ -773,8 +773,9 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
size_t &kernel_local_size)
{
assert(queue);
const static size_t preferred_work_group_size_intersect_shading = 32;
const static size_t preferred_work_group_size_intersect = 128;
const static size_t preferred_work_group_size_shading = 256;
const static size_t preferred_work_group_size_shading_simd8 = 64;
/* Shader evaluation kernels seems to use some amount of shared memory, so better
* to avoid usage of maximum work group sizes for them. */
const static size_t preferred_work_group_size_shader_evaluation = 256;
@ -783,6 +784,9 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
const static size_t preferred_work_group_size_cryptomatte = 512;
const static size_t preferred_work_group_size_default = 1024;
const sycl::device &device = reinterpret_cast<sycl::queue *>(queue)->get_device();
const size_t max_work_group_size = device.get_info<sycl::info::device::max_work_group_size>();
size_t preferred_work_group_size = 0;
switch (kernel) {
case DEVICE_KERNEL_INTEGRATOR_INIT_FROM_CAMERA:
@ -792,6 +796,9 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE:
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK:
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_DEDICATED_LIGHT:
preferred_work_group_size = preferred_work_group_size_intersect;
break;
case DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND:
case DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT:
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE:
@ -799,9 +806,13 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE:
case DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME:
case DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW:
case DEVICE_KERNEL_INTEGRATOR_SHADE_DEDICATED_LIGHT:
preferred_work_group_size = preferred_work_group_size_intersect_shading;
break;
case DEVICE_KERNEL_INTEGRATOR_SHADE_DEDICATED_LIGHT: {
const bool device_is_simd8 =
(device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) &&
device.get_info<sycl::ext::intel::info::device::gpu_eu_simd_width>() == 8);
preferred_work_group_size = (device_is_simd8) ? preferred_work_group_size_shading_simd8 :
preferred_work_group_size_shading;
} break;
case DEVICE_KERNEL_CRYPTOMATTE_POSTPROCESS:
preferred_work_group_size = preferred_work_group_size_cryptomatte;
@ -829,11 +840,7 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
preferred_work_group_size = preferred_work_group_size_default;
}
const size_t limit_work_group_size = reinterpret_cast<sycl::queue *>(queue)
->get_device()
.get_info<sycl::info::device::max_work_group_size>();
kernel_local_size = std::min(limit_work_group_size, preferred_work_group_size);
kernel_local_size = std::min(max_work_group_size, preferred_work_group_size);
/* NOTE(@nsirgien): As for now non-uniform work-groups don't work on most oneAPI devices,
* we extend work size to fit uniformity requirements. */

View File

@ -46,7 +46,7 @@ static const char *oidn_device_type_to_string(const OIDNDeviceType type)
return "HIP";
# endif
/* The Metal support was added in OIDN 2.2.*/
/* The Metal support was added in OIDN 2.2. */
# if (OIDN_VERSION_MAJOR > 2) || ((OIDN_VERSION_MAJOR == 2) && (OIDN_VERSION_MINOR >= 2))
case OIDN_DEVICE_TYPE_METAL:
return "METAL";

View File

@ -18,7 +18,7 @@ typedef struct HuangHairExtra {
/* Optional modulation factors. */
float R, TT, TRT;
/* Local coordinate system. X is stored as `bsdf->N`.*/
/* Local coordinate system. X is stored as `bsdf->N`. */
float3 Y, Z;
/* Incident direction in local coordinate system. */

View File

@ -38,7 +38,7 @@
#define ccl_global
#define ccl_always_inline __attribute__((always_inline))
#define ccl_device_inline inline
#define ccl_noinline __attribute__((noinline))
#define ccl_noinline
#define ccl_inline_constant const constexpr
#define ccl_device_constant static constexpr
#define ccl_static_constexpr static constexpr

View File

@ -115,10 +115,10 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
{
void *newp = NULL;
if (vmemh) {
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
const MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
const size_t prev_size = MEM_lockfree_allocN_len(vmemh);
if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
const MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
newp = MEM_lockfree_mallocN_aligned(
prev_size, (size_t)memh_aligned->alignment, "dupli_malloc");
}
@ -135,14 +135,14 @@ void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *str)
void *newp = NULL;
if (vmemh) {
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
size_t old_len = MEM_lockfree_allocN_len(vmemh);
const MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
const size_t old_len = MEM_lockfree_allocN_len(vmemh);
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
newp = MEM_lockfree_mallocN(len, "realloc");
}
else {
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
const MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "realloc");
}
@ -171,14 +171,14 @@ void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *str)
void *newp = NULL;
if (vmemh) {
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
size_t old_len = MEM_lockfree_allocN_len(vmemh);
const MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
const size_t old_len = MEM_lockfree_allocN_len(vmemh);
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
newp = MEM_lockfree_mallocN(len, "recalloc");
}
else {
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
const MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "recalloc");
}

View File

@ -0,0 +1,23 @@
The 2-Clause BSD License
------------------------
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* 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.
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.

View File

@ -231,6 +231,72 @@ class DATA_PT_grease_pencil_layer_relations(LayerDataButtonsPanel, Panel):
col.prop_search(layer, "viewlayer_render", context.scene, "view_layers", text="View Layer")
class DATA_PT_grease_pencil_onion_skinning(DataButtonsPanel, Panel):
bl_label = "Onion Skinning"
def draw(self, context):
grease_pencil = context.grease_pencil
layout = self.layout
layout.use_property_split = True
col = layout.column()
col.prop(grease_pencil, "onion_mode")
col.prop(grease_pencil, "onion_factor", text="Opacity", slider=True)
col.prop(grease_pencil, "onion_keyframe_type")
if grease_pencil.onion_mode == 'ABSOLUTE':
col = layout.column(align=True)
col.prop(grease_pencil, "ghost_before_range", text="Frames Before")
col.prop(grease_pencil, "ghost_after_range", text="Frames After")
elif grease_pencil.onion_mode == 'RELATIVE':
col = layout.column(align=True)
col.prop(grease_pencil, "ghost_before_range", text="Keyframes Before")
col.prop(grease_pencil, "ghost_after_range", text="Keyframes After")
class DATA_PT_grease_pencil_onion_skinning_custom_colors(DataButtonsPanel, Panel):
bl_parent_id = "DATA_PT_grease_pencil_onion_skinning"
bl_label = "Custom Colors"
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
grease_pencil = context.grease_pencil
self.layout.prop(grease_pencil, "use_ghost_custom_colors", text="")
def draw(self, context):
grease_pencil = context.grease_pencil
layout = self.layout
layout.use_property_split = True
layout.enabled = grease_pencil.users <= 1 and grease_pencil.use_ghost_custom_colors
layout.prop(grease_pencil, "before_color", text="Before")
layout.prop(grease_pencil, "after_color", text="After")
class DATA_PT_grease_pencil_onion_skinning_display(DataButtonsPanel, Panel):
bl_parent_id = "DATA_PT_grease_pencil_onion_skinning"
bl_label = "Display"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
grease_pencil = context.grease_pencil
layout = self.layout
layout.use_property_split = True
# This was done in GPv2 but it's not entirely clear why. Presumably it was
# to indicate that the settings will affect the onion skinning of the
# other users.
layout.enabled = grease_pencil.users <= 1
col = layout.column(align=True)
col.prop(grease_pencil, "use_onion_fade", text="Fade")
sub = layout.column()
sub.active = grease_pencil.onion_mode in {'RELATIVE', 'SELECTED'}
sub.prop(grease_pencil, "use_onion_loop", text="Show Start Frame")
class DATA_PT_grease_pencil_settings(DataButtonsPanel, Panel):
bl_label = "Settings"
@ -257,6 +323,9 @@ classes = (
DATA_PT_grease_pencil_layer_masks,
DATA_PT_grease_pencil_layer_transform,
DATA_PT_grease_pencil_layer_relations,
DATA_PT_grease_pencil_onion_skinning,
DATA_PT_grease_pencil_onion_skinning_custom_colors,
DATA_PT_grease_pencil_onion_skinning_display,
DATA_PT_grease_pencil_settings,
DATA_PT_grease_pencil_custom_props,
GREASE_PENCIL_MT_grease_pencil_add_layer_extra,

View File

@ -816,6 +816,27 @@ def brush_settings(layout, context, brush, popover=False):
col.active = not brush.curves_sculpt_settings.use_point_count_interpolate
col.prop(brush.curves_sculpt_settings, "points_per_curve", text="Points")
if brush.curves_sculpt_tool == 'DENSITY':
col = layout.column()
col.prop(brush.curves_sculpt_settings, "density_add_attempts", text="Count Max")
col = layout.column(heading="Interpolate", align=True)
col.prop(brush.curves_sculpt_settings, "use_length_interpolate", text="Length")
col.prop(brush.curves_sculpt_settings, "use_radius_interpolate", text="Radius")
col.prop(brush.curves_sculpt_settings, "use_shape_interpolate", text="Shape")
col.prop(brush.curves_sculpt_settings, "use_point_count_interpolate", text="Point Count")
col = layout.column()
col.active = not brush.curves_sculpt_settings.use_length_interpolate
col.prop(brush.curves_sculpt_settings, "curve_length", text="Length")
col = layout.column()
col.active = not brush.curves_sculpt_settings.use_radius_interpolate
col.prop(brush.curves_sculpt_settings, "curve_radius", text="Radius")
col = layout.column()
col.active = not brush.curves_sculpt_settings.use_point_count_interpolate
col.prop(brush.curves_sculpt_settings, "points_per_curve", text="Points")
elif brush.curves_sculpt_tool == 'GROW_SHRINK':
layout.prop(brush.curves_sculpt_settings, "use_uniform_scale")
layout.prop(brush.curves_sculpt_settings, "minimum_length")

View File

@ -671,8 +671,8 @@ class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):
import sys
return sys.platform[:3] == "win"
def draw_centered(self, _context, layout):
if _context.preferences.system.is_microsoft_store_install:
def draw_centered(self, context, layout):
if context.preferences.system.is_microsoft_store_install:
layout.label(text="Microsoft Store installation")
layout.label(text="Use Windows 'Default Apps' to associate with blend files")
else:

View File

@ -7861,6 +7861,8 @@ class VIEW3D_PT_overlay_grease_pencil_options(Panel):
'OBJECT': iface_("Grease Pencil"),
}[context.mode], translate=False)
layout.prop(overlay, "use_gpencil_onion_skin", text="Onion Skin")
if ob.mode in {'EDIT'}:
split = layout.split()
col = split.column()

View File

@ -105,6 +105,7 @@ set(SRC_DNA_DEFAULTS_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_fluid_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_grease_pencil_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lattice_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_light_defaults.h

View File

@ -30,7 +30,7 @@ class BoneColor : public ::BoneColor {
const ThemeWireColor *effective_color() const;
/* Support for storing in a blender::Set<BoneColor>.*/
/* Support for storing in a #blender::Set<BoneColor>. */
bool operator==(const BoneColor &other) const;
bool operator!=(const BoneColor &other) const;
uint64_t hash() const;

View File

@ -73,7 +73,8 @@ bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
has_parent = (pchan->parent != nullptr);
}
else {
BLI_assert(!"visualkey_can_use called for data-block that is not an Object or PoseBone.");
BLI_assert_msg(false,
"visualkey_can_use called for data-block that is not an Object or PoseBone.");
return false;
}

View File

@ -280,7 +280,7 @@ std::unique_ptr<AssetCatalogDefinitionFile> AssetCatalogDefinitionFile::copy_and
continue;
}
BLI_assert(!"A CDF should only reference known catalogs.");
BLI_assert_msg(false, "A CDF should only reference known catalogs.");
}
return copy;

View File

@ -35,7 +35,7 @@ void BKE_addon_pref_type_init(void);
void BKE_addon_pref_type_free(void);
struct bAddon *BKE_addon_new(void);
struct bAddon *BKE_addon_find(struct ListBase *addon_list, const char *module);
struct bAddon *BKE_addon_find(const struct ListBase *addon_list, const char *module);
struct bAddon *BKE_addon_ensure(struct ListBase *addon_list, const char *module);
bool BKE_addon_remove_safe(struct ListBase *addon_list, const char *module);
void BKE_addon_free(struct bAddon *addon);

View File

@ -280,17 +280,17 @@ void BKE_pose_where_is_bone_tail(bPoseChannel *pchan);
*/
void BKE_pose_apply_action_selected_bones(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context);
const AnimationEvalContext *anim_eval_context);
/**
* Evaluate the action and apply it to the pose. Ignore selection state of the bones.
*/
void BKE_pose_apply_action_all_bones(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context);
const AnimationEvalContext *anim_eval_context);
void BKE_pose_apply_action_blend(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context,
const AnimationEvalContext *anim_eval_context,
float blend_factor);
void vec_roll_to_mat3(const float vec[3], float roll, float r_mat[3][3]);

View File

@ -89,23 +89,11 @@ class BlobWriteSharing : NonCopyable, NonMovable {
*/
Map<const ImplicitSharingInfo *, StoredByRuntimeValue> stored_by_runtime_;
struct SliceHash {
uint64_t a;
uint64_t b;
BLI_STRUCT_EQUALITY_OPERATORS_2(SliceHash, a, b)
uint64_t hash() const
{
return get_default_hash(this->a, this->b);
}
};
/**
* Remembers where data was stored based on the hash of the data. This allows us to skip writing
* the same array again if it has the same hash.
*/
Map<SliceHash, BlobSlice> slice_by_content_hash_;
Map<uint64_t, BlobSlice> slice_by_content_hash_;
public:
~BlobWriteSharing();

View File

@ -11,7 +11,7 @@
#include "BLI_bounds_types.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_implicit_sharing.hh"
#include "BLI_implicit_sharing_ptr.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
@ -451,7 +451,7 @@ class CurvesEditHints {
* Evaluated positions for the points in #curves_orig. If this is empty, the positions from the
* evaluated #Curves should be used if possible.
*/
std::optional<Array<float3>> positions;
ImplicitSharingPtrAndData positions_data;
/**
* Matrices which transform point movement vectors from original data to corresponding movements
* of evaluated data.
@ -460,6 +460,9 @@ class CurvesEditHints {
CurvesEditHints(const Curves &curves_id_orig) : curves_id_orig(curves_id_orig) {}
std::optional<Span<float3>> positions() const;
std::optional<MutableSpan<float3>> positions_for_write();
/**
* The edit hints have to correspond to the original curves, i.e. the number of deformed points
* is the same as the number of original points.

View File

@ -249,14 +249,13 @@ void *CustomData_add_layer(CustomData *data,
/**
* Adds a layer of the given type to the #CustomData object. The new layer takes ownership of the
* passed in `layer_data`. If a #ImplicitSharingInfoHandle is passed in, its user count is
* increased.
* passed in `layer_data`. If a #ImplicitSharingInfo is passed in, its user count is increased.
*/
const void *CustomData_add_layer_with_data(CustomData *data,
eCustomDataType type,
void *layer_data,
int totelem,
const ImplicitSharingInfoHandle *sharing_info);
const blender::ImplicitSharingInfo *sharing_info);
/**
* Same as above but accepts a name.
@ -272,7 +271,7 @@ const void *CustomData_add_layer_named_with_data(CustomData *data,
void *layer_data,
int totelem,
blender::StringRef name,
const ImplicitSharingInfoHandle *sharing_info);
const blender::ImplicitSharingInfo *sharing_info);
void *CustomData_add_layer_anonymous(CustomData *data,
eCustomDataType type,
@ -285,7 +284,7 @@ const void *CustomData_add_layer_anonymous_with_data(
const AnonymousAttributeIDHandle *anonymous_id,
int totelem,
void *layer_data,
const ImplicitSharingInfoHandle *sharing_info);
const blender::ImplicitSharingInfo *sharing_info);
/**
* Frees the active or first data layer with the give type.

View File

@ -17,22 +17,38 @@ struct BMEditMesh;
namespace blender::bke {
struct EditMeshData {
/** when set, \a vertexNos, faceNos are lazy initialized */
/**
* Deformed positions calculated by modifiers in the modifier stack that can can process an
* edit mesh input. When this is not empty, the other arrays will depend on the values.
*/
Array<float3> vert_positions;
/** lazy initialize (when \a vert_positions is set) */
/**
* Lazily initialized vertex normal cache (used when `vert_positions` is set.
* Access via #BKE_editmesh_cache_ensure_vert_normals instead of directly.
*/
Array<float3> vert_normals;
/**
* Lazily initialized face normal cache (used when `vert_positions` is set.
* Access via #BKE_editmesh_cache_ensure_face_normals instead of directly.
*/
Array<float3> face_normals;
/** also lazy init but don't depend on \a vert_positions */
/**
* Cache of face centers, also depends on `vert_positions` when it is not empty.
* Access via #BKE_editmesh_cache_ensure_face_centers instead of directly.
*/
Array<float3> face_centers;
};
} // namespace blender::bke
void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMeshData &emd);
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMeshData &emd);
blender::Span<blender::float3> BKE_editmesh_cache_ensure_face_normals(
BMEditMesh &em, blender::bke::EditMeshData &emd);
blender::Span<blender::float3> BKE_editmesh_cache_ensure_vert_normals(
BMEditMesh &em, blender::bke::EditMeshData &emd);
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em, blender::bke::EditMeshData &emd);
blender::Span<blender::float3> BKE_editmesh_cache_ensure_face_centers(
BMEditMesh &em, blender::bke::EditMeshData &emd);
std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax(
const BMEditMesh &em, const blender::bke::EditMeshData &emd);

View File

@ -14,6 +14,7 @@
#include "BLI_array_utils.hh"
#include "BLI_color.hh"
#include "BLI_function_ref.hh"
#include "BLI_implicit_sharing_ptr.hh"
#include "BLI_map.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
@ -702,7 +703,8 @@ inline void TreeNode::set_selected(const bool selected)
}
inline bool TreeNode::use_onion_skinning() const
{
return ((this->flag & GP_LAYER_TREE_NODE_USE_ONION_SKINNING) != 0);
return ((this->flag & GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING) == 0) &&
(!this->parent_group() || this->parent_group()->as_node().use_onion_skinning());
}
inline bool TreeNode::use_masks() const
{
@ -773,7 +775,11 @@ class GreasePencilRuntime {
class GreasePencilDrawingEditHints {
public:
std::optional<Array<float3>> positions;
const greasepencil::Drawing *drawing_orig;
ImplicitSharingPtrAndData positions_data;
std::optional<Span<float3>> positions() const;
std::optional<MutableSpan<float3>> positions_for_write();
};
/**

View File

@ -83,7 +83,7 @@ bool BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle,
void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase);
std::optional<std::string> BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle,
struct ColorBand *color_ramp);
const struct ColorBand *color_ramp);
bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, bool use_shading_nodes);

View File

@ -67,8 +67,8 @@ void BKE_mask_point_free(struct MaskSplinePoint *point);
void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay);
void BKE_mask_layer_rename(struct Mask *mask,
struct MaskLayer *masklay,
char *oldname,
char *newname);
const char *oldname,
const char *newname);
struct MaskLayer *BKE_mask_layer_copy(const struct MaskLayer *masklay);
void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, const struct ListBase *masklayers);

View File

@ -494,9 +494,6 @@ bool BKE_mesh_validate_all_customdata(CustomData *vert_data,
void BKE_mesh_strip_loose_faces(Mesh *mesh);
/* In DerivedMesh.cc */
void BKE_mesh_wrapper_deferred_finalize_mdata(Mesh *mesh_eval);
/* **** Depsgraph evaluation **** */
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh);

View File

@ -163,11 +163,6 @@ struct MeshRuntime {
/** #eMeshWrapperType and others. */
eMeshWrapperType wrapper_type = ME_WRAPPER_TYPE_MDATA;
/**
* A type mask from wrapper_type,
* in case there are differences in finalizing logic between types.
*/
eMeshWrapperType wrapper_type_finalize = ME_WRAPPER_TYPE_MDATA;
/**
* Settings for lazily evaluating the subdivision on the CPU if needed. These are

View File

@ -87,7 +87,7 @@ void BKE_movieclip_build_proxy_frame(struct MovieClip *clip,
int clip_flag,
struct MovieDistortion *distortion,
int cfra,
int *build_sizes,
const int *build_sizes,
int build_count,
bool undistorted);
@ -99,7 +99,7 @@ void BKE_movieclip_build_proxy_frame_for_ibuf(struct MovieClip *clip,
struct ImBuf *ibuf,
struct MovieDistortion *distortion,
int cfra,
int *build_sizes,
const int *build_sizes,
int build_count,
bool undistorted);
bool BKE_movieclip_proxy_enabled(struct MovieClip *clip);

View File

@ -123,7 +123,7 @@ int BKE_packedfile_count_all(struct Main *bmain);
*/
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
const char *filepath_rel,
struct PackedFile *pf);
const struct PackedFile *pf);
/* Read. */
@ -143,7 +143,7 @@ void BKE_packedfile_id_unpack(struct Main *bmain,
struct ReportList *reports,
enum ePF_FileStatus how);
void BKE_packedfile_blend_write(struct BlendWriter *writer, struct PackedFile *pf);
void BKE_packedfile_blend_write(struct BlendWriter *writer, const struct PackedFile *pf);
void BKE_packedfile_blend_read(struct BlendDataReader *reader, struct PackedFile **pf_p);
#ifdef __cplusplus

View File

@ -220,11 +220,8 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG &subdiv_ccg,
int &r_num_loops);
struct SubdivCCGNeighbors {
SubdivCCGCoord *coords;
int size;
blender::Array<SubdivCCGCoord, 256> coords;
int num_duplicates;
SubdivCCGCoord coords_fixed[256];
};
void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord &coord);
@ -244,9 +241,6 @@ bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG &subdiv_ccg, const SubdivC
* element inside of every neighboring grid. */
/* Get actual neighbors of the given coordinate.
*
* SubdivCCGNeighbors.neighbors must be freed if it is not equal to
* SubdivCCGNeighbors.fixed_neighbors.
*
* If include_duplicates is true, vertices in other grids that match
* the current vertex are added at the end of the coords array. */

View File

@ -65,7 +65,7 @@ void txt_clean_text(struct Text *text);
void txt_order_cursors(struct Text *text, bool reverse);
int txt_find_string(struct Text *text, const char *findstr, int wrap, int match_case);
bool txt_has_sel(const struct Text *text);
int txt_get_span(struct TextLine *from, const struct TextLine *to);
int txt_get_span(const struct TextLine *from, const struct TextLine *to);
void txt_move_up(struct Text *text, bool sel);
void txt_move_down(struct Text *text, bool sel);
void txt_move_left(struct Text *text, bool sel);

View File

@ -579,6 +579,7 @@ set(LIB
bf_shader_fx
bf_simulation
PRIVATE bf::extern::fmtlib
PRIVATE bf::extern::xxhash
PRIVATE bf::intern::atomic
# For `vfontdata_freetype.c`.
${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES}

View File

@ -221,7 +221,8 @@ struct CCGSubSurf {
(void)0
#define NormCopy(av, bv) \
{ \
float *_a = (float *)av, *_b = (float *)bv; \
float *_a = (float *)av; \
const float *_b = (const float *)bv; \
_a[0] = _b[0]; \
_a[1] = _b[1]; \
_a[2] = _b[2]; \
@ -229,7 +230,8 @@ struct CCGSubSurf {
(void)0
#define NormAdd(av, bv) \
{ \
float *_a = (float *)av, *_b = (float *)bv; \
float *_a = (float *)av; \
const float *_b = (const float *)bv; \
_a[0] += _b[0]; \
_a[1] += _b[1]; \
_a[2] += _b[2]; \

View File

@ -70,12 +70,16 @@ static float *_face_getIFNoEdge(CCGFace *f,
static void _face_calcIFNo(
CCGFace *f, int lvl, int S, int x, int y, float no[3], int levels, int dataSize)
{
float *a = static_cast<float *>(ccg_face_getIFCo(f, lvl, S, x + 0, y + 0, levels, dataSize));
float *b = static_cast<float *>(ccg_face_getIFCo(f, lvl, S, x + 1, y + 0, levels, dataSize));
float *c = static_cast<float *>(ccg_face_getIFCo(f, lvl, S, x + 1, y + 1, levels, dataSize));
float *d = static_cast<float *>(ccg_face_getIFCo(f, lvl, S, x + 0, y + 1, levels, dataSize));
float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
const float *a = static_cast<float *>(
ccg_face_getIFCo(f, lvl, S, x + 0, y + 0, levels, dataSize));
const float *b = static_cast<float *>(
ccg_face_getIFCo(f, lvl, S, x + 1, y + 0, levels, dataSize));
const float *c = static_cast<float *>(
ccg_face_getIFCo(f, lvl, S, x + 1, y + 1, levels, dataSize));
const float *d = static_cast<float *>(
ccg_face_getIFCo(f, lvl, S, x + 0, y + 1, levels, dataSize));
const float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
const float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
no[0] = b_dY * a_cZ - b_dZ * a_cY;
no[1] = b_dZ * a_cX - b_dX * a_cZ;

View File

@ -89,8 +89,6 @@ using blender::bke::MeshComponent;
#endif
static void mesh_init_origspace(Mesh *mesh);
static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final);
static void editbmesh_calc_modifier_final_normals_or_defer(Mesh *mesh_final);
/* -------------------------------------------------------------------- */
@ -465,16 +463,6 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval)
mesh_eval->runtime->edit_mesh = mesh_input->runtime->edit_mesh;
}
void BKE_mesh_wrapper_deferred_finalize_mdata(Mesh *mesh_eval)
{
if (mesh_eval->runtime->wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) {
editbmesh_calc_modifier_final_normals(mesh_eval);
mesh_eval->runtime->wrapper_type_finalize = eMeshWrapperType(
mesh_eval->runtime->wrapper_type_finalize & ~(1 << ME_WRAPPER_TYPE_BMESH));
}
BLI_assert(mesh_eval->runtime->wrapper_type_finalize == 0);
}
/**
* Modifies the given mesh and geometry set. The mesh is not passed as part of the mesh component
* in the \a geometry_set input, it is only passed in \a input_mesh and returned in the return
@ -1001,36 +989,6 @@ bool editbmesh_modifier_is_enabled(const Scene *scene,
return true;
}
static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final)
{
switch (mesh_final->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
break;
case ME_WRAPPER_TYPE_BMESH: {
BMEditMesh &em = *mesh_final->runtime->edit_mesh;
blender::bke::EditMeshData &emd = *mesh_final->runtime->edit_data;
if (!emd.vert_positions.is_empty()) {
BKE_editmesh_cache_ensure_vert_normals(em, emd);
BKE_editmesh_cache_ensure_face_normals(em, emd);
}
return;
}
}
}
static void editbmesh_calc_modifier_final_normals_or_defer(Mesh *mesh_final)
{
if (mesh_final->runtime->wrapper_type != ME_WRAPPER_TYPE_MDATA) {
/* Generated at draw time. */
mesh_final->runtime->wrapper_type_finalize = eMeshWrapperType(
1 << mesh_final->runtime->wrapper_type);
return;
}
editbmesh_calc_modifier_final_normals(mesh_final);
}
static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
{
switch (mesh->runtime->wrapper_type) {
@ -1244,12 +1202,6 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
BKE_id_free(nullptr, mesh_orco);
}
/* Compute normals. */
editbmesh_calc_modifier_final_normals_or_defer(mesh_final);
if (mesh_cage && (mesh_cage != mesh_final)) {
editbmesh_calc_modifier_final_normals_or_defer(mesh_cage);
}
/* Return final mesh. */
*r_final = mesh_final;
if (r_cage) {

View File

@ -350,8 +350,8 @@ void action_group_colors_sync(bActionGroup *grp, const bActionGroup *ref_grp)
if (grp->customCol) {
if (grp->customCol > 0) {
/* copy theme colors on-to group's custom color in case user tries to edit color */
bTheme *btheme = static_cast<bTheme *>(U.themes.first);
ThemeWireColor *col_set = &btheme->tarm[(grp->customCol - 1)];
const bTheme *btheme = static_cast<const bTheme *>(U.themes.first);
const ThemeWireColor *col_set = &btheme->tarm[(grp->customCol - 1)];
memcpy(&grp->cs, col_set, sizeof(ThemeWireColor));
}
@ -1779,6 +1779,9 @@ void what_does_obaction(Object *ob,
/* execute effects of Action on to workob (or its PoseChannels) */
BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
/* Ensure stack memory set here isn't accessed later, relates to !118847. */
workob->adt = nullptr;
}
/* Ensure stack memory set here isn't accessed later, see !118847. */
workob->runtime = nullptr;

View File

@ -38,7 +38,7 @@ bAddon *BKE_addon_new()
return addon;
}
bAddon *BKE_addon_find(ListBase *addon_list, const char *module)
bAddon *BKE_addon_find(const ListBase *addon_list, const char *module)
{
return static_cast<bAddon *>(BLI_findstring(addon_list, module, offsetof(bAddon, module)));
}

View File

@ -2850,8 +2850,9 @@ static void nlastrip_evaluate_transition(const int evaluation_mode,
break;
}
case STRIP_EVAL_NOBLEND: {
BLI_assert( !"This case shouldn't occur. Transitions assumed to not reference other "
"transitions. ");
BLI_assert_msg(false,
"This case shouldn't occur. "
"Transitions assumed to not reference other transitions.");
break;
}
}

View File

@ -34,14 +34,14 @@ void pose_apply_restore_fcurves(bAction *action);
void pose_apply(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context,
const AnimationEvalContext *anim_eval_context,
ActionApplier applier);
} // namespace
void BKE_pose_apply_action_selected_bones(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context)
const AnimationEvalContext *anim_eval_context)
{
auto evaluate_and_apply =
[](PointerRNA *ptr, bAction *act, const AnimationEvalContext *anim_eval_context) {
@ -53,7 +53,7 @@ void BKE_pose_apply_action_selected_bones(Object *ob,
void BKE_pose_apply_action_all_bones(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context)
const AnimationEvalContext *anim_eval_context)
{
PointerRNA pose_owner_ptr = RNA_id_pointer_create(&ob->id);
animsys_evaluate_action(&pose_owner_ptr, action, anim_eval_context, false);
@ -61,7 +61,7 @@ void BKE_pose_apply_action_all_bones(Object *ob,
void BKE_pose_apply_action_blend(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context,
const AnimationEvalContext *anim_eval_context,
const float blend_factor)
{
auto evaluate_and_blend = [blend_factor](PointerRNA *ptr,
@ -76,7 +76,7 @@ void BKE_pose_apply_action_blend(Object *ob,
namespace {
void pose_apply(Object *ob,
bAction *action,
AnimationEvalContext *anim_eval_context,
const AnimationEvalContext *anim_eval_context,
ActionApplier applier)
{
bPose *pose = ob->pose;

View File

@ -338,7 +338,7 @@ static int position_tail_on_spline(bSplineIKConstraint *ik_data,
}
/* Calculate the intersection point using the secant root finding method */
float x0 = 0.0f, x1 = 1.0f, x2 = 0.5f;
float x0 = 0.0f, x1 = 1.0f;
float x0_point[3], x1_point[3], start_p[3];
float epsilon = max_fff(1.0f, len_v3(head_pos), len_v3(bp->vec)) * FLT_EPSILON;
@ -364,7 +364,7 @@ static int position_tail_on_spline(bSplineIKConstraint *ik_data,
break;
}
x2 = x1 - f_x1 * (x1 - x0) / (f_x1 - f_x0);
const float x2 = x1 - f_x1 * (x1 - x0) / (f_x1 - f_x0);
x0 = x1;
x1 = x2;
}

View File

@ -14,7 +14,6 @@
#include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
#include "BLI_hash_md5.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_path_util.h"
@ -26,6 +25,7 @@
#include <fmt/format.h>
#include <sstream>
#include <xxhash.h>
#ifdef WITH_OPENVDB
# include <openvdb/io/Stream.h>
@ -192,8 +192,7 @@ DictionaryValuePtr BlobWriteSharing::write_implicitly_shared(
std::shared_ptr<io::serialize::DictionaryValue> BlobWriteSharing::write_deduplicated(
BlobWriter &writer, const void *data, const int64_t size_in_bytes)
{
SliceHash content_hash;
BLI_hash_md5_buffer(static_cast<const char *>(data), size_in_bytes, &content_hash);
const uint64_t content_hash = XXH3_64bits(data, size_in_bytes);
const BlobSlice slice = slice_by_content_hash_.lookup_or_add_cb(
content_hash, [&]() { return writer.write(data, size_in_bytes); });
return slice.serialize();

View File

@ -182,7 +182,7 @@ static BlendHandle *link_append_context_library_blohandle_ensure(
lib_context->bf_reports.reports = reports;
}
char *libname = lib_context->path;
const char *libname = lib_context->path;
BlendHandle *blo_handle = lib_context->blo_handle;
if (blo_handle == nullptr) {
if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) {
@ -1410,7 +1410,7 @@ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *re
{
BlendfileLinkAppendContextLibrary *lib_context =
static_cast<BlendfileLinkAppendContextLibrary *>(liblink->link);
char *libname = lib_context->path;
const char *libname = lib_context->path;
BlendHandle *blo_handle = link_append_context_library_blohandle_ensure(
lapp_context, lib_context, reports);

View File

@ -1659,6 +1659,64 @@ static bConstraintTypeInfo CTI_LOCLIMIT = {
/* -------- Limit Rotation --------- */
/**
* Wraps a number to be in [-PI, +PI].
*/
static inline float wrap_rad_angle(const float angle)
{
const float b = angle * (0.5 / M_PI) + 0.5;
return ((b - std::floor(b)) - 0.5) * (2.0 * M_PI);
}
/**
* Clamps an angle between min and max.
*
* All angles are in radians.
*
* This function treats angles as existing in a looping (cyclic) space, and is therefore
* specifically not equivalent to a simple `clamp(angle, min, max)`. `min` and `max` are treated as
* a directed range on the unit circle and `angle` is treated as a point on the unit circle.
* `angle` is then clamped to be within the directed range defined by `min` and `max`.
*/
static float clamp_angle(const float angle, const float min, const float max)
{
/* If the allowed range exceeds 360 degrees no clamping can occur. */
if ((max - min) >= (2 * M_PI)) {
return angle;
}
/* Invalid case, just return min. */
if (max <= min) {
return min;
}
/* Move min and max into a space where `angle == 0.0`, and wrap them to
* [-PI, +PI] in that space. This simplifies the cases below, as we can
* just use 0.0 in place of `angle` and know that everything is in
* [-PI, +PI]. */
const float min_wrapped = wrap_rad_angle(min - angle);
const float max_wrapped = wrap_rad_angle(max - angle);
/* If the range defined by `min`/`max` doesn't contain the boundary at
* PI/-PI. This is the simple case, because it means we can do a simple
* clamp. */
if (min_wrapped < max_wrapped) {
return angle + std::clamp(0.0f, min_wrapped, max_wrapped);
}
/* At this point we know that `min_wrapped` >= `max_wrapped`, meaning the boundary is crossed.
* With that we know that no clamping is needed in the following case. */
if (max_wrapped >= 0.0 || min_wrapped <= 0.0) {
return angle;
}
/* If zero is outside of the range, we clamp to the closest of `min_wrapped` or `max_wrapped`. */
if (std::fabs(max_wrapped) < std::fabs(min_wrapped)) {
return angle + max_wrapped;
}
return angle + min_wrapped;
}
static void rotlimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /*targets*/)
{
bRotLimitConstraint *data = static_cast<bRotLimitConstraint *>(con->data);
@ -1693,31 +1751,13 @@ static void rotlimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * /
/* limiting of euler values... */
if (data->flag & LIMIT_XROT) {
if (eul[0] < data->xmin) {
eul[0] = data->xmin;
}
if (eul[0] > data->xmax) {
eul[0] = data->xmax;
}
eul[0] = clamp_angle(eul[0], data->xmin, data->xmax);
}
if (data->flag & LIMIT_YROT) {
if (eul[1] < data->ymin) {
eul[1] = data->ymin;
}
if (eul[1] > data->ymax) {
eul[1] = data->ymax;
}
eul[1] = clamp_angle(eul[1], data->ymin, data->ymax);
}
if (data->flag & LIMIT_ZROT) {
if (eul[2] < data->zmin) {
eul[2] = data->zmin;
}
if (eul[2] > data->zmax) {
eul[2] = data->zmax;
}
eul[2] = clamp_angle(eul[2], data->zmin, data->zmax);
}
loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);

View File

@ -599,9 +599,9 @@ GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, cons
if (edit_component_eval != nullptr) {
const CurvesEditHints *edit_hints = edit_component_eval->curves_edit_hints_.get();
if (edit_hints != nullptr && &edit_hints->curves_id_orig == &curves_id_orig) {
if (edit_hints->positions.has_value()) {
BLI_assert(edit_hints->positions->size() == points_num);
deformation.positions = *edit_hints->positions;
if (const std::optional<Span<float3>> positions = edit_hints->positions()) {
BLI_assert(positions->size() == points_num);
deformation.positions = *positions;
uses_extra_positions = true;
}
if (edit_hints->deform_mats.has_value()) {
@ -677,8 +677,8 @@ GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object
BLI_assert(edit_hints->drawing_hints->size() == layers_orig.size());
const GreasePencilDrawingEditHints &drawing_hints =
edit_hints->drawing_hints.value()[layer_index];
if (drawing_hints.positions.has_value()) {
deformation.positions = *drawing_hints.positions;
if (const std::optional<Span<float3>> positions = drawing_hints.positions()) {
deformation.positions = *positions;
return deformation;
}
}

View File

@ -4750,7 +4750,6 @@ bool BKE_nurb_valid_message(const int pnts,
NURBSValidationStatus status = nurb_check_valid(
pnts, order, flag, type, is_surf, &points_needed);
const char *msg_template = nullptr;
switch (status) {
case NURBSValidationStatus::Valid:
message_dst[0] = 0;
@ -4761,20 +4760,24 @@ bool BKE_nurb_valid_message(const int pnts,
message_dst[0] = 0;
return false;
}
msg_template = RPT_("At least two points required");
BLI_strncpy(message_dst, RPT_("At least two points required"), maxncpy);
break;
case NURBSValidationStatus::MorePointsThanOrderRequired:
msg_template = RPT_("Must have more control points than Order");
BLI_strncpy(message_dst, RPT_("Must have more control points than Order"), maxncpy);
break;
case NURBSValidationStatus::MoreRowsForBezierRequired:
msg_template = RPT_("%d more %s row(s) needed for Bézier");
BLI_snprintf(message_dst,
maxncpy,
RPT_("%d more %s row(s) needed for Bézier"),
points_needed,
dir == 0 ? "U" : "V");
break;
case NURBSValidationStatus::MorePointsForBezierRequired:
msg_template = RPT_("%d more point(s) needed for Bézier");
BLI_snprintf(
message_dst, maxncpy, RPT_("%d more point(s) needed for Bézier"), points_needed);
break;
}
BLI_snprintf(message_dst, maxncpy, msg_template, points_needed, dir == 0 ? "U" : "V");
return true;
}

View File

@ -333,8 +333,8 @@ CurvesSurfaceTransforms::CurvesSurfaceTransforms(const Object &curves_ob, const
bool CurvesEditHints::is_valid() const
{
const int point_num = this->curves_id_orig.geometry.point_num;
if (this->positions.has_value()) {
if (this->positions->size() != point_num) {
if (this->positions().has_value()) {
if (this->positions()->size() != point_num) {
return false;
}
}
@ -346,6 +346,35 @@ bool CurvesEditHints::is_valid() const
return true;
}
std::optional<Span<float3>> CurvesEditHints::positions() const
{
if (!this->positions_data.has_value()) {
return std::nullopt;
}
const int points_num = this->curves_id_orig.geometry.wrap().points_num();
return Span(static_cast<const float3 *>(this->positions_data.data), points_num);
}
std::optional<MutableSpan<float3>> CurvesEditHints::positions_for_write()
{
if (!this->positions_data.has_value()) {
return std::nullopt;
}
const int points_num = this->curves_id_orig.geometry.wrap().points_num();
ImplicitSharingPtrAndData &data = this->positions_data;
if (data.sharing_info->is_mutable()) {
data.sharing_info->tag_ensured_mutable();
}
else {
auto *new_sharing_info = new ImplicitSharedValue<Array<float3>>(*this->positions());
data.sharing_info = ImplicitSharingPtr<ImplicitSharingInfo>(new_sharing_info);
data.data = new_sharing_info->data.data();
}
return MutableSpan(const_cast<float3 *>(static_cast<const float3 *>(data.data)), points_num);
}
void curves_normals_point_domain_calc(const CurvesGeometry &curves, MutableSpan<float3> normals)
{
const bke::CurvesFieldContext context(curves, AttrDomain::Point);

View File

@ -17,14 +17,18 @@
#include "BKE_editmesh.hh"
#include "BKE_editmesh_cache.hh" /* own include */
using blender::float3;
using blender::Span;
/* -------------------------------------------------------------------- */
/** \name Ensure Data (derived from coords)
* \{ */
void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
Span<float3> BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em,
blender::bke::EditMeshData &emd)
{
if (emd.vert_positions.is_empty() || !emd.face_normals.is_empty()) {
return;
return emd.face_normals;
}
BMesh *bm = em.bm;
@ -36,37 +40,35 @@ void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMe
int i;
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
BM_elem_index_set(efa, i); /* set_inline */
BM_face_calc_normal_vcos(bm,
efa,
emd.face_normals[i],
reinterpret_cast<const float(*)[3]>(emd.vert_positions.data()));
BM_face_calc_normal_vcos(bm, efa, emd.face_normals[i], emd.vert_positions);
}
bm->elem_index_dirty &= ~BM_FACE;
return emd.face_normals;
}
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
Span<float3> BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em,
blender::bke::EditMeshData &emd)
{
if (emd.vert_positions.is_empty() || !emd.vert_normals.is_empty()) {
return;
return emd.vert_normals;
}
BMesh *bm = em.bm;
/* Calculate vertex normals from face normals. */
BKE_editmesh_cache_ensure_face_normals(em, emd);
const Span<float3> face_normals = BKE_editmesh_cache_ensure_face_normals(em, emd);
emd.vert_normals.reinitialize(bm->totvert);
BM_mesh_elem_index_ensure(bm, BM_FACE);
BM_verts_calc_normal_vcos(bm,
reinterpret_cast<const float(*)[3]>(emd.face_normals.data()),
reinterpret_cast<const float(*)[3]>(emd.vert_positions.data()),
reinterpret_cast<float(*)[3]>(emd.vert_normals.data()));
BM_verts_calc_normal_vcos(bm, face_normals, emd.vert_positions, emd.vert_normals);
return emd.vert_normals;
}
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em, blender::bke::EditMeshData &emd)
Span<float3> BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em,
blender::bke::EditMeshData &emd)
{
if (!emd.face_centers.is_empty()) {
return;
return emd.face_centers;
}
BMesh *bm = em.bm;
@ -86,6 +88,7 @@ void BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em, blender::bke::EditMe
BM_face_calc_center_median_vcos(bm, efa, emd.face_centers[i], emd.vert_positions);
}
}
return emd.face_centers;
}
/** \} */

View File

@ -40,25 +40,37 @@ void GeometryComponentEditData::clear()
grease_pencil_edit_hints_.reset();
}
static ImplicitSharingPtrAndData save_shared_attribute(const GAttributeReader &attribute)
{
if (attribute.sharing_info && attribute.varray.is_span()) {
const void *data = attribute.varray.get_internal_span().data();
attribute.sharing_info->add_user();
return {ImplicitSharingPtr(attribute.sharing_info), data};
}
auto *data = new ImplicitSharedValue<GArray<>>(attribute.varray.type(), attribute.varray.size());
attribute.varray.materialize(data->data.data());
return {ImplicitSharingPtr<ImplicitSharingInfo>(data), data->data.data()};
}
static void remember_deformed_curve_positions_if_necessary(
const Curves *curves_id, GeometryComponentEditData &edit_component)
{
if (!edit_component.curves_edit_hints_) {
return;
}
if (edit_component.curves_edit_hints_->positions.has_value()) {
if (curves_id == nullptr) {
return;
}
if (curves_id == nullptr) {
CurvesEditHints &edit_hints = *edit_component.curves_edit_hints_;
if (edit_hints.positions().has_value()) {
return;
}
const CurvesGeometry &curves = curves_id->geometry.wrap();
const int points_num = curves.points_num();
if (points_num != edit_component.curves_edit_hints_->curves_id_orig.geometry.point_num) {
if (points_num != edit_hints.curves_id_orig.geometry.point_num) {
return;
}
edit_component.curves_edit_hints_->positions.emplace(points_num);
edit_component.curves_edit_hints_->positions->as_mutable_span().copy_from(curves.positions());
edit_hints.positions_data = save_shared_attribute(curves.attributes().lookup("position"));
}
static void remember_deformed_grease_pencil_if_necessary(const GreasePencil *grease_pencil,
@ -91,14 +103,15 @@ static void remember_deformed_grease_pencil_if_necessary(const GreasePencil *gre
const greasepencil::Drawing *orig_drawing = orig_grease_pencil.get_drawing_at(
orig_layer, grease_pencil->runtime->eval_frame);
GreasePencilDrawingEditHints &drawing_hints = all_hints[layer_index];
if (!drawing || !orig_drawing) {
continue;
}
if (drawing->strokes().points_num() != orig_drawing->strokes().points_num()) {
drawing_hints.drawing_orig = orig_drawing;
const CurvesGeometry &curves = drawing->strokes();
if (curves.points_num() != orig_drawing->strokes().points_num()) {
continue;
}
drawing_hints.positions.emplace(drawing->strokes().positions());
drawing_hints.positions_data = save_shared_attribute(curves.attributes().lookup("position"));
}
}

View File

@ -42,6 +42,7 @@
#include "BLI_string.h"
#include "BLI_string_ref.hh"
#include "BLI_string_utils.hh"
#include "BLI_utildefines.h"
#include "BLI_vector_set.hh"
#include "BLI_virtual_array.hh"
@ -52,6 +53,7 @@
#include "DNA_ID.h"
#include "DNA_ID_enums.h"
#include "DNA_brush_types.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_material_types.h"
@ -80,10 +82,12 @@ static void grease_pencil_init_data(ID *id)
using namespace blender::bke;
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(id);
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(grease_pencil, id));
MEMCPY_STRUCT_AFTER(grease_pencil, DNA_struct_default_get(GreasePencil), id);
grease_pencil->root_group_ptr = MEM_new<greasepencil::LayerGroup>(__func__);
grease_pencil->active_layer = nullptr;
grease_pencil->flag |= GREASE_PENCIL_ANIM_CHANNEL_EXPANDED;
CustomData_reset(&grease_pencil->layers_data);
@ -578,7 +582,7 @@ void Drawing::set_texture_matrices(Span<float4x2> matrices, const IndexMask &sel
const float4x2 texspace = matrices[pos];
/* We do the computation using doubles to avoid numerical precision errors. */
double4x3 strokemat4x3 = double4x3(expand_4x2_mat(strokemat));
const double4x3 strokemat4x3 = double4x3(expand_4x2_mat(strokemat));
/*
* We want to solve for `texture_matrix` in the equation: `texspace = texture_matrix *
@ -766,7 +770,7 @@ TreeNode::TreeNode()
this->parent = nullptr;
this->GreasePencilLayerTreeNode::name = nullptr;
this->flag = GP_LAYER_TREE_NODE_HIDE_MASKS;
this->flag = 0;
this->color[0] = this->color[1] = this->color[2] = 0;
}
@ -928,7 +932,7 @@ Layer::Layer(const Layer &other) : Layer()
/* Note: We do not duplicate the frame storage since it is only needed for writing to file. */
this->runtime->frames_ = other.runtime->frames_;
this->runtime->sorted_keys_cache_ = other.runtime->sorted_keys_cache_;
/* Tag the frames map, so the frame storage is recreated once the DNA is saved.*/
/* Tag the frames map, so the frame storage is recreated once the DNA is saved. */
this->tag_frames_map_changed();
/* TODO: what about masks cache? */
@ -1570,6 +1574,40 @@ void LayerGroup::update_from_dna_read()
} // namespace blender::bke::greasepencil
namespace blender::bke {
std::optional<Span<float3>> GreasePencilDrawingEditHints::positions() const
{
if (!this->positions_data.has_value()) {
return std::nullopt;
}
const int points_num = this->drawing_orig->geometry.wrap().points_num();
return Span(static_cast<const float3 *>(this->positions_data.data), points_num);
}
std::optional<MutableSpan<float3>> GreasePencilDrawingEditHints::positions_for_write()
{
if (!this->positions_data.has_value()) {
return std::nullopt;
}
const int points_num = this->drawing_orig->geometry.wrap().points_num();
ImplicitSharingPtrAndData &data = this->positions_data;
if (data.sharing_info->is_mutable()) {
/* If the referenced component is already mutable, return it directly. */
data.sharing_info->tag_ensured_mutable();
}
else {
auto *new_sharing_info = new ImplicitSharedValue<Array<float3>>(*this->positions());
data.sharing_info = ImplicitSharingPtr<ImplicitSharingInfo>(new_sharing_info);
data.data = new_sharing_info->data.data();
}
return MutableSpan(const_cast<float3 *>(static_cast<const float3 *>(data.data)), points_num);
}
} // namespace blender::bke
/* ------------------------------------------------------------------- */
/** \name Grease Pencil kernel functions
* \{ */

View File

@ -172,6 +172,10 @@ static void find_used_vertex_groups(const bGPDframe &gpf,
Span<MDeformVert> dverts = {gps->dvert, gps->totpoints};
for (const MDeformVert &dvert : dverts) {
for (const MDeformWeight &weight : Span<MDeformWeight>{dvert.dw, dvert.totweight}) {
if (weight.def_nr >= dvert.totweight) {
/* Ignore invalid deform weight group indices. */
continue;
}
is_group_used[weight.def_nr] = true;
}
}
@ -362,6 +366,10 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
dst_dvert.dw = static_cast<MDeformWeight *>(MEM_dupallocN(src_dvert.dw));
const MutableSpan<MDeformWeight> vertex_weights = {dst_dvert.dw, dst_dvert.totweight};
for (MDeformWeight &weight : vertex_weights) {
if (weight.def_nr >= dst_dvert.totweight) {
/* Ignore invalid deform weight group indices. */
continue;
}
/* Map def_nr to the reduced vertex group list. */
weight.def_nr = stroke_def_nr_map[weight.def_nr];
}
@ -403,7 +411,11 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
SpanAttributeWriter<float> stroke_point_aspect_ratios =
attributes.lookup_or_add_for_write_span<float>("aspect_ratio", AttrDomain::Curve);
SpanAttributeWriter<ColorGeometry4f> stroke_fill_colors =
attributes.lookup_or_add_for_write_span<ColorGeometry4f>("fill_color", AttrDomain::Curve);
attributes.lookup_or_add_for_write_span<ColorGeometry4f>(
"fill_color",
AttrDomain::Curve,
bke::AttributeInitVArray(VArray<ColorGeometry4f>::ForSingle(
ColorGeometry4f(float4(0.0f)), curves.curves_num())));
SpanAttributeWriter<int> stroke_materials = attributes.lookup_or_add_for_write_span<int>(
"material_index", AttrDomain::Curve);
@ -573,8 +585,8 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_USE_LIGHTS), GP_LAYER_TREE_NODE_USE_LIGHTS);
SET_FLAG_FROM_TEST(new_layer.base.flag,
(gpl->onion_flag & GP_LAYER_ONIONSKIN),
GP_LAYER_TREE_NODE_USE_ONION_SKINNING);
(gpl->onion_flag & GP_LAYER_ONIONSKIN) == 0,
GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING);
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_USE_MASK) == 0, GP_LAYER_TREE_NODE_HIDE_MASKS);
@ -638,18 +650,28 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
grease_pencil.vertex_group_active_index = gpd.vertex_group_active_index;
/* Convert the onion skinning settings. */
grease_pencil.onion_skinning_settings.opacity = gpd.onion_factor;
grease_pencil.onion_skinning_settings.mode = gpd.onion_mode;
GreasePencilOnionSkinningSettings &settings = grease_pencil.onion_skinning_settings;
settings.opacity = gpd.onion_factor;
settings.mode = gpd.onion_mode;
SET_FLAG_FROM_TEST(settings.flag,
((gpd.onion_flag & GP_ONION_GHOST_PREVCOL) != 0 &&
(gpd.onion_flag & GP_ONION_GHOST_NEXTCOL) != 0),
GP_ONION_SKINNING_USE_CUSTOM_COLORS);
SET_FLAG_FROM_TEST(
settings.flag, (gpd.onion_flag & GP_ONION_FADE) != 0, GP_ONION_SKINNING_USE_FADE);
SET_FLAG_FROM_TEST(
settings.flag, (gpd.onion_flag & GP_ONION_LOOP) != 0, GP_ONION_SKINNING_SHOW_LOOP);
/* Convert keytype filter to a bit flag. */
if (gpd.onion_keytype == -1) {
grease_pencil.onion_skinning_settings.filter = GREASE_PENCIL_ONION_SKINNING_FILTER_ALL;
settings.filter = GREASE_PENCIL_ONION_SKINNING_FILTER_ALL;
}
else {
grease_pencil.onion_skinning_settings.filter = (1 << gpd.onion_keytype);
settings.filter = (1 << gpd.onion_keytype);
}
grease_pencil.onion_skinning_settings.num_frames_before = gpd.gstep;
grease_pencil.onion_skinning_settings.num_frames_after = gpd.gstep_next;
copy_v3_v3(grease_pencil.onion_skinning_settings.color_before, gpd.gcolor_prev);
copy_v3_v3(grease_pencil.onion_skinning_settings.color_after, gpd.gcolor_next);
settings.num_frames_before = gpd.gstep;
settings.num_frames_after = gpd.gstep_next;
copy_v3_v3(settings.color_before, gpd.gcolor_prev);
copy_v3_v3(settings.color_after, gpd.gcolor_next);
BKE_id_materials_copy(&bmain, &gpd.id, &grease_pencil.id);

View File

@ -622,8 +622,8 @@ void BKE_image_free_old_gputextures(Main *bmain)
/** \name Paint Update
* \{ */
static ImBuf *update_do_scale(uchar *rect,
float *rect_float,
static ImBuf *update_do_scale(const uchar *rect,
const float *rect_float,
int *x,
int *y,
int *w,
@ -662,8 +662,8 @@ static ImBuf *update_do_scale(uchar *rect,
}
static void gpu_texture_update_scaled(GPUTexture *tex,
uchar *rect,
float *rect_float,
const uchar *rect,
const float *rect_float,
int full_w,
int full_h,
int x,

View File

@ -1852,7 +1852,7 @@ void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, List
}
std::optional<std::string> BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle,
ColorBand *color_ramp)
const ColorBand *color_ramp)
{
bool found = false;

View File

@ -340,7 +340,10 @@ void BKE_mask_layer_unique_name(Mask *mask, MaskLayer *masklay)
sizeof(masklay->name));
}
void BKE_mask_layer_rename(Mask *mask, MaskLayer *masklay, char *oldname, char *newname)
void BKE_mask_layer_rename(Mask *mask,
MaskLayer *masklay,
const char *oldname,
const char *newname)
{
STRNCPY(masklay->name, newname);

View File

@ -1158,6 +1158,19 @@ static void polygonize(PROCESS *process)
}
}
static bool object_has_zero_axis_matrix(const Object *bob)
{
if (has_zero_axis_m4(bob->object_to_world().ptr())) {
return true;
}
for (Object *pob = bob->parent; pob; pob = pob->parent) {
if (has_zero_axis_m4(pob->object_to_world().ptr())) {
return true;
}
}
return false;
}
/**
* Iterates over ALL objects in the scene and all of its sets, including
* making all duplis (not only meta-elements). Copies meta-elements to #process.mainb array.
@ -1168,19 +1181,15 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
Scene *sce_iter = scene;
Base *base;
Object *bob;
MetaBall *mb;
const MetaElem *ml;
float obinv[4][4], obmat[4][4];
uint i;
int obnr, zero_size = 0;
int obnr;
char obname[MAX_ID_NAME];
SceneBaseIter iter;
const eEvaluationMode deg_eval_mode = DEG_get_mode(depsgraph);
const short parenting_dupli_transflag = (OB_DUPLIFACES | OB_DUPLIVERTS);
copy_m4_m4(
obmat,
ob->object_to_world().ptr()); /* to cope with duplicators from BKE_scene_base_iter_next */
/* Copy object matrices to cope with duplicators from #BKE_scene_base_iter_next. */
float obinv[4][4], obmat[4][4];
copy_m4_m4(obmat, ob->object_to_world().ptr());
invert_m4_m4(obinv, ob->object_to_world().ptr());
BLI_string_split_name_number(ob->id.name + 2, '.', obname, &obnr);
@ -1188,187 +1197,154 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
/* make main array */
BKE_scene_base_iter_next(depsgraph, &iter, &sce_iter, 0, nullptr, nullptr);
while (BKE_scene_base_iter_next(depsgraph, &iter, &sce_iter, 1, &base, &bob)) {
if (bob->type == OB_MBALL) {
zero_size = 0;
ml = nullptr;
if (bob->type != OB_MBALL) {
continue;
}
/* If this metaball is the original that's used for duplication, only have it visible when
* the instancer is visible too. */
if ((base->flag_legacy & OB_FROMDUPLI) == 0 && ob->parent != nullptr &&
(ob->parent->transflag & parenting_dupli_transflag) != 0 &&
(BKE_object_visibility(ob->parent, deg_eval_mode) & OB_VISIBLE_SELF) == 0)
{
/* If this metaball is the original that's used for duplication, only have it visible when
* the instancer is visible too. */
if ((base->flag_legacy & OB_FROMDUPLI) == 0 && ob->parent != nullptr &&
(ob->parent->transflag & parenting_dupli_transflag) != 0 &&
(BKE_object_visibility(ob->parent, deg_eval_mode) & OB_VISIBLE_SELF) == 0)
{
continue;
}
if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
/* Pass. */
}
else {
char name[MAX_ID_NAME];
int nr;
BLI_string_split_name_number(bob->id.name + 2, '.', name, &nr);
if (!STREQ(obname, name)) {
/* Not part of the mother-ball, continue. */
continue;
}
}
if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
mb = static_cast<MetaBall *>(ob->data);
/* When metaball object has zero scale, then MetaElem to this MetaBall
* will not be put to `mainb` array. */
if (object_has_zero_axis_matrix(bob)) {
continue;
}
if (mb->editelems) {
ml = static_cast<const MetaElem *>(mb->editelems->first);
}
else {
ml = static_cast<const MetaElem *>(mb->elems.first);
}
const MetaBall *mb = static_cast<MetaBall *>(bob->data);
LISTBASE_FOREACH (const MetaElem *, ml, (mb->editelems ? mb->editelems : &mb->elems)) {
if (ml->flag & MB_HIDE) {
continue;
}
float pos[4][4], rot[4][4];
float expx, expy, expz;
blender::float3 tempmin, tempmax;
/* make a copy because of duplicates */
MetaElem *new_ml = static_cast<MetaElem *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem)));
*(new_ml) = *ml;
new_ml->bb = static_cast<BoundBox *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox)));
new_ml->mat = static_cast<float *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(float[4][4])));
new_ml->imat = static_cast<float *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(float[4][4])));
/* too big stiffness seems only ugly due to linear interpolation
* no need to have possibility for too big stiffness */
if (ml->s > 10.0f) {
new_ml->s = 10.0f;
}
else {
char name[MAX_ID_NAME];
int nr;
BLI_string_split_name_number(bob->id.name + 2, '.', name, &nr);
if (STREQ(obname, name)) {
mb = static_cast<MetaBall *>(bob->data);
if (mb->editelems) {
ml = static_cast<const MetaElem *>(mb->editelems->first);
}
else {
ml = static_cast<const MetaElem *>(mb->elems.first);
}
}
new_ml->s = ml->s;
}
/* when metaball object has zero scale, then MetaElem to this MetaBall
* will not be put to mainb array */
if (has_zero_axis_m4(bob->object_to_world().ptr())) {
zero_size = 1;
}
else if (bob->parent) {
Object *pob = bob->parent;
while (pob) {
if (has_zero_axis_m4(pob->object_to_world().ptr())) {
zero_size = 1;
break;
}
pob = pob->parent;
}
/* if metaball is negative, set stiffness negative */
if (new_ml->flag & MB_NEGATIVE) {
new_ml->s = -new_ml->s;
}
if (zero_size) {
while (ml) {
ml = ml->next;
}
/* Translation of MetaElem */
unit_m4(pos);
pos[3][0] = ml->x;
pos[3][1] = ml->y;
pos[3][2] = ml->z;
/* Rotation of MetaElem is stored in quat */
quat_to_mat4(rot, ml->quat);
/* Matrix multiply is as follows:
* basis object space ->
* world ->
* ml object space ->
* position ->
* rotation ->
* ml local space
*/
mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->object_to_world().ptr(), pos, rot);
/* ml local space -> basis object space */
invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat);
/* rad2 is inverse of squared radius */
new_ml->rad2 = 1 / (ml->rad * ml->rad);
/* initial dimensions = radius */
expx = ml->rad;
expy = ml->rad;
expz = ml->rad;
switch (ml->type) {
case MB_BALL:
break;
case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
expz += ml->expz;
ATTR_FALLTHROUGH;
case MB_PLANE: /* plane is "expanded" by expy and expx */
expy += ml->expy;
ATTR_FALLTHROUGH;
case MB_TUBE: /* tube is "expanded" by expx */
expx += ml->expx;
break;
case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */
expx *= ml->expx;
expy *= ml->expy;
expz *= ml->expz;
break;
}
else {
while (ml) {
if (!(ml->flag & MB_HIDE)) {
float pos[4][4], rot[4][4];
float expx, expy, expz;
blender::float3 tempmin, tempmax;
MetaElem *new_ml;
/* untransformed Bounding Box of MetaElem */
/* TODO: its possible the elem type has been changed and the exp*
* values can use a fallback. */
copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */
copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */
copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz); /* 2 */
copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz); /* 3 */
copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz); /* 4 */
copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz); /* 5 */
copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz); /* 6 */
copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz); /* 7 */
/* make a copy because of duplicates */
new_ml = static_cast<MetaElem *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem)));
*(new_ml) = *ml;
new_ml->bb = static_cast<BoundBox *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox)));
new_ml->mat = static_cast<float *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(float[4][4])));
new_ml->imat = static_cast<float *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(float[4][4])));
/* too big stiffness seems only ugly due to linear interpolation
* no need to have possibility for too big stiffness */
if (ml->s > 10.0f) {
new_ml->s = 10.0f;
}
else {
new_ml->s = ml->s;
}
/* if metaball is negative, set stiffness negative */
if (new_ml->flag & MB_NEGATIVE) {
new_ml->s = -new_ml->s;
}
/* Translation of MetaElem */
unit_m4(pos);
pos[3][0] = ml->x;
pos[3][1] = ml->y;
pos[3][2] = ml->z;
/* Rotation of MetaElem is stored in quat */
quat_to_mat4(rot, ml->quat);
/* Matrix multiply is as follows:
* basis object space ->
* world ->
* ml object space ->
* position ->
* rotation ->
* ml local space
*/
mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->object_to_world().ptr(), pos, rot);
/* ml local space -> basis object space */
invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat);
/* rad2 is inverse of squared radius */
new_ml->rad2 = 1 / (ml->rad * ml->rad);
/* initial dimensions = radius */
expx = ml->rad;
expy = ml->rad;
expz = ml->rad;
switch (ml->type) {
case MB_BALL:
break;
case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
expz += ml->expz;
ATTR_FALLTHROUGH;
case MB_PLANE: /* plane is "expanded" by expy and expx */
expy += ml->expy;
ATTR_FALLTHROUGH;
case MB_TUBE: /* tube is "expanded" by expx */
expx += ml->expx;
break;
case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */
expx *= ml->expx;
expy *= ml->expy;
expz *= ml->expz;
break;
}
/* untransformed Bounding Box of MetaElem */
/* TODO: its possible the elem type has been changed and the exp*
* values can use a fallback. */
copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */
copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */
copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz); /* 2 */
copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz); /* 3 */
copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz); /* 4 */
copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz); /* 5 */
copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz); /* 6 */
copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz); /* 7 */
/* Transformation of meta-elem bounding-box. */
for (i = 0; i < 8; i++) {
mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]);
}
/* Find max and min of transformed bounding-box. */
INIT_MINMAX(tempmin, tempmax);
for (i = 0; i < 8; i++) {
blender::math::min_max(blender::float3(new_ml->bb->vec[i]), tempmin, tempmax);
}
/* Set only point 0 and 6 - AABB of meta-elem. */
copy_v3_v3(new_ml->bb->vec[0], tempmin);
copy_v3_v3(new_ml->bb->vec[6], tempmax);
/* add new_ml to mainb[] */
if (UNLIKELY(process->totelem == process->mem)) {
process->mem = process->mem * 2 + 10;
process->mainb = static_cast<MetaElem **>(
MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem));
}
process->mainb[process->totelem++] = new_ml;
}
ml = ml->next;
}
/* Transformation of meta-elem bounding-box. */
for (uint i = 0; i < 8; i++) {
mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]);
}
/* Find max and min of transformed bounding-box. */
INIT_MINMAX(tempmin, tempmax);
for (uint i = 0; i < 8; i++) {
blender::math::min_max(blender::float3(new_ml->bb->vec[i]), tempmin, tempmax);
}
/* Set only point 0 and 6 - AABB of meta-elem. */
copy_v3_v3(new_ml->bb->vec[0], tempmin);
copy_v3_v3(new_ml->bb->vec[6], tempmax);
/* add new_ml to mainb[] */
if (UNLIKELY(process->totelem == process->mem)) {
process->mem = process->mem * 2 + 10;
process->mainb = static_cast<MetaElem **>(
MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem));
}
process->mainb[process->totelem++] = new_ml;
}
}
@ -1376,7 +1352,7 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
if (process->totelem > 0) {
copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]);
copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]);
for (i = 1; i < process->totelem; i++) {
for (uint i = 1; i < process->totelem; i++) {
make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb);
}
}

View File

@ -113,7 +113,6 @@ static void mesh_copy_data(Main *bmain,
mesh_dst->runtime = new blender::bke::MeshRuntime();
mesh_dst->runtime->deformed_only = mesh_src->runtime->deformed_only;
mesh_dst->runtime->wrapper_type = mesh_src->runtime->wrapper_type;
mesh_dst->runtime->wrapper_type_finalize = mesh_src->runtime->wrapper_type_finalize;
mesh_dst->runtime->subsurf_runtime_data = mesh_src->runtime->subsurf_runtime_data;
mesh_dst->runtime->cd_mask_extra = mesh_src->runtime->cd_mask_extra;
/* Copy face dot tags and edge tags, since meshes may be duplicated after a subsurf modifier or

View File

@ -44,16 +44,16 @@ static void reserve_hash_maps(const Mesh &mesh,
edge_maps, [&](EdgeMap &edge_map) { edge_map.reserve(totedge_guess / edge_maps.size()); });
}
static void add_existing_edges_to_hash_maps(Mesh &mesh,
MutableSpan<EdgeMap> edge_maps,
uint32_t parallel_mask)
static void add_existing_edges_to_hash_maps(const Mesh &mesh,
const uint32_t parallel_mask,
MutableSpan<EdgeMap> edge_maps)
{
/* Assume existing edges are valid. */
const Span<int2> edges = mesh.edges();
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
const int task_index = &edge_map - edge_maps.data();
for (const int2 &edge : edges) {
OrderedEdge ordered_edge{edge[0], edge[1]};
const OrderedEdge ordered_edge(edge[0], edge[1]);
/* Only add the edge when it belongs into this map. */
if (task_index == (parallel_mask & edge_hash_2(ordered_edge))) {
edge_map.add_new(ordered_edge, {&edge});
@ -62,27 +62,27 @@ static void add_existing_edges_to_hash_maps(Mesh &mesh,
});
}
static void add_face_edges_to_hash_maps(Mesh &mesh,
MutableSpan<EdgeMap> edge_maps,
uint32_t parallel_mask)
static void add_face_edges_to_hash_maps(const Mesh &mesh,
const uint32_t parallel_mask,
MutableSpan<EdgeMap> edge_maps)
{
const OffsetIndices faces = mesh.faces();
const OffsetIndices<int> faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
const int task_index = &edge_map - edge_maps.data();
for (const int i : faces.index_range()) {
const Span<int> face_verts = corner_verts.slice(faces[i]);
int vert_prev = face_verts.last();
for (const int vert : face_verts) {
for (const int face_i : faces.index_range()) {
const IndexRange face = faces[face_i];
for (const int corner : face) {
const int vert = corner_verts[corner];
const int vert_prev = corner_verts[bke::mesh::face_corner_prev(face, corner)];
/* Can only be the same when the mesh data is invalid. */
if (vert_prev != vert) {
OrderedEdge ordered_edge{vert_prev, vert};
const OrderedEdge ordered_edge(vert_prev, vert);
/* Only add the edge when it belongs into this map. */
if (task_index == (parallel_mask & edge_hash_2(ordered_edge))) {
edge_map.lookup_or_add(ordered_edge, {nullptr});
}
}
vert_prev = vert;
}
}
});
@ -94,16 +94,16 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg
/* All edges are distributed in the hash tables now. They have to be serialized into a single
* array below. To be able to parallelize this, we have to compute edge index offsets for each
* map. */
Array<int> edge_index_offsets(edge_maps.size());
edge_index_offsets[0] = 0;
for (const int i : IndexRange(edge_maps.size() - 1)) {
edge_index_offsets[i + 1] = edge_index_offsets[i] + edge_maps[i].size();
Array<int> edge_sizes(edge_maps.size() + 1);
for (const int i : edge_maps.index_range()) {
edge_sizes[i] = edge_maps[i].size();
}
const OffsetIndices<int> edge_offsets = offset_indices::accumulate_counts_to_offsets(edge_sizes);
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
const int task_index = &edge_map - edge_maps.data();
int new_edge_index = edge_index_offsets[task_index];
int new_edge_index = edge_offsets[task_index].first();
for (EdgeMap::MutableItem item : edge_map.items()) {
int2 &new_edge = new_edges[new_edge_index];
const int2 *orig_edge = item.value.original_edge;
@ -113,8 +113,7 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg
}
else {
/* Initialize new edge. */
new_edge[0] = item.key.v_low;
new_edge[1] = item.key.v_high;
new_edge = int2(item.key.v_low, item.key.v_high);
}
item.value.index = new_edge_index;
new_edge_index++;
@ -131,14 +130,13 @@ static void update_edge_indices_in_face_loops(const OffsetIndices<int> faces,
threading::parallel_for(faces.index_range(), 100, [&](IndexRange range) {
for (const int face_index : range) {
const IndexRange face = faces[face_index];
int prev_corner = face.last();
for (const int next_corner : face) {
const int vert = corner_verts[next_corner];
const int vert_prev = corner_verts[prev_corner];
for (const int corner : face) {
const int vert = corner_verts[corner];
const int vert_prev = corner_verts[bke::mesh::face_corner_next(face, corner)];
int edge_index;
if (vert_prev != vert) {
OrderedEdge ordered_edge{vert_prev, vert};
const OrderedEdge ordered_edge(vert_prev, vert);
/* Double lookup: First find the map that contains the edge, then lookup the edge. */
const EdgeMap &edge_map = edge_maps[parallel_mask & edge_hash_2(ordered_edge)];
edge_index = edge_map.lookup(ordered_edge).index;
@ -149,8 +147,7 @@ static void update_edge_indices_in_face_loops(const OffsetIndices<int> faces,
* #76514. */
edge_index = 0;
}
corner_edges[prev_corner] = edge_index;
prev_corner = next_corner;
corner_edges[corner] = edge_index;
}
}
});
@ -187,21 +184,20 @@ void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, const bool select_new
/* Add all edges. */
if (keep_existing_edges) {
calc_edges::add_existing_edges_to_hash_maps(mesh, edge_maps, parallel_mask);
calc_edges::add_existing_edges_to_hash_maps(mesh, parallel_mask, edge_maps);
}
calc_edges::add_face_edges_to_hash_maps(mesh, edge_maps, parallel_mask);
calc_edges::add_face_edges_to_hash_maps(mesh, parallel_mask, edge_maps);
/* Compute total number of edges. */
int new_totedge = 0;
for (calc_edges::EdgeMap &edge_map : edge_maps) {
for (const calc_edges::EdgeMap &edge_map : edge_maps) {
new_totedge += edge_map.size();
}
/* Create new edges. */
MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.add<int>(".corner_edge", AttrDomain::Corner, AttributeInitConstruct());
MutableSpan<int2> new_edges{
static_cast<int2 *>(MEM_calloc_arrayN(new_totedge, sizeof(int2), __func__)), new_totedge};
MutableSpan<int2> new_edges(MEM_cnew_array<int2>(new_totedge, __func__), new_totedge);
calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges);
calc_edges::update_edge_indices_in_face_loops(
mesh.faces(), mesh.corner_verts(), edge_maps, parallel_mask, mesh.corner_edges_for_write());
@ -219,7 +215,7 @@ void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, const bool select_new
if (select_edge) {
int new_edge_index = 0;
for (const calc_edges::EdgeMap &edge_map : edge_maps) {
for (calc_edges::EdgeMap::Item item : edge_map.items()) {
for (const calc_edges::EdgeMap::Item item : edge_map.items()) {
if (item.value.original_edge == nullptr) {
select_edge.span[new_edge_index] = true;
}

View File

@ -45,8 +45,7 @@ void BKE_mesh_foreach_mapped_vert(
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vert_positions;
blender::Span<blender::float3> vert_normals;
if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_editmesh_cache_ensure_vert_normals(*em, *mesh->runtime->edit_data);
vert_normals = mesh->runtime->edit_data->vert_normals;
vert_normals = BKE_editmesh_cache_ensure_vert_normals(*em, *mesh->runtime->edit_data);
}
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? &vert_normals[i].x : nullptr;
@ -236,18 +235,16 @@ void BKE_mesh_foreach_mapped_face_center(
if (mesh->runtime->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
BMEditMesh *em = mesh->runtime->edit_mesh;
BMesh *bm = em->bm;
blender::Span<blender::float3> face_centers;
blender::Span<blender::float3> face_normals;
BMFace *efa;
BMIter iter;
int i;
BKE_editmesh_cache_ensure_face_centers(*em, *mesh->runtime->edit_data);
face_centers = mesh->runtime->edit_data->face_centers; /* always set */
const Span<float3> face_centers = BKE_editmesh_cache_ensure_face_centers(
*em, *mesh->runtime->edit_data);
Span<float3> face_normals;
if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_editmesh_cache_ensure_face_normals(*em, *mesh->runtime->edit_data);
face_normals = mesh->runtime->edit_data->face_normals; /* maybe nullptr */
face_normals = BKE_editmesh_cache_ensure_face_normals(*em, *mesh->runtime->edit_data);
}
if (!face_normals.is_empty()) {

View File

@ -129,10 +129,6 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
mesh->runtime->is_original_bmesh = false;
}
if (mesh->runtime->wrapper_type_finalize) {
BKE_mesh_wrapper_deferred_finalize_mdata(mesh);
}
mesh->runtime->edit_data.reset();
break;
}
@ -165,8 +161,8 @@ Span<float3> BKE_mesh_wrapper_face_normals(Mesh *mesh)
{
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
BKE_editmesh_cache_ensure_face_normals(*mesh->runtime->edit_mesh, *mesh->runtime->edit_data);
return mesh->runtime->edit_data->face_normals;
return BKE_editmesh_cache_ensure_face_normals(*mesh->runtime->edit_mesh,
*mesh->runtime->edit_data);
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
return mesh->face_normals();
@ -179,10 +175,10 @@ void BKE_mesh_wrapper_tag_positions_changed(Mesh *mesh)
{
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
if (mesh->runtime->edit_data) {
mesh->runtime->edit_data->vert_normals = {};
mesh->runtime->edit_data->face_centers = {};
mesh->runtime->edit_data->face_normals = {};
if (blender::bke::EditMeshData *edit_data = mesh->runtime->edit_data.get()) {
edit_data->vert_normals = {};
edit_data->face_centers = {};
edit_data->face_normals = {};
}
break;
case ME_WRAPPER_TYPE_MDATA:

View File

@ -1804,7 +1804,7 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip,
int clip_flag,
MovieDistortion *distortion,
int cfra,
int *build_sizes,
const int *build_sizes,
int build_count,
bool undistorted)
{
@ -1845,7 +1845,7 @@ void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip,
ImBuf *ibuf,
MovieDistortion *distortion,
int cfra,
int *build_sizes,
const int *build_sizes,
int build_count,
bool undistorted)
{

View File

@ -1455,7 +1455,7 @@ bool BKE_object_modifier_stack_copy(Object *ob_dst,
const int flag_subdata)
{
if ((ob_dst->type == OB_GPENCIL_LEGACY) != (ob_src->type == OB_GPENCIL_LEGACY)) {
BLI_assert_msg(0,
BLI_assert_msg(false,
"Trying to copy a modifier stack between a GPencil object and another type.");
return false;
}
@ -1463,8 +1463,9 @@ bool BKE_object_modifier_stack_copy(Object *ob_dst,
if (!BLI_listbase_is_empty(&ob_dst->modifiers) ||
!BLI_listbase_is_empty(&ob_dst->greasepencil_modifiers))
{
BLI_assert(
!"Trying to copy a modifier stack into an object having a non-empty modifier stack.");
BLI_assert_msg(
false,
"Trying to copy a modifier stack into an object having a non-empty modifier stack.");
return false;
}

View File

@ -544,7 +544,7 @@ bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_t
return true;
}
case ID_GP:
/* Should not be used with grease pencil objects.*/
/* Should not be used with grease pencil objects. */
BLI_assert_unreachable();
break;
default:

View File

@ -444,17 +444,17 @@ static void make_child_duplis(const DupliContext *ctx,
static const Mesh *mesh_data_from_duplicator_object(Object *ob,
BMEditMesh **r_em,
const float (**r_vert_coords)[3],
const float (**r_vert_normals)[3])
Span<float3> *r_vert_coords,
Span<float3> *r_vert_normals)
{
/* Gather mesh info. */
BMEditMesh *em = BKE_editmesh_from_object(ob);
const Mesh *mesh_eval;
*r_em = nullptr;
*r_vert_coords = nullptr;
*r_vert_coords = {};
if (r_vert_normals != nullptr) {
*r_vert_normals = nullptr;
*r_vert_normals = {};
}
/* We do not need any render-specific handling anymore, depsgraph takes care of that. */
@ -473,10 +473,9 @@ static const Mesh *mesh_data_from_duplicator_object(Object *ob,
mesh_eval = nullptr;
if ((emd != nullptr) && !emd->vert_positions.is_empty()) {
*r_vert_coords = reinterpret_cast<const float(*)[3]>(emd->vert_positions.data());
*r_vert_coords = emd->vert_positions;
if (r_vert_normals != nullptr) {
BKE_editmesh_cache_ensure_vert_normals(*em, *emd);
*r_vert_normals = reinterpret_cast<const float(*)[3]>(emd->vert_normals.data());
*r_vert_normals = BKE_editmesh_cache_ensure_vert_normals(*em, *emd);
}
}
}
@ -563,9 +562,9 @@ struct VertexDupliData_EditMesh {
BMEditMesh *em;
/* Can be nullptr. */
const float (*vert_positions_deform)[3];
const float (*vert_normals_deform)[3];
/* Can be empty. */
Span<float3> vert_positions_deform;
Span<float3> vert_normals_deform;
/**
* \note The edit-mesh may assign #DupliObject.orco in cases when a regular mesh wouldn't.
@ -582,8 +581,8 @@ struct VertexDupliData_EditMesh {
* currently this is copied from a `short[3]` normal without division.
* Can be null when \a use_rotation is false.
*/
static void get_duplivert_transform(const float co[3],
const float no[3],
static void get_duplivert_transform(const float3 &co,
const float3 &no,
const bool use_rotation,
const short axis,
const short upflag,
@ -609,8 +608,8 @@ static DupliObject *vertex_dupli(const DupliContext *ctx,
Object *inst_ob,
const float child_imat[4][4],
int index,
const float co[3],
const float no[3],
const float3 &co,
const float3 &no,
const bool use_rotation)
{
/* `obmat` is transform to vertex. */
@ -681,14 +680,13 @@ static void make_child_duplis_verts_from_editmesh(const DupliContext *ctx,
BMIter iter;
int i;
const float(*vert_positions_deform)[3] = vdd->vert_positions_deform;
const float(*vert_normals_deform)[3] = vdd->vert_normals_deform;
const Span<float3> vert_positions_deform = vdd->vert_positions_deform;
const Span<float3> vert_normals_deform = vdd->vert_normals_deform;
BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) {
const float *co, *no;
if (vert_positions_deform != nullptr) {
float3 co, no;
if (!vert_positions_deform.is_empty()) {
co = vert_positions_deform[i];
no = vert_normals_deform ? vert_normals_deform[i] : nullptr;
no = !vert_normals_deform.is_empty() ? vert_normals_deform[i] : float3(0);
}
else {
co = v->co;
@ -709,8 +707,8 @@ static void make_duplis_verts(const DupliContext *ctx)
/* Gather mesh info. */
BMEditMesh *em = nullptr;
const float(*vert_positions_deform)[3] = nullptr;
const float(*vert_normals_deform)[3] = nullptr;
Span<float3> vert_positions_deform;
Span<float3> vert_normals_deform;
const Mesh *mesh_eval = mesh_data_from_duplicator_object(
parent, &em, &vert_positions_deform, use_rotation ? &vert_normals_deform : nullptr);
if (em == nullptr && mesh_eval == nullptr) {
@ -725,7 +723,7 @@ static void make_duplis_verts(const DupliContext *ctx)
vdd.em = em;
vdd.vert_positions_deform = vert_positions_deform;
vdd.vert_normals_deform = vert_normals_deform;
vdd.has_orco = (vert_positions_deform != nullptr);
vdd.has_orco = !vert_positions_deform.is_empty();
make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_editmesh);
}
@ -1080,8 +1078,8 @@ struct FaceDupliData_EditMesh {
bool has_orco, has_uvs;
int cd_loop_uv_offset;
/* Can be nullptr. */
const float (*vert_positions_deform)[3];
/* Can be empty. */
Span<float3> vert_positions_deform;
};
static void get_dupliface_transform_from_coords(Span<float3> coords,
@ -1186,7 +1184,7 @@ static DupliObject *face_dupli_from_editmesh(const DupliContext *ctx,
/* Mesh variables. */
BMFace *f,
const float (*vert_positions_deform)[3])
const Span<float3> vert_positions_deform)
{
const int coords_len = f->len;
Array<float3, 64> coords(coords_len);
@ -1194,7 +1192,7 @@ static DupliObject *face_dupli_from_editmesh(const DupliContext *ctx,
BMLoop *l_first, *l_iter;
int i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
if (vert_positions_deform != nullptr) {
if (!vert_positions_deform.is_empty()) {
do {
copy_v3_v3(coords[i++], vert_positions_deform[BM_elem_index_get(l_iter->v)]);
} while ((l_iter = l_iter->next) != l_first);
@ -1263,9 +1261,9 @@ static void make_child_duplis_faces_from_editmesh(const DupliContext *ctx,
BMIter iter;
const bool use_scale = fdd->params.use_scale;
const float(*vert_positions_deform)[3] = fdd->vert_positions_deform;
const Span<float3> vert_positions_deform = fdd->vert_positions_deform;
BLI_assert((vert_positions_deform == nullptr) || (em->bm->elem_index_dirty & BM_VERT) == 0);
BLI_assert(vert_positions_deform.is_empty() || (em->bm->elem_index_dirty & BM_VERT) == 0);
invert_m4_m4(inst_ob->runtime->world_to_object.ptr(), inst_ob->object_to_world().ptr());
/* Relative transform from parent to child space. */
@ -1296,7 +1294,7 @@ static void make_duplis_faces(const DupliContext *ctx)
/* Gather mesh info. */
BMEditMesh *em = nullptr;
const float(*vert_positions_deform)[3] = nullptr;
Span<float3> vert_positions_deform;
const Mesh *mesh_eval = mesh_data_from_duplicator_object(
parent, &em, &vert_positions_deform, nullptr);
if (em == nullptr && mesh_eval == nullptr) {
@ -1311,7 +1309,7 @@ static void make_duplis_faces(const DupliContext *ctx)
fdd.params = fdd_params;
fdd.em = em;
fdd.vert_positions_deform = vert_positions_deform;
fdd.has_orco = (vert_positions_deform != nullptr);
fdd.has_orco = !vert_positions_deform.is_empty();
fdd.has_uvs = (uv_idx != -1);
fdd.cd_loop_uv_offset = (uv_idx != -1) ?
CustomData_get_n_offset(&em->bm->ldata, CD_PROP_FLOAT2, uv_idx) :

View File

@ -367,7 +367,7 @@ int BKE_packedfile_write_to_file(ReportList *reports,
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
const char *filepath_rel,
PackedFile *pf)
const PackedFile *pf)
{
BLI_stat_t st;
enum ePF_FileCompare ret_val;
@ -880,7 +880,7 @@ void BKE_packedfile_id_unpack(Main *bmain, ID *id, ReportList *reports, enum ePF
}
}
void BKE_packedfile_blend_write(BlendWriter *writer, PackedFile *pf)
void BKE_packedfile_blend_write(BlendWriter *writer, const PackedFile *pf)
{
if (pf == nullptr) {
return;

View File

@ -2287,7 +2287,7 @@ void clip_ray_ortho(
axis_dominant_v3_to_m3(mat, ray_normal);
float a[3], b[3], min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {FLT_MIN, FLT_MIN, FLT_MIN};
/* Compute AABB bounds rotated along ray_normal.*/
/* Compute AABB bounds rotated along ray_normal. */
copy_v3_v3(a, bb_root.min);
copy_v3_v3(b, bb_root.max);
mul_m3_v3(mat, a);

View File

@ -312,7 +312,7 @@ UVVertex *UVEdge::get_other_uv_vertex(const int vertex)
UVVertex *UVIsland::lookup(const UVVertex &vertex)
{
const int vert_index = vertex.vertex;
Vector<UVVertex *> &vertices = uv_vertex_lookup.lookup_or_add_default(vert_index);
const Vector<UVVertex *> &vertices = uv_vertex_lookup.lookup_or_add_default(vert_index);
for (UVVertex *v : vertices) {
if (v->uv == vertex.uv) {
return v;
@ -1033,9 +1033,8 @@ static void reset_extendability_flags(UVIsland &island)
uv_vertex.flags.is_extended = false;
}
}
for (UVBorder border : island.borders) {
for (UVBorderEdge &border_edge : border.edges) {
for (const UVBorder &border : island.borders) {
for (const UVBorderEdge &border_edge : border.edges) {
border_edge.edge->vertices[0]->flags.is_border = true;
border_edge.edge->vertices[1]->flags.is_border = true;
}

View File

@ -1136,13 +1136,12 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
if (sce->nodetree) {
BLO_write_init_id_buffer_from_id(
temp_embedded_id_buffer, &sce->nodetree->id, BLO_write_is_undo(writer));
BLO_write_struct_at_address(writer,
bNodeTree,
sce->nodetree,
BLO_write_get_id_buffer_temp_id(temp_embedded_id_buffer));
ntreeBlendWrite(
writer,
reinterpret_cast<bNodeTree *>(BLO_write_get_id_buffer_temp_id(temp_embedded_id_buffer)));
bNodeTree *temp_nodetree = reinterpret_cast<bNodeTree *>(
BLO_write_get_id_buffer_temp_id(temp_embedded_id_buffer));
/* Set deprecated chunksize for forward compatibility. */
temp_nodetree->chunksize = 256;
BLO_write_struct_at_address(writer, bNodeTree, sce->nodetree, temp_nodetree);
ntreeBlendWrite(writer, temp_nodetree);
}
BKE_color_managed_view_settings_blend_write(writer, &sce->view_settings);

View File

@ -560,7 +560,7 @@ CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
* {(x, y), {x + 1, y}, {x + 1, y + 1}, {x, y + 1}}
*
* The result is stored in normals storage from TLS. */
static void subdiv_ccg_recalc_inner_face_normals(SubdivCCG &subdiv_ccg,
static void subdiv_ccg_recalc_inner_face_normals(const SubdivCCG &subdiv_ccg,
const CCGKey &key,
MutableSpan<float3> face_normals,
const int corner)
@ -590,7 +590,7 @@ static void subdiv_ccg_recalc_inner_face_normals(SubdivCCG &subdiv_ccg,
}
/* Average normals at every grid element, using adjacent faces normals. */
static void subdiv_ccg_average_inner_face_normals(SubdivCCG &subdiv_ccg,
static void subdiv_ccg_average_inner_face_normals(const SubdivCCG &subdiv_ccg,
const CCGKey &key,
const Span<float3> face_normals,
const int corner)
@ -690,7 +690,7 @@ static void average_grid_element_value_v3(float a[3], float b[3])
copy_v3_v3(b, a);
}
static void average_grid_element(SubdivCCG &subdiv_ccg,
static void average_grid_element(const SubdivCCG &subdiv_ccg,
const CCGKey &key,
CCGElem *grid_element_a,
CCGElem *grid_element_b)
@ -744,7 +744,7 @@ static void element_accumulator_mul_fl(GridElementAccumulator &accumulator, cons
accumulator.mask *= f;
}
static void element_accumulator_copy(SubdivCCG &subdiv_ccg,
static void element_accumulator_copy(const SubdivCCG &subdiv_ccg,
const CCGKey &key,
CCGElem &destination,
const GridElementAccumulator &accumulator)
@ -795,7 +795,7 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG &subdiv_ccg,
static void subdiv_ccg_average_grids_boundary(SubdivCCG &subdiv_ccg,
const CCGKey &key,
SubdivCCGAdjacentEdge &adjacent_edge,
const SubdivCCGAdjacentEdge &adjacent_edge,
MutableSpan<GridElementAccumulator> accumulators)
{
const int num_adjacent_faces = adjacent_edge.num_adjacent_faces;
@ -837,7 +837,7 @@ struct AverageGridsCornerData {
static void subdiv_ccg_average_grids_corners(SubdivCCG &subdiv_ccg,
const CCGKey &key,
SubdivCCGAdjacentVertex &adjacent_vertex)
const SubdivCCGAdjacentVertex &adjacent_vertex)
{
const int num_adjacent_faces = adjacent_vertex.num_adjacent_faces;
if (num_adjacent_faces == 1) {
@ -871,7 +871,7 @@ static void subdiv_ccg_average_boundaries(SubdivCCG &subdiv_ccg,
adjacent_edge_mask.foreach_segment(GrainSize(1024), [&](const IndexMaskSegment segment) {
MutableSpan<GridElementAccumulator> accumulators = all_accumulators.local();
for (const int i : segment) {
SubdivCCGAdjacentEdge &adjacent_edge = subdiv_ccg.adjacent_edges[i];
const SubdivCCGAdjacentEdge &adjacent_edge = subdiv_ccg.adjacent_edges[i];
subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, accumulators);
}
});
@ -883,7 +883,7 @@ static void subdiv_ccg_average_corners(SubdivCCG &subdiv_ccg,
{
using namespace blender;
adjacent_vert_mask.foreach_index(GrainSize(1024), [&](const int i) {
SubdivCCGAdjacentVertex &adjacent_vert = subdiv_ccg.adjacent_verts[i];
const SubdivCCGAdjacentVertex &adjacent_vert = subdiv_ccg.adjacent_verts[i];
subdiv_ccg_average_grids_corners(subdiv_ccg, key, adjacent_vert);
});
}
@ -1004,15 +1004,8 @@ BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors &neighbors,
const int num_duplicates)
{
const int size = num_unique + num_duplicates;
neighbors.size = size;
neighbors.coords.reinitialize(size);
neighbors.num_duplicates = num_duplicates;
if (size < ARRAY_SIZE(neighbors.coords_fixed)) {
neighbors.coords = neighbors.coords_fixed;
}
else {
neighbors.coords = static_cast<SubdivCCGCoord *>(
MEM_mallocN(sizeof(*neighbors.coords) * size, "SubdivCCGNeighbors.coords"));
}
}
/* Check whether given coordinate belongs to a grid corner. */
@ -1520,7 +1513,7 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg,
}
#ifndef NDEBUG
for (int i = 0; i < r_neighbors.size; i++) {
for (const int i : r_neighbors.coords.index_range()) {
BLI_assert(BKE_subdiv_ccg_check_coord_valid(subdiv_ccg, r_neighbors.coords[i]));
}
#endif

View File

@ -673,10 +673,10 @@ void txt_clean_text(Text *text)
}
}
int txt_get_span(TextLine *from, const TextLine *to)
int txt_get_span(const TextLine *from, const TextLine *to)
{
int ret = 0;
TextLine *tmp = from;
const TextLine *tmp = from;
if (!to || !from) {
return 0;

View File

@ -2158,7 +2158,7 @@ void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking * /*trackin
return;
}
if (cameras[a].framenr != framenr && a < reconstruction->camnr - 1) {
if ((a < reconstruction->camnr - 1) && (cameras[a].framenr != framenr)) {
float t = (float(framenr) - cameras[a].framenr) /
(cameras[a + 1].framenr - cameras[a].framenr);
blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t);

View File

@ -806,8 +806,9 @@ bool BKE_undosys_step_load_data_ex(UndoStack *ustack,
}
}
BLI_assert(
!"This should never be reached, either undo stack is corrupted, or code above is buggy");
BLI_assert_msg(
false,
"This should never be reached, either undo stack is corrupted, or code above is buggy");
return false;
}

View File

@ -420,15 +420,16 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const ImBuf *image)
/* Copy the Blender pixels into the FFMPEG data-structure, taking care of endianness and flipping
* the image vertically. */
int linesize = rgb_frame->linesize[0];
int linesize_src = rgb_frame->width * 4;
for (int y = 0; y < height; y++) {
uint8_t *target = rgb_frame->data[0] + linesize * (height - y - 1);
const uint8_t *src = pixels + linesize * y;
const uint8_t *src = pixels + linesize_src * y;
# if ENDIAN_ORDER == L_ENDIAN
memcpy(target, src, linesize);
memcpy(target, src, linesize_src);
# elif ENDIAN_ORDER == B_ENDIAN
const uint8_t *end = src + linesize;
const uint8_t *end = src + linesize_src;
while (src != end) {
target[3] = src[0];
target[2] = src[1];

View File

@ -27,7 +27,7 @@ BArrayStore *BLI_array_store_at_size_get(struct BArrayStore_AtSize *bs_stride, i
void BLI_array_store_at_size_clear(struct BArrayStore_AtSize *bs_stride);
void BLI_array_store_at_size_calc_memory_usage(struct BArrayStore_AtSize *bs_stride,
void BLI_array_store_at_size_calc_memory_usage(const struct BArrayStore_AtSize *bs_stride,
size_t *r_size_expanded,
size_t *r_size_compacted);

View File

@ -13,6 +13,8 @@
#include "BLI_assert.h"
#include "BLI_utility_mixins.hh"
#include "MEM_guardedalloc.h"
namespace blender {
/**
@ -199,6 +201,30 @@ class ImplicitSharingMixin : public ImplicitSharingInfo {
virtual void delete_self() = 0;
};
/**
* Utility for creating an allocated shared resource, to be used like:
* `new ImplicitSharedValue<T>(args);`
*/
template<typename T> class ImplicitSharedValue : public ImplicitSharingInfo {
public:
T data;
template<typename... Args>
ImplicitSharedValue(Args &&...args) : data(std::forward<Args>(args)...)
{
}
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("ImplicitSharedValue");
#endif
private:
void delete_self_with_data() override
{
delete this;
}
};
/**
* Utility that contains sharing information and the data that is shared.
*/

View File

@ -8,6 +8,9 @@
* \ingroup bli
*/
#include <memory>
#include <utility>
#include "BLI_implicit_sharing.hh"
#include "BLI_struct_equality_utils.hh"
@ -132,4 +135,64 @@ template<typename T> class ImplicitSharingPtr {
}
};
/**
* Utility struct to allow used #ImplicitSharingPtr when it's necessary to type-erase the backing
* storage for user-exposed data. For example, #blender::Vector, or #std::vector might be used to
* store an implicitly shared array that is only accessed with #Span or #MutableSpan.
*
* This class handles RAII for the sharing info and the exposed data pointer.
* Retrieving the data with write access and type safety must be handled elsewhere.
*/
class ImplicitSharingPtrAndData {
public:
ImplicitSharingPtr<ImplicitSharingInfo> sharing_info;
const void *data = nullptr;
ImplicitSharingPtrAndData() = default;
ImplicitSharingPtrAndData(ImplicitSharingPtr<ImplicitSharingInfo> sharing_info, const void *data)
: sharing_info(std::move(sharing_info)), data(data)
{
}
ImplicitSharingPtrAndData(const ImplicitSharingPtrAndData &other)
: sharing_info(other.sharing_info), data(other.data)
{
}
ImplicitSharingPtrAndData(ImplicitSharingPtrAndData &&other)
: sharing_info(std::move(other.sharing_info)), data(std::exchange(other.data, nullptr))
{
}
ImplicitSharingPtrAndData &operator=(const ImplicitSharingPtrAndData &other)
{
if (this == &other) {
return *this;
}
std::destroy_at(this);
new (this) ImplicitSharingPtrAndData(other);
return *this;
}
ImplicitSharingPtrAndData &operator=(ImplicitSharingPtrAndData &&other)
{
if (this == &other) {
return *this;
}
std::destroy_at(this);
new (this) ImplicitSharingPtrAndData(std::move(other));
return *this;
}
~ImplicitSharingPtrAndData()
{
this->data = nullptr;
}
bool has_value() const
{
return this->sharing_info.has_value();
}
};
} // namespace blender

View File

@ -45,6 +45,10 @@ extern "C" {
#define BLI_STR_UTF8_DOWNWARDS_ARROW "\xe2\x86\x93"
/** u21E7: `⇧` */
#define BLI_STR_UTF8_UPWARDS_WHITE_ARROW "\xe2\x87\xa7"
/** u21FF: `⇪` For caps lock */
#define BLI_STR_UTF8_UPWARDS_UP_ARROW_FROM_BAR "\xe2\x87\xaa"
/** u2277: `≷` Greater than / Less than */
#define BLI_STR_UTF8_GREATER_THAN_OR_LESS_THAN "\xe2\x89\xb7"
/** u2303: `⌃` */
#define BLI_STR_UTF8_UP_ARROWHEAD "\xe2\x8c\x83"
/** u2318: `⌘` */
@ -67,12 +71,22 @@ extern "C" {
#define BLI_STR_UTF8_BLACK_SQUARE_FOR_STOP "\xe2\x8f\xb9"
/** u2423: `␣` */
#define BLI_STR_UTF8_OPEN_BOX "\xe2\x90\xa3"
/** u25A6: `▦` */
#define BLI_STR_UTF8_SQUARE_WITH_ORTHOGONAL_CROSSHATCH "\xe2\x96\xa6"
/** u25B8: `▸` */
#define BLI_STR_UTF8_BLACK_RIGHT_POINTING_SMALL_TRIANGLE "\xe2\x96\xb8"
/** u2B7E: `⭾` */
#define BLI_STR_UTF8_HORIZONTAL_TAB_KEY "\xe2\xad\xbe"
/** u270E: `✎` Tablet Pen */
#define BLI_STR_UTF8_LOWER_RIGHT_PENCIL "\xe2\x9c\x8e"
/** u2710: `✐` Tablet Eraser */
#define BLI_STR_UTF8_UPPER_RIGHT_PENCIL "\xe2\x9c\x90"
/** u2756: `❖` */
#define BLI_STR_UTF8_BLACK_DIAMOND_MINUS_WHITE_X "\xe2\x9d\x96"
/** u29BE: `⦾` Use for 3D Mice */
#define BLI_STR_UTF8_CIRCLED_WHITE_BULLET "\xe2\xa6\xbe"
/** u2B2E: `⬮` Generic Mouse */
#define BLI_STR_UTF8_BLACK_VERTICAL_ELLIPSE "\xe2\xac\xae"
#ifdef __cplusplus
}

View File

@ -401,6 +401,7 @@ set(SRC
set(LIB
PUBLIC bf::dna
PRIVATE bf::extern::fmtlib
PRIVATE bf::extern::xxhash
bf_intern_eigen
PRIVATE bf::intern::guardedalloc
extern_wcwidth

View File

@ -59,14 +59,14 @@ void BLI_array_store_at_size_clear(BArrayStore_AtSize *bs_stride)
bs_stride->stride_table_len = 0;
}
void BLI_array_store_at_size_calc_memory_usage(BArrayStore_AtSize *bs_stride,
void BLI_array_store_at_size_calc_memory_usage(const BArrayStore_AtSize *bs_stride,
size_t *r_size_expanded,
size_t *r_size_compacted)
{
size_t size_compacted = 0;
size_t size_expanded = 0;
for (int i = 0; i < bs_stride->stride_table_len; i++) {
BArrayStore *bs = bs_stride->stride_table[i];
const BArrayStore *bs = bs_stride->stride_table[i];
if (bs) {
size_compacted += BLI_array_store_calc_size_compacted_get(bs);
size_expanded += BLI_array_store_calc_size_expanded_get(bs);

View File

@ -3,8 +3,9 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_compute_context.hh"
#include "BLI_hash_md5.hh"
#include <sstream>
#include <xxhash.h>
namespace blender {
@ -15,7 +16,9 @@ void ComputeContextHash::mix_in(const void *data, int64_t len)
memcpy(buffer, this, HashSizeInBytes);
memcpy(buffer + HashSizeInBytes, data, len);
BLI_hash_md5_buffer(buffer, HashSizeInBytes + len, this);
const XXH128_hash_t hash = XXH3_128bits(buffer, len);
memcpy(this, &hash, sizeof(hash));
static_assert(sizeof(ComputeContextHash) == sizeof(hash));
}
std::ostream &operator<<(std::ostream &stream, const ComputeContextHash &hash)

View File

@ -128,7 +128,7 @@ static int convexhull_2d_sorted(const float (*points)[2], const int points_num,
i = minmax;
while (++i <= maxmin) {
/* The lower line joins `points[minmin]` with `points[maxmin]`. */
if (is_left(points[minmin], points[maxmin], points[i]) >= 0 && i < maxmin) {
if ((i < maxmin) && (is_left(points[minmin], points[maxmin], points[i]) >= 0)) {
continue; /* Ignore `points[i]` above or on the lower line. */
}
@ -152,7 +152,7 @@ static int convexhull_2d_sorted(const float (*points)[2], const int points_num,
i = maxmin;
while (--i >= minmax) {
/* The upper line joins `points[maxmax]` with `points[minmax]`. */
if (is_left(points[maxmax], points[minmax], points[i]) >= 0 && i > minmax) {
if ((i > minmax) && (is_left(points[maxmax], points[minmax], points[i]) >= 0)) {
continue; /* Ignore points[i] below or on the upper line. */
}

View File

@ -2674,7 +2674,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3],
/* clamp to [0, 1] */
CLAMP(t0, 0.0f, 1.0f);
CLAMP(t1, 0.0f, 1.0f);
// CLAMP(t1, 0.0f, 1.0f); /* UNUSED. */
/*---test inside of tri---*/
/* plane intersection point */

View File

@ -784,6 +784,7 @@ void BLI_ewa_filter(const int width,
BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
if ((b2 = b * b) < rmin) {
if ((a2 = a * a) < rmin) {
UNUSED_VARS(a2, b2);
B = 0.0f;
A = C = rmin;
F = A * C;

View File

@ -2705,7 +2705,7 @@ static bool raycast_test_remove(BoolOpType op, Array<int> &winding, int shape, b
}
/** Add triangle a flipped version of tri to out_faces. */
static void raycast_add_flipped(Vector<Face *> &out_faces, Face &tri, IMeshArena *arena)
static void raycast_add_flipped(Vector<Face *> &out_faces, const Face &tri, IMeshArena *arena)
{
Array<const Vert *> flipped_vs = {tri[0], tri[2], tri[1]};

View File

@ -11,6 +11,7 @@
# include <algorithm>
# include <fstream>
# include <functional>
# include <iostream>
# include <memory>
@ -945,7 +946,7 @@ class CoplanarClusterInfo {
return tri_cluster_[t];
}
int add_cluster(CoplanarCluster cl)
int add_cluster(const CoplanarCluster &cl)
{
int c_index = clusters_.append_and_get_index(cl);
for (int t : cl) {

View File

@ -39,7 +39,7 @@ typedef struct PolyFill {
uint edges, verts;
float min_xy[2], max_xy[2];
ushort nr;
bool f;
uchar f;
} PolyFill;
typedef struct ScanFillVertLink {
@ -52,19 +52,19 @@ typedef struct ScanFillVertLink {
#define SF_EPSILON 0.00003f
#define SF_EPSILON_SQ (SF_EPSILON * SF_EPSILON)
/** #ScanFillVert.status */
/** #ScanFillVert::f (status) */
#define SF_VERT_NEW 0 /* all new verts have this flag set */
#define SF_VERT_AVAILABLE 1 /* available - in an edge */
#define SF_VERT_ZERO_LEN 2
/** #ScanFillEdge.status */
/** #ScanFillEdge::f (status) */
/* Optionally set ScanFillEdge f to this to mark original boundary edges.
* Only needed if there are internal diagonal edges passed to BLI_scanfill_calc. */
#define SF_EDGE_NEW 0 /* all new edges have this flag set */
// #define SF_EDGE_BOUNDARY 1 /* UNUSED */
#define SF_EDGE_INTERNAL 2 /* edge is created while scan-filling */
/** #PolyFill.status */
/** #PolyFill::f (status) */
#define SF_POLY_NEW 0 /* all polys initialized to this */
#define SF_POLY_VALID 1 /* has at least 3 verts */
@ -348,7 +348,7 @@ static ScanFillVertLink *addedgetoscanlist(ScanFillVertLink *scdata, ScanFillEdg
/**
* Return true if `eve` inside the bound-box of `eed`.
*/
static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve)
static bool boundinsideEV(const ScanFillEdge *eed, const ScanFillVert *eve)
{
float minx, maxx, miny, maxy;

View File

@ -126,7 +126,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
LinkNode *name = names;
for (; name; name = name->next) {
char *str_name = (char *)name->link;
const char *str_name = (const char *)name->link;
if (id->name[2] == str_name[0] && STREQ(str_name, id->name + 2)) {
break;
}

View File

@ -1335,8 +1335,9 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (relation->parentid == 0) {
BLI_assert(
!"Found a valid parent for workspace data relation, but no valid parent id.");
BLI_assert_msg(
false,
"Found a valid parent for workspace data relation, but no valid parent id.");
}
}
if (relation->parentid == 0) {

View File

@ -2967,7 +2967,7 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 21)) {
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
/* The `sculpt_flag` was used to store the `BRUSH_DIR_IN`
* With the fix for #115313 this is now just using the `brush->flag`.*/
* With the fix for #115313 this is now just using the `brush->flag`. */
if (brush->gpencil_settings && (brush->gpencil_settings->sculpt_flag & BRUSH_DIR_IN) != 0) {
brush->flag |= BRUSH_DIR_IN;
}

View File

@ -14,6 +14,7 @@
#include "DNA_scene_types.h"
#include "BLI_array.hh"
#include "BLI_bitmap.h"
#include "BLI_linklist_stack.h"
#include "BLI_math_base.hh"
@ -29,15 +30,18 @@
#include "intern/bmesh_private.hh"
using blender::Array;
using blender::float3;
using blender::MutableSpan;
using blender::Span;
/* Smooth angle to use when tagging edges is disabled entirely. */
#define EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS -FLT_MAX
static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
static void bm_edge_tag_from_smooth_and_set_sharp(Span<float3> fnos,
BMEdge *e,
const float split_angle_cos);
static void bm_edge_tag_from_smooth(const float (*fnos)[3],
BMEdge *e,
const float split_angle_cos);
static void bm_edge_tag_from_smooth(Span<float3> fnos, BMEdge *e, const float split_angle_cos);
/* -------------------------------------------------------------------- */
/** \name Update Vertex & Face Normals
@ -53,11 +57,11 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3],
struct BMVertsCalcNormalsWithCoordsData {
/* Read-only data. */
const float (*fnos)[3];
const float (*vcos)[3];
Span<float3> fnos;
Span<float3> vcos;
/* Write data. */
float (*vnos)[3];
MutableSpan<float3> vnos;
};
BLI_INLINE void bm_vert_calc_normals_accum_loop(const BMLoop *l_iter,
@ -204,21 +208,21 @@ static void bm_vert_calc_normals_with_coords_cb(void *userdata,
}
static void bm_mesh_verts_calc_normals(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
float (*vnos)[3])
const Span<float3> fnos,
const Span<float3> vcos,
MutableSpan<float3> vnos)
{
BM_mesh_elem_index_ensure(bm, BM_FACE | ((vnos || vcos) ? BM_VERT : 0));
BM_mesh_elem_index_ensure(bm, BM_FACE | ((!vnos.is_empty() || !vcos.is_empty()) ? BM_VERT : 0));
TaskParallelSettings settings;
BLI_parallel_mempool_settings_defaults(&settings);
settings.use_threading = bm->totvert >= BM_THREAD_LIMIT;
if (vcos == nullptr) {
if (vcos.is_empty()) {
BM_iter_parallel(bm, BM_VERTS_OF_MESH, bm_vert_calc_normals_cb, nullptr, &settings);
}
else {
BLI_assert(!ELEM(nullptr, fnos, vnos));
BLI_assert(!fnos.is_empty() || !vnos.is_empty());
BMVertsCalcNormalsWithCoordsData data{};
data.fnos = fnos;
data.vcos = vcos;
@ -248,7 +252,7 @@ void BM_mesh_normals_update_ex(BMesh *bm, const BMeshNormalsUpdate_Params *param
}
/* Add weighted face normals to vertices, and normalize vert normals. */
bm_mesh_verts_calc_normals(bm, nullptr, nullptr, nullptr);
bm_mesh_verts_calc_normals(bm, {}, {}, {});
}
void BM_mesh_normals_update(BMesh *bm)
@ -321,9 +325,9 @@ void BM_mesh_normals_update_with_partial(BMesh *bm, const BMPartialUpdate *bmpin
* \{ */
void BM_verts_calc_normal_vcos(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
float (*vnos)[3])
const Span<float3> fnos,
const Span<float3> vcos,
MutableSpan<float3> vnos)
{
/* Add weighted face normals to vertices, and normalize vert normals. */
bm_mesh_verts_calc_normals(bm, fnos, vcos, vnos);
@ -374,7 +378,7 @@ void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges)
* Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normal_vcos
*/
static void bm_mesh_edges_sharp_tag(BMesh *bm,
const float (*fnos)[3],
const Span<float3> fnos,
float split_angle_cos,
const bool do_sharp_edges_tag)
{
@ -382,7 +386,7 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm,
BMEdge *e;
int i;
if (fnos) {
if (!fnos.is_empty()) {
BM_mesh_elem_index_ensure(bm, BM_FACE);
}
@ -413,7 +417,7 @@ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
return;
}
bm_mesh_edges_sharp_tag(bm, nullptr, cosf(split_angle), true);
bm_mesh_edges_sharp_tag(bm, {}, cosf(split_angle), true);
}
/** \} */
@ -467,8 +471,8 @@ bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
* \return The number of loops that were handled (for early exit when all have been handled).
*/
static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
const bool has_clnors,
@ -477,12 +481,12 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
/* Iterate. */
BMLoop *l_curr,
/* Result. */
float (*r_lnos)[3],
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr)
{
BLI_assert((bm->elem_index_dirty & BM_LOOP) == 0);
BLI_assert((fnos == nullptr) || ((bm->elem_index_dirty & BM_FACE) == 0));
BLI_assert((vcos == nullptr) || ((bm->elem_index_dirty & BM_VERT) == 0));
BLI_assert(fnos.is_empty() || ((bm->elem_index_dirty & BM_FACE) == 0));
BLI_assert(vcos.is_empty() || ((bm->elem_index_dirty & BM_VERT) == 0));
UNUSED_VARS_NDEBUG(bm);
int handled = 0;
@ -514,7 +518,8 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
* this vertex just takes its face normal.
*/
const int l_curr_index = BM_elem_index_get(l_curr);
const float *no = fnos ? fnos[BM_elem_index_get(l_curr->f)] : l_curr->f->no;
const float3 no = !fnos.is_empty() ? fnos[BM_elem_index_get(l_curr->f)] :
float3(l_curr->f->no);
copy_v3_v3(r_lnos[l_curr_index], no);
/* If needed, generate this (simple!) lnor space. */
@ -524,11 +529,12 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
{
const BMVert *v_pivot = l_curr->v;
const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
const float3 co_pivot = !vcos.is_empty() ? vcos[BM_elem_index_get(v_pivot)] :
float3(v_pivot->co);
const BMVert *v_1 = l_curr->next->v;
const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co;
const float3 co_1 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_1)] : float3(v_1->co);
const BMVert *v_2 = l_curr->prev->v;
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
const float3 co_2 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_2)] : float3(v_2->co);
BLI_assert(v_1 == BM_edge_other_vert(l_curr->e, v_pivot));
BLI_assert(v_2 == BM_edge_other_vert(l_curr->prev->e, v_pivot));
@ -586,7 +592,8 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
int clnors_count = 0;
bool clnors_invalid = false;
const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
const float3 co_pivot = !vcos.is_empty() ? vcos[BM_elem_index_get(v_pivot)] :
float3(v_pivot->co);
MLoopNorSpace *lnor_space = r_lnors_spacearr ? BKE_lnor_space_create(r_lnors_spacearr) :
nullptr;
@ -601,7 +608,7 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
* then we can just reuse old current one! */
{
const BMVert *v_2 = lfan_pivot->next->v;
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
const float3 co_2 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_2)] : float3(v_2->co);
BLI_assert(v_2 == BM_edge_other_vert(e_next, v_pivot));
@ -633,7 +640,7 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
*/
{
const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
const float3 co_2 = !vcos.is_empty() ? vcos[BM_elem_index_get(v_2)] : float3(v_2->co);
sub_v3_v3v3(vec_next, co_2, co_pivot);
normalize_v3(vec_next);
@ -644,7 +651,7 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
/* Calculate angle between the two face edges incident on this vertex. */
const BMFace *f = lfan_pivot->f;
const float fac = blender::math::safe_acos_approx(dot_v3v3(vec_next, vec_curr));
const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no;
const float3 no = !fnos.is_empty() ? fnos[BM_elem_index_get(f)] : float3(f->no);
/* Accumulate */
madd_v3_v3fl(lnor, no, fac);
@ -795,16 +802,18 @@ BLI_INLINE bool bm_edge_is_smooth_no_angle_test(const BMEdge *e,
BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH));
}
static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const float split_angle_cos)
static void bm_edge_tag_from_smooth(const Span<float3> fnos,
BMEdge *e,
const float split_angle_cos)
{
BLI_assert(e->l != nullptr);
BMLoop *l_a = e->l, *l_b = l_a->radial_next;
bool is_smooth = false;
if (bm_edge_is_smooth_no_angle_test(e, l_a, l_b)) {
if (split_angle_cos != -1.0f) {
const float dot = (fnos == nullptr) ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
const float dot = fnos.is_empty() ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
if (dot >= split_angle_cos) {
is_smooth = true;
}
@ -834,7 +843,7 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const flo
* \note This doesn't have the same atomic requirement as #bm_edge_tag_from_smooth
* since it isn't run from multiple threads at once.
*/
static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
static void bm_edge_tag_from_smooth_and_set_sharp(const Span<float3> fnos,
BMEdge *e,
const float split_angle_cos)
{
@ -843,9 +852,9 @@ static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
bool is_smooth = false;
if (bm_edge_is_smooth_no_angle_test(e, l_a, l_b)) {
if (split_angle_cos != -1.0f) {
const float dot = (fnos == nullptr) ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
const float dot = fnos.is_empty() ? dot_v3v3(l_a->f->no, l_b->f->no) :
dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
fnos[BM_elem_index_get(l_b->f)]);
if (dot >= split_angle_cos) {
is_smooth = true;
}
@ -871,9 +880,9 @@ static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
*/
static void bm_mesh_loops_calc_normals_for_vert_with_clnors(
BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
const bool do_rebuild,
@ -993,9 +1002,9 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(
*/
static void bm_mesh_loops_calc_normals_for_vert_without_clnors(
BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
const bool do_rebuild,
const float split_angle_cos,
/* TLS */
@ -1070,9 +1079,9 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors(
* we could add a low-level API flag for this, see #BM_ELEM_API_FLAG_ENABLE and friends.
*/
static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1091,7 +1100,7 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
{
char htype = 0;
if (vcos) {
if (!vcos.is_empty()) {
htype |= BM_VERT;
}
/* Face/Loop indices are set inline below. */
@ -1164,8 +1173,8 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
struct BMLoopsCalcNormalsWithCoordsData {
/* Read-only data. */
const float (*fnos)[3];
const float (*vcos)[3];
Span<float3> vcos;
Span<float3> fnos;
BMesh *bm;
const short (*clnors_data)[2];
int cd_loop_clnors_offset;
@ -1173,7 +1182,7 @@ struct BMLoopsCalcNormalsWithCoordsData {
float split_angle_cos;
/* Output. */
float (*r_lnos)[3];
MutableSpan<float3> r_lnos;
MLoopNorSpaceArray *r_lnors_spacearr;
};
@ -1272,9 +1281,9 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors_fn(
}
static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1286,10 +1295,10 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm,
{
char htype = BM_LOOP;
if (vcos) {
if (!vcos.is_empty()) {
htype |= BM_VERT;
}
if (fnos) {
if (!fnos.is_empty()) {
htype |= BM_FACE;
}
/* Face/Loop indices are set inline below. */
@ -1347,9 +1356,9 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm,
}
static void bm_mesh_loops_calc_normals(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
float (*r_lnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
const short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1572,8 +1581,8 @@ static void bm_mesh_loops_assign_normal_data(BMesh *bm,
* instead, depending on the do_split_fans parameter.
*/
static void bm_mesh_loops_custom_normals_set(BMesh *bm,
const float (*vcos)[3],
const float (*fnos)[3],
const Span<float3> vcos,
const Span<float3> fnos,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*r_clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1584,8 +1593,7 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm,
BMFace *f;
BMLoop *l;
BMIter liter, fiter;
float(*cur_lnors)[3] = static_cast<float(*)[3]>(
MEM_mallocN(sizeof(*cur_lnors) * bm->totloop, __func__));
Array<float3> cur_lnors(bm->totloop);
BKE_lnor_spacearr_clear(r_lnors_spacearr);
@ -1653,27 +1661,25 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm,
bm_mesh_loops_assign_normal_data(
bm, r_lnors_spacearr, r_clnors_data, cd_loop_clnors_offset, custom_lnors);
MEM_freeN(cur_lnors);
if (custom_lnors != new_lnors) {
MEM_freeN(custom_lnors);
}
}
static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
const float (*vnos)[3],
const float (*fnos)[3],
float (*r_lnos)[3])
const Span<float3> vnos,
const Span<float3> fnos,
MutableSpan<float3> r_lnos)
{
BMIter fiter;
BMFace *f_curr;
{
char htype = BM_LOOP;
if (vnos) {
if (!vnos.is_empty()) {
htype |= BM_VERT;
}
if (fnos) {
if (!fnos.is_empty()) {
htype |= BM_FACE;
}
BM_mesh_elem_index_ensure(bm, htype);
@ -1685,8 +1691,10 @@ static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
do {
const float *no = is_face_flat ? (fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no) :
(vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no);
const float3 no = is_face_flat ? (!fnos.is_empty() ? fnos[BM_elem_index_get(f_curr)] :
float3(f_curr->no)) :
(!vnos.is_empty() ? vnos[BM_elem_index_get(l_curr->v)] :
float3(l_curr->v->no));
copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no);
} while ((l_curr = l_curr->next) != l_first);
@ -1694,11 +1702,11 @@ static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
}
void BM_loops_calc_normal_vcos(BMesh *bm,
const float (*vcos)[3],
const float (*vnos)[3],
const float (*fnos)[3],
const Span<float3> vcos,
const Span<float3> vnos,
const Span<float3> fnos,
const bool use_split_normals,
float (*r_lnos)[3],
MutableSpan<float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2],
const int cd_loop_clnors_offset,
@ -1728,7 +1736,7 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
/** \name Loop Normal Space API
* \{ */
void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3])
void BM_lnorspacearr_store(BMesh *bm, MutableSpan<float3> r_lnors)
{
BLI_assert(bm->lnor_spacearr != nullptr);
@ -1738,16 +1746,8 @@ void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3])
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(bm,
nullptr,
nullptr,
nullptr,
true,
r_lnors,
bm->lnor_spacearr,
nullptr,
cd_loop_clnors_offset,
false);
BM_loops_calc_normal_vcos(
bm, {}, {}, {}, true, r_lnors, bm->lnor_spacearr, nullptr, cd_loop_clnors_offset, false);
bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
}
@ -1834,10 +1834,8 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
BMLoop *l;
BMIter fiter, liter;
float(*r_lnors)[3] = static_cast<float(*)[3]>(
MEM_callocN(sizeof(*r_lnors) * bm->totloop, __func__));
float(*oldnors)[3] = static_cast<float(*)[3]>(
preserve_clnor ? MEM_mallocN(sizeof(*oldnors) * bm->totloop, __func__) : nullptr);
Array<float3> r_lnors(bm->totloop, float3(0));
Array<float3> oldnors(preserve_clnor ? bm->totloop : 0, float3(0));
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
@ -1865,17 +1863,8 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
BKE_lnor_spacearr_clear(bm->lnor_spacearr);
}
BM_loops_calc_normal_vcos(bm,
nullptr,
nullptr,
nullptr,
true,
r_lnors,
bm->lnor_spacearr,
nullptr,
cd_loop_clnors_offset,
true);
MEM_freeN(r_lnors);
BM_loops_calc_normal_vcos(
bm, {}, {}, {}, true, r_lnors, bm->lnor_spacearr, nullptr, cd_loop_clnors_offset, true);
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@ -1894,7 +1883,6 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
}
}
MEM_SAFE_FREE(oldnors);
bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
#ifndef NDEBUG
@ -1908,12 +1896,8 @@ void BM_lnorspace_update(BMesh *bm)
bm->lnor_spacearr = MEM_cnew<MLoopNorSpaceArray>(__func__);
}
if (bm->lnor_spacearr->lspacearr == nullptr) {
float(*lnors)[3] = static_cast<float(*)[3]>(
MEM_callocN(sizeof(*lnors) * bm->totloop, __func__));
Array<float3> lnors(bm->totloop, float3(0));
BM_lnorspacearr_store(bm, lnors);
MEM_freeN(lnors);
}
else if (bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL)) {
BM_lnorspace_rebuild(bm, false);
@ -1945,9 +1929,9 @@ void BM_lnorspace_err(BMesh *bm)
BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
float(*lnors)[3] = static_cast<float(*)[3]>(MEM_callocN(sizeof(*lnors) * bm->totloop, __func__));
Array<float3> lnors(bm->totloop, float3(0));
BM_loops_calc_normal_vcos(
bm, nullptr, nullptr, nullptr, true, lnors, temp, nullptr, cd_loop_clnors_offset, true);
bm, {}, {}, {}, true, lnors, temp, nullptr, cd_loop_clnors_offset, true);
for (int i = 0; i < bm->totloop; i++) {
int j = 0;
@ -1969,7 +1953,6 @@ void BM_lnorspace_err(BMesh *bm)
}
BKE_lnor_spacearr_free(temp);
MEM_freeN(temp);
MEM_freeN(lnors);
BLI_assert(clear);
bm->spacearr_dirty &= ~BM_SPACEARR_DIRTY_ALL;
@ -2268,8 +2251,8 @@ void BM_custom_loop_normals_from_vector_layer(BMesh *bm, bool add_sharp_edges)
}
bm_mesh_loops_custom_normals_set(bm,
nullptr,
nullptr,
{},
{},
bm->lnor_spacearr,
nullptr,
cd_custom_normal_offset,

View File

@ -43,9 +43,9 @@ void BM_mesh_normals_update_with_partial(BMesh *bm, const BMPartialUpdate *bmpin
* using given vertex coordinates (vcos) and polygon normals (fnos).
*/
void BM_verts_calc_normal_vcos(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
float (*vnos)[3]);
blender::Span<blender::float3> fnos,
blender::Span<blender::float3> vcos,
blender::MutableSpan<blender::float3> vnos);
/**
* \brief BMesh Compute Loop Normals from/to external data.
*
@ -54,11 +54,11 @@ void BM_verts_calc_normal_vcos(BMesh *bm,
* (splitting edges).
*/
void BM_loops_calc_normal_vcos(BMesh *bm,
const float (*vcos)[3],
const float (*vnos)[3],
const float (*fnos)[3],
blender::Span<blender::float3> vcos,
blender::Span<blender::float3> vnos,
blender::Span<blender::float3> fnos,
bool use_split_normals,
float (*r_lnos)[3],
blender::MutableSpan<blender::float3> r_lnos,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2],
int cd_loop_clnors_offset,
@ -70,7 +70,7 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
* and yet we need to walk them once, and only once.
*/
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]);
void BM_lnorspacearr_store(BMesh *bm, blender::MutableSpan<blender::float3> r_lnors);
void BM_lnorspace_invalidate(BMesh *bm, bool do_invalidate_all);
void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor);
/**

View File

@ -31,6 +31,9 @@
#include "intern/bmesh_private.hh"
using blender::float3;
using blender::Span;
/**
* \brief COMPUTE POLY NORMAL (BMFace)
*
@ -66,7 +69,7 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
*/
static float bm_face_calc_poly_normal_vertex_cos(const BMFace *f,
float r_no[3],
float const (*vertexCos)[3])
const Span<float3> vertexCos)
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter = l_first;
@ -742,7 +745,7 @@ void BM_face_normal_update(BMFace *f)
float BM_face_calc_normal_vcos(const BMesh *bm,
const BMFace *f,
float r_no[3],
float const (*vertexCos)[3])
const Span<float3> vertexCos)
{
BMLoop *l;

View File

@ -46,7 +46,7 @@ float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
float BM_face_calc_normal_vcos(const BMesh *bm,
const BMFace *f,
float r_no[3],
float const (*vertexCos)[3]) ATTR_NONNULL();
blender::Span<blender::float3> vertexCos) ATTR_NONNULL();
/**
* Calculate a normal from a vertex cloud.

View File

@ -49,8 +49,8 @@ class ConversionOperation : public SimpleOperation {
/* -------------------------------------------------------------------- */
/** \name Convert Float to Vector Operation
*
* Takes a float result and outputs a vector result. All three components of the output are filled
* with the input float.
* Takes a float result and outputs a vector result. The first three components of the output are
* filled with the input float, while the fourth component is set to 1.
* \{ */
class ConvertFloatToVectorOperation : public ConversionOperation {

View File

@ -49,7 +49,10 @@ class FileOutput {
public:
/* Allocate and initialize the internal render result of the file output using the give
* parameters. See the implementation for more information. */
FileOutput(std::string path, ImageFormatData format, int2 size, bool save_as_render);
FileOutput(const std::string &path,
const ImageFormatData &format,
int2 size,
bool save_as_render);
/* Free the internal render result. */
~FileOutput();

View File

@ -36,7 +36,7 @@ class DistortionGridKey {
DistortionType type;
int2 calibration_size;
DistortionGridKey(MovieTrackingCamera camera,
DistortionGridKey(const MovieTrackingCamera &camera,
int2 size,
DistortionType type,
int2 calibration_size);

View File

@ -22,9 +22,9 @@ class OCIOColorSpaceConversionShaderKey {
std::string target;
std::string config_cache_id;
OCIOColorSpaceConversionShaderKey(std::string source,
std::string target,
std::string config_cache_id);
OCIOColorSpaceConversionShaderKey(const std::string &source,
const std::string &target,
const std::string &config_cache_id);
uint64_t hash() const;
};

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