Fix #119909: Unkeyable custom properties receive keyframes #119914
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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.
|
|
@ -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
|
|
@ -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"
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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,
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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]; \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
* \{ */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) :
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue