Sculpt: Improve Expand performance #120125

Closed
Raul Fernandez Hernandez wants to merge 181 commits from farsthary/blender:improve-expand-perf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
304 changed files with 10466 additions and 1826 deletions
Showing only changes of commit 6c7d2cb02e - Show all commits

View File

@ -30,7 +30,7 @@ CHECKER_EXCLUDE_SOURCE_FILES = set(os.path.join(*f.split("/")) for f in (
"source/blender/draw/engines/eevee_next/eevee_lut.cc",
))
CHECKER_ARGS = [
CHECKER_ARGS = (
# Speed up execution.
# As Blender has many defines, the total number of configurations is large making execution unreasonably slow.
# This could be increased but do so with care.
@ -39,9 +39,15 @@ CHECKER_ARGS = [
# Enable this when includes are missing.
# "--check-config",
# This is slower, for a comprehensive output it is needed.
"--check-level=exhaustive",
# Shows many pedantic issues, some are quite useful.
"--enable=all",
# Generates many warnings, CPPCHECK known about system includes without resolving them.
"--suppress=missingIncludeSystem",
# Also shows useful messages, even if some are false-positives.
"--inconclusive",
@ -50,7 +56,15 @@ CHECKER_ARGS = [
*(() if USE_VERBOSE else ("--quiet",))
# NOTE: `--cppcheck-build-dir=<dir>` is added later as a temporary directory.
]
)
CHECKER_ARGS_C = (
"--std=c11",
)
CHECKER_ARGS_CXX = (
"--std=c++17",
)
def source_info_filter(
@ -74,22 +88,50 @@ def source_info_filter(
return source_info_result
def cppcheck() -> None:
def cppcheck(temp_dir: str) -> None:
temp_build_dir = os.path.join(temp_dir, "build")
temp_source_dir = os.path.join(temp_dir, "source")
del temp_dir
os.mkdir(temp_build_dir)
os.mkdir(temp_source_dir)
source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX)
source_defines = project_source_info.build_defines_as_args()
cppcheck_compiler_h = os.path.join(temp_source_dir, "cppcheck_compiler.h")
with open(cppcheck_compiler_h, "w", encoding="utf-8") as fh:
fh.write(project_source_info.build_defines_as_source())
# Add additional defines.
fh.write("\n")
# Python's `pyport.h` errors without this.
fh.write("#define UCHAR_MAX 255\n")
# `intern/atomic/intern/atomic_ops_utils.h` errors with `Cannot find int size` without this.
fh.write("#define UINT_MAX 0xFFFFFFFF\n")
# Apply exclusion.
source_info = source_info_filter(source_info)
check_commands = []
for c, inc_dirs, defs in source_info:
if c.endswith(".c"):
checker_args_extra = CHECKER_ARGS_C
else:
checker_args_extra = CHECKER_ARGS_CXX
cmd = (
[CHECKER_BIN] +
CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs] +
source_defines
CHECKER_BIN,
*CHECKER_ARGS,
*checker_args_extra,
"--cppcheck-build-dir=" + temp_build_dir,
"--include=" + cppcheck_compiler_h,
# NOTE: for some reason failing to include this crease a large number of syntax errors
# from `intern/guardedalloc/MEM_guardedalloc.h`. Include directly to resolve.
"--include=" + os.path.join(
project_source_info.SOURCE_DIR, "source", "blender", "blenlib", "BLI_compiler_attrs.h",
),
c,
*[("-I%s" % i) for i in inc_dirs],
*[("-D%s" % d) for d in defs],
)
check_commands.append((c, cmd))
@ -119,8 +161,7 @@ def cppcheck() -> None:
def main() -> None:
with tempfile.TemporaryDirectory() as temp_dir:
CHECKER_ARGS.append("--cppcheck-build-dir=" + temp_dir)
cppcheck()
cppcheck(temp_dir)
if __name__ == "__main__":

View File

@ -24,12 +24,12 @@ from typing import (
Any,
Callable,
Generator,
IO,
List,
Optional,
Sequence,
Tuple,
Union,
cast,
)
import shlex
@ -120,12 +120,13 @@ def makefile_log() -> List[str]:
time.sleep(1)
# We know this is always true based on the input arguments to `Popen`.
stdout: IO[bytes] = process.stdout # type: ignore
assert process.stdout is not None
stdout: IO[bytes] = process.stdout
out = stdout.read()
stdout.close()
print("done!", len(out), "bytes")
return cast(List[str], out.decode("utf-8", errors="ignore").split("\n"))
return out.decode("utf-8", errors="ignore").split("\n")
def build_info(
@ -211,9 +212,10 @@ def build_defines_as_source() -> str:
)
# We know this is always true based on the input arguments to `Popen`.
stdout: IO[bytes] = process.stdout # type: ignore
assert process.stdout is not None
stdout: IO[bytes] = process.stdout
return cast(str, stdout.read().strip().decode('ascii'))
return stdout.read().strip().decode('ascii')
def build_defines_as_args() -> List[str]:

View File

@ -33,7 +33,7 @@ def main() -> None:
blender_srcdir = Path(__file__).absolute().parent.parent.parent
cli_parser = argparse.ArgumentParser(
description=f"Create a tarball of the Blender sources, optionally including sources of dependencies.",
description="Create a tarball of the Blender sources, optionally including sources of dependencies.",
epilog="This script is intended to be run by `make source_archive_complete`.",
)
cli_parser.add_argument(

View File

@ -393,7 +393,7 @@ def floating_checkout_add_origin_if_needed(
upstream_url = make_utils.git_get_remote_url(args.git_command, "upstream")
call((args.git_command, "remote", "rename", "upstream", "origin"))
make_utils.git_set_config(args.git_command, f"remote.origin.url", origin_external_url)
make_utils.git_set_config(args.git_command, "remote.origin.url", origin_external_url)
call((args.git_command, "remote", "add", "upstream", upstream_url))
finally:

View File

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

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

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

26
extern/xxhash/LICENSE vendored Normal file
View File

@ -0,0 +1,26 @@
xxHash Library
Copyright (c) 2012-2021 Yann Collet
All rights reserved.
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

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

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

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

@ -0,0 +1,43 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2012-2021 Yann Collet
*
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* xxhash.c instantiates functions defined in xxhash.h
*/
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
#define XXH_IMPLEMENTATION /* access definitions */
#include "xxhash.h"

6773
extern/xxhash/xxhash.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -18,9 +18,8 @@
#include "util/texture.h"
#include "util/types.h"
/* On x86_64, versions of glibc < 2.16 have an issue where expf is
* much slower than the double version. This was fixed in glibc 2.16.
*/
/* On x86_64, versions of GLIBC < 2.16 have an issue where `expf` is
* much slower than the double version. This was fixed in GLIBC 2.16. */
#if !defined(__KERNEL_GPU__) && defined(__x86_64__) && defined(__x86_64__) && \
defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
(__GLIBC__ <= 2 && __GLIBC_MINOR__ < 16)

View File

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

View File

@ -275,8 +275,8 @@ ccl_device_inline float4 improve_5throot_solution_sse2(const float4 &old_result,
/* Calculate powf(x, 2.4). Working domain: 1e-10 < x < 1e+10 */
ccl_device_inline float4 fastpow24_sse2(const float4 &arg)
{
/* max, avg and |avg| errors were calculated in gcc without FMA instructions
* The final precision should be better than powf in glibc */
/* `max`, `avg` and |avg| errors were calculated in GCC without FMA instructions.
* The final precision should be better than `powf` in GLIBC. */
/* Calculate x^4/5, coefficient 0.994 was constructed manually to minimize avg error */
/* 0x3F4CCCCD = 4/5 */

View File

@ -14,7 +14,7 @@ CCL_NAMESPACE_BEGIN
thread::thread(function<void()> run_cb) : run_cb_(run_cb), joined_(false)
{
#if defined(__APPLE__) || defined(__linux__) && !defined(__GLIBC__)
/* Set the stack size to 2MB to match glibc. The default 512KB on macOS is
/* Set the stack size to 2MB to match GLIBC. The default 512KB on macOS is
* too small for Embree, and consistent stack size also makes things more
* predictable in general. */
pthread_attr_t attribute;

View File

@ -427,7 +427,7 @@ struct GWL_Cursor {
/**
* The name of the theme (set by an environment variable).
* When disabled, leave as an empty string and the default theme will be used.
* When disabled, leave as an empty string and pass in nullptr to use the default theme.
*/
std::string theme_name;
/**
@ -2507,7 +2507,9 @@ static const wl_cursor *gwl_seat_cursor_find_from_shape(GWL_Seat *seat,
if (!cursor->wl.theme) {
/* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
cursor->wl.theme = wl_cursor_theme_load(
cursor->theme_name.c_str(), cursor->theme_size, seat->system->wl_shm_get());
(cursor->theme_name.empty() ? nullptr : cursor->theme_name.c_str()),
cursor->theme_size,
seat->system->wl_shm_get());
}
if (cursor->wl.theme) {
@ -3521,7 +3523,9 @@ static bool update_cursor_scale(GWL_Cursor &cursor,
}
wl_cursor_theme_destroy(cursor.wl.theme);
cursor.wl.theme = wl_cursor_theme_load(
cursor.theme_name.c_str(), scale * cursor.theme_size, shm);
(cursor.theme_name.empty() ? nullptr : cursor.theme_name.c_str()),
scale * cursor.theme_size,
shm);
if (cursor.wl.theme_cursor) {
cursor.wl.theme_cursor = wl_cursor_theme_get_cursor(cursor.wl.theme,
cursor.wl.theme_cursor_name);

View File

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

View File

@ -0,0 +1,23 @@
The 2-Clause BSD License
------------------------
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -84,7 +84,7 @@ def _kmi_properties_to_lines_recursive(level, properties, lines):
lines_test = []
_kmi_properties_to_lines_recursive(level + 2, value, lines_test)
if lines_test:
lines.append(f"(")
lines.append("(")
lines.append(f"\"{pname}\",\n")
lines.append(f"{indent(level + 3)}" "[")
lines.extend(lines_test)
@ -172,19 +172,19 @@ def keyconfig_export_as_data(wm, kc, filepath, *, all_keymaps=False):
fw("},\n")
fw(f"{indent(2)}" "{")
is_modal = km.is_modal
fw(f"\"items\":\n")
fw("\"items\":\n")
fw(f"{indent(3)}[")
for kmi in km.keymap_items:
if is_modal:
kmi_id = kmi.propvalue
else:
kmi_id = kmi.idname
fw(f"(")
fw("(")
kmi_args = kmi_args_as_data(kmi)
kmi_data = _kmi_attrs_or_none(4, kmi)
fw(f"\"{kmi_id:s}\"")
if kmi_data is None:
fw(f", ")
fw(", ")
else:
fw(",\n" f"{indent(5)}")

View File

@ -6142,6 +6142,7 @@ def km_edit_curves(params):
(op_tool_cycle, "builtin.tilt"), params),
("transform.transform", {"type": 'S', "value": 'PRESS', "alt": True},
{"properties": [("mode", 'CURVE_SHRINKFATTEN')]}),
("curves.cyclic_toggle", {"type": 'C', "value": 'PRESS', "alt": True}, None),
])
return keymap

View File

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

View File

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

View File

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

View File

@ -5911,6 +5911,8 @@ class VIEW3D_MT_edit_curves(Menu):
layout.separator()
layout.operator("curves.attribute_set")
layout.operator("curves.delete")
layout.operator("curves.cyclic_toggle")
layout.operator_menu_enum("curves.curve_type_set", "type")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
@ -7861,6 +7863,8 @@ class VIEW3D_PT_overlay_grease_pencil_options(Panel):
'OBJECT': iface_("Grease Pencil"),
}[context.mode], translate=False)
layout.prop(overlay, "use_gpencil_onion_skin", text="Onion Skin")
if ob.mode in {'EDIT'}:
split = layout.split()
col = split.column()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@
#include "BLI_array_utils.hh"
#include "BLI_color.hh"
#include "BLI_function_ref.hh"
#include "BLI_implicit_sharing_ptr.hh"
#include "BLI_map.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
@ -244,20 +245,23 @@ class TreeNode : public ::GreasePencilLayerTreeNode {
/**
* \returns this node as a #Layer.
*/
Layer &as_layer();
const Layer &as_layer() const;
Layer &as_layer();
/**
* \returns this node as a #LayerGroup.
*/
LayerGroup &as_group();
const LayerGroup &as_group() const;
LayerGroup &as_group();
/**
* \returns the parent layer group or nullptr for the root group.
*/
LayerGroup *parent_group() const;
TreeNode *parent_node() const;
const LayerGroup *parent_group() const;
LayerGroup *parent_group();
const TreeNode *parent_node() const;
TreeNode *parent_node();
/**
* \returns the number of non-null parents of the node.
@ -373,7 +377,8 @@ class Layer : public ::GreasePencilLayer {
/**
* \returns the parent #LayerGroup of this layer.
*/
LayerGroup &parent_group() const;
const LayerGroup &parent_group() const;
LayerGroup &parent_group();
/**
* \returns the frames mapping.
@ -702,7 +707,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
{
@ -748,7 +754,11 @@ inline bool Layer::is_empty() const
{
return (this->frames().is_empty());
}
inline LayerGroup &Layer::parent_group() const
inline const LayerGroup &Layer::parent_group() const
{
return *this->as_node().parent_group();
}
inline LayerGroup &Layer::parent_group()
{
return *this->as_node().parent_group();
}
@ -773,7 +783,11 @@ class GreasePencilRuntime {
class GreasePencilDrawingEditHints {
public:
std::optional<Array<float3>> positions;
const greasepencil::Drawing *drawing_orig;
ImplicitSharingPtrAndData positions_data;
std::optional<Span<float3>> positions() const;
std::optional<MutableSpan<float3>> positions_for_write();
};
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1359,8 +1359,6 @@ bool BKE_collection_object_add_notest(Main *bmain, Collection *collection, Objec
return false;
}
const int id_create_flag = (collection->id.tag & LIB_TAG_NO_MAIN) ? LIB_ID_CREATE_NO_MAIN : 0;
/* Only case where this pointer can be nullptr is when scene itself is linked, this case should
* never be reached. */
BLI_assert(collection != nullptr);
@ -1368,6 +1366,7 @@ bool BKE_collection_object_add_notest(Main *bmain, Collection *collection, Objec
return false;
}
const int id_create_flag = (collection->id.tag & LIB_TAG_NO_MAIN) ? LIB_ID_CREATE_NO_MAIN : 0;
if (!collection_object_add(bmain, collection, ob, nullptr, id_create_flag, true)) {
return false;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1754,8 +1754,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
nullptr,
nullptr},
/* 18: CD_TANGENT */
{sizeof(float[4][4]),
alignof(float[4][4]),
{sizeof(float[4]),
alignof(float[4]),
"",
0,
N_("Tangent"),

View File

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

View File

@ -700,9 +700,9 @@ bool get_effector_data(EffectorCache *eff,
else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) {
/* TODO: hair and points object support */
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(eff->ob);
if (mesh_eval != nullptr) {
const blender::Span<blender::float3> positions = mesh_eval->vert_positions();
const blender::Span<blender::float3> vert_normals = mesh_eval->vert_normals();
if (mesh_eval != nullptr) {
copy_v3_v3(efd->loc, positions[*efd->index]);
copy_v3_v3(efd->nor, vert_normals[*efd->index]);

View File

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

View File

@ -1028,7 +1028,7 @@ void BKE_gpencil_stroke_copy_settings(const bGPDstroke *gps_src, bGPDstroke *gps
copy_v2_v2_short(gps_dst->caps, gps_src->caps);
gps_dst->hardness = gps_src->hardness;
copy_v2_v2(gps_dst->aspect_ratio, gps_src->aspect_ratio);
gps_dst->fill_opacity_fac = gps_dst->fill_opacity_fac;
gps_dst->fill_opacity_fac = gps_src->fill_opacity_fac;
copy_v3_v3(gps_dst->boundbox_min, gps_src->boundbox_min);
copy_v3_v3(gps_dst->boundbox_max, gps_src->boundbox_max);
gps_dst->uv_rotation = gps_src->uv_rotation;

View File

@ -42,6 +42,7 @@
#include "BLI_string.h"
#include "BLI_string_ref.hh"
#include "BLI_string_utils.hh"
#include "BLI_utildefines.h"
#include "BLI_vector_set.hh"
#include "BLI_virtual_array.hh"
@ -52,6 +53,7 @@
#include "DNA_ID.h"
#include "DNA_ID_enums.h"
#include "DNA_brush_types.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_material_types.h"
@ -80,10 +82,12 @@ static void grease_pencil_init_data(ID *id)
using namespace blender::bke;
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(id);
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(grease_pencil, id));
MEMCPY_STRUCT_AFTER(grease_pencil, DNA_struct_default_get(GreasePencil), id);
grease_pencil->root_group_ptr = MEM_new<greasepencil::LayerGroup>(__func__);
grease_pencil->active_layer = nullptr;
grease_pencil->flag |= GREASE_PENCIL_ANIM_CHANNEL_EXPANDED;
CustomData_reset(&grease_pencil->layers_data);
@ -578,7 +582,7 @@ void Drawing::set_texture_matrices(Span<float4x2> matrices, const IndexMask &sel
const float4x2 texspace = matrices[pos];
/* We do the computation using doubles to avoid numerical precision errors. */
double4x3 strokemat4x3 = double4x3(expand_4x2_mat(strokemat));
const double4x3 strokemat4x3 = double4x3(expand_4x2_mat(strokemat));
/*
* We want to solve for `texture_matrix` in the equation: `texspace = texture_matrix *
@ -766,7 +770,7 @@ TreeNode::TreeNode()
this->parent = nullptr;
this->GreasePencilLayerTreeNode::name = nullptr;
this->flag = GP_LAYER_TREE_NODE_HIDE_MASKS;
this->flag = 0;
this->color[0] = this->color[1] = this->color[2] = 0;
}
@ -819,12 +823,19 @@ Layer &TreeNode::as_layer()
return *reinterpret_cast<Layer *>(this);
}
LayerGroup *TreeNode::parent_group() const
const LayerGroup *TreeNode::parent_group() const
{
return (this->parent) ? &this->parent->wrap() : nullptr;
}
TreeNode *TreeNode::parent_node() const
LayerGroup *TreeNode::parent_group()
{
return (this->parent) ? &this->parent->wrap() : nullptr;
}
const TreeNode *TreeNode::parent_node() const
{
return this->parent_group() ? &this->parent->wrap().as_node() : nullptr;
}
TreeNode *TreeNode::parent_node()
{
return this->parent_group() ? &this->parent->wrap().as_node() : nullptr;
}
@ -928,7 +939,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 +1581,40 @@ void LayerGroup::update_from_dna_read()
} // namespace blender::bke::greasepencil
namespace blender::bke {
std::optional<Span<float3>> GreasePencilDrawingEditHints::positions() const
{
if (!this->positions_data.has_value()) {
return std::nullopt;
}
const int points_num = this->drawing_orig->geometry.wrap().points_num();
return Span(static_cast<const float3 *>(this->positions_data.data), points_num);
}
std::optional<MutableSpan<float3>> GreasePencilDrawingEditHints::positions_for_write()
{
if (!this->positions_data.has_value()) {
return std::nullopt;
}
const int points_num = this->drawing_orig->geometry.wrap().points_num();
ImplicitSharingPtrAndData &data = this->positions_data;
if (data.sharing_info->is_mutable()) {
/* If the referenced component is already mutable, return it directly. */
data.sharing_info->tag_ensured_mutable();
}
else {
auto *new_sharing_info = new ImplicitSharedValue<Array<float3>>(*this->positions());
data.sharing_info = ImplicitSharingPtr<ImplicitSharingInfo>(new_sharing_info);
data.data = new_sharing_info->data.data();
}
return MutableSpan(const_cast<float3 *>(static_cast<const float3 *>(data.data)), points_num);
}
} // namespace blender::bke
/* ------------------------------------------------------------------- */
/** \name Grease Pencil kernel functions
* \{ */

View File

@ -172,6 +172,10 @@ static void find_used_vertex_groups(const bGPDframe &gpf,
Span<MDeformVert> dverts = {gps->dvert, gps->totpoints};
for (const MDeformVert &dvert : dverts) {
for (const MDeformWeight &weight : Span<MDeformWeight>{dvert.dw, dvert.totweight}) {
if (weight.def_nr >= dvert.totweight) {
/* Ignore invalid deform weight group indices. */
continue;
}
is_group_used[weight.def_nr] = true;
}
}
@ -362,6 +366,10 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
dst_dvert.dw = static_cast<MDeformWeight *>(MEM_dupallocN(src_dvert.dw));
const MutableSpan<MDeformWeight> vertex_weights = {dst_dvert.dw, dst_dvert.totweight};
for (MDeformWeight &weight : vertex_weights) {
if (weight.def_nr >= dst_dvert.totweight) {
/* Ignore invalid deform weight group indices. */
continue;
}
/* Map def_nr to the reduced vertex group list. */
weight.def_nr = stroke_def_nr_map[weight.def_nr];
}
@ -403,7 +411,11 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
SpanAttributeWriter<float> stroke_point_aspect_ratios =
attributes.lookup_or_add_for_write_span<float>("aspect_ratio", AttrDomain::Curve);
SpanAttributeWriter<ColorGeometry4f> stroke_fill_colors =
attributes.lookup_or_add_for_write_span<ColorGeometry4f>("fill_color", AttrDomain::Curve);
attributes.lookup_or_add_for_write_span<ColorGeometry4f>(
"fill_color",
AttrDomain::Curve,
bke::AttributeInitVArray(VArray<ColorGeometry4f>::ForSingle(
ColorGeometry4f(float4(0.0f)), curves.curves_num())));
SpanAttributeWriter<int> stroke_materials = attributes.lookup_or_add_for_write_span<int>(
"material_index", AttrDomain::Curve);
@ -573,8 +585,8 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_USE_LIGHTS), GP_LAYER_TREE_NODE_USE_LIGHTS);
SET_FLAG_FROM_TEST(new_layer.base.flag,
(gpl->onion_flag & GP_LAYER_ONIONSKIN),
GP_LAYER_TREE_NODE_USE_ONION_SKINNING);
(gpl->onion_flag & GP_LAYER_ONIONSKIN) == 0,
GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING);
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_USE_MASK) == 0, GP_LAYER_TREE_NODE_HIDE_MASKS);
@ -638,18 +650,28 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
grease_pencil.vertex_group_active_index = gpd.vertex_group_active_index;
/* Convert the onion skinning settings. */
grease_pencil.onion_skinning_settings.opacity = gpd.onion_factor;
grease_pencil.onion_skinning_settings.mode = gpd.onion_mode;
GreasePencilOnionSkinningSettings &settings = grease_pencil.onion_skinning_settings;
settings.opacity = gpd.onion_factor;
settings.mode = gpd.onion_mode;
SET_FLAG_FROM_TEST(settings.flag,
((gpd.onion_flag & GP_ONION_GHOST_PREVCOL) != 0 &&
(gpd.onion_flag & GP_ONION_GHOST_NEXTCOL) != 0),
GP_ONION_SKINNING_USE_CUSTOM_COLORS);
SET_FLAG_FROM_TEST(
settings.flag, (gpd.onion_flag & GP_ONION_FADE) != 0, GP_ONION_SKINNING_USE_FADE);
SET_FLAG_FROM_TEST(
settings.flag, (gpd.onion_flag & GP_ONION_LOOP) != 0, GP_ONION_SKINNING_SHOW_LOOP);
/* Convert keytype filter to a bit flag. */
if (gpd.onion_keytype == -1) {
grease_pencil.onion_skinning_settings.filter = GREASE_PENCIL_ONION_SKINNING_FILTER_ALL;
settings.filter = GREASE_PENCIL_ONION_SKINNING_FILTER_ALL;
}
else {
grease_pencil.onion_skinning_settings.filter = (1 << gpd.onion_keytype);
settings.filter = (1 << gpd.onion_keytype);
}
grease_pencil.onion_skinning_settings.num_frames_before = gpd.gstep;
grease_pencil.onion_skinning_settings.num_frames_after = gpd.gstep_next;
copy_v3_v3(grease_pencil.onion_skinning_settings.color_before, gpd.gcolor_prev);
copy_v3_v3(grease_pencil.onion_skinning_settings.color_after, gpd.gcolor_next);
settings.num_frames_before = gpd.gstep;
settings.num_frames_after = gpd.gstep_next;
copy_v3_v3(settings.color_before, gpd.gcolor_prev);
copy_v3_v3(settings.color_after, gpd.gcolor_next);
BKE_id_materials_copy(&bmain, &gpd.id, &grease_pencil.id);
@ -784,10 +806,10 @@ void layer_adjustments_to_modifiers(Main &bmain, bGPdata &src_object_data, Objec
*
* NOTE: NLA animation in GPData that would control adjustment properties is not converted. This
* would require (partially) re-creating a copy of the potential bGPData NLA into the Object NLA,
* which is too complex for the few potential usecases.
* which is too complex for the few potential use cases.
*
* This is achieved in several steps, roughly:
* * For each GP layer, chack if there is animation on the adjutment data.
* * For each GP layer, check if there is animation on the adjustment data.
* * Rename relevant FCurves RNA paths from GP animation data, and store their reference in
* temporary vectors.
* * Once all layers have been processed, move all affected FCurves from GPData animation to
@ -838,7 +860,7 @@ void layer_adjustments_to_modifiers(Main &bmain, bGPdata &src_object_data, Objec
BLI_str_escape(layer_name_esc, gpl->info, sizeof(layer_name_esc));
const std::string legacy_root_path = fmt::format("layers[\"{}\"]", layer_name_esc);
/* If tint or thickness are animated, relevamt modifiers also need to be created. */
/* If tint or thickness are animated, relevant modifiers also need to be created. */
if (gpd_animdata) {
auto adjustment_animation_detection = [&](bAction *owner_action, FCurve &fcurve) -> bool {
/* Early out if we already know that both data are animated. */

View File

@ -457,9 +457,7 @@ static ImageGPUTextures image_get_gpu_texture(Image *ima,
if (GPU_mipmap_enabled()) {
GPU_texture_update_mipmap_chain(*tex);
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
GPU_texture_mipmap_mode(*tex, true, true);
}
else {
@ -624,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,
@ -664,8 +662,8 @@ static ImBuf *update_do_scale(uchar *rect,
}
static void gpu_texture_update_scaled(GPUTexture *tex,
uchar *rect,
float *rect_float,
const uchar *rect,
const float *rect_float,
int full_w,
int full_h,
int x,

View File

@ -431,9 +431,7 @@ static void layer_aov_copy_data(ViewLayer *view_layer_dst,
ListBase *aovs_dst,
const ListBase *aovs_src)
{
if (aovs_src != nullptr) {
BLI_duplicatelist(aovs_dst, aovs_src);
}
ViewLayerAOV *aov_dst = static_cast<ViewLayerAOV *>(aovs_dst->first);
const ViewLayerAOV *aov_src = static_cast<const ViewLayerAOV *>(aovs_src->first);

View File

@ -287,5 +287,5 @@ int64_t BKE_lightprobe_grid_cache_frame_sample_count(const LightProbeGridCacheFr
return cache->block_len * cube_i(cache->block_size);
}
/* LIGHTPROBE_CACHE_UNIFORM_GRID */
return cache->size[0] * cache->size[1] * cache->size[2];
return int64_t(cache->size[0]) * cache->size[1] * cache->size[2];
}

View File

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

View File

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

View File

@ -1158,6 +1158,19 @@ static void polygonize(PROCESS *process)
}
}
static bool object_has_zero_axis_matrix(const Object *bob)
{
if (has_zero_axis_m4(bob->object_to_world().ptr())) {
return true;
}
for (Object *pob = bob->parent; pob; pob = pob->parent) {
if (has_zero_axis_m4(pob->object_to_world().ptr())) {
return true;
}
}
return false;
}
/**
* Iterates over ALL objects in the scene and all of its sets, including
* making all duplis (not only meta-elements). Copies meta-elements to #process.mainb array.
@ -1168,19 +1181,15 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
Scene *sce_iter = scene;
Base *base;
Object *bob;
MetaBall *mb;
const MetaElem *ml;
float obinv[4][4], obmat[4][4];
uint i;
int obnr, zero_size = 0;
int obnr;
char obname[MAX_ID_NAME];
SceneBaseIter iter;
const eEvaluationMode deg_eval_mode = DEG_get_mode(depsgraph);
const short parenting_dupli_transflag = (OB_DUPLIFACES | OB_DUPLIVERTS);
copy_m4_m4(
obmat,
ob->object_to_world().ptr()); /* to cope with duplicators from BKE_scene_base_iter_next */
/* Copy object matrices to cope with duplicators from #BKE_scene_base_iter_next. */
float obinv[4][4], obmat[4][4];
copy_m4_m4(obmat, ob->object_to_world().ptr());
invert_m4_m4(obinv, ob->object_to_world().ptr());
BLI_string_split_name_number(ob->id.name + 2, '.', obname, &obnr);
@ -1188,9 +1197,9 @@ 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. */
@ -1202,64 +1211,35 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
}
if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
mb = static_cast<MetaBall *>(ob->data);
if (mb->editelems) {
ml = static_cast<const MetaElem *>(mb->editelems->first);
}
else {
ml = static_cast<const MetaElem *>(mb->elems.first);
}
/* Pass. */
}
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);
}
}
}
/* 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 (!STREQ(obname, name)) {
/* Not part of the mother-ball, continue. */
continue;
}
}
if (zero_size) {
while (ml) {
ml = ml->next;
/* 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;
}
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;
}
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;
/* make a copy because of duplicates */
new_ml = static_cast<MetaElem *>(
MetaElem *new_ml = static_cast<MetaElem *>(
BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem)));
*(new_ml) = *ml;
new_ml->bb = static_cast<BoundBox *>(
@ -1344,13 +1324,13 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz); /* 7 */
/* Transformation of meta-elem bounding-box. */
for (i = 0; i < 8; i++) {
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 (i = 0; i < 8; i++) {
for (uint i = 0; i < 8; i++) {
blender::math::min_max(blender::float3(new_ml->bb->vec[i]), tempmin, tempmax);
}
@ -1366,17 +1346,13 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
}
process->mainb[process->totelem++] = new_ml;
}
ml = ml->next;
}
}
}
}
/* Compute AABB of all meta-elems. */
if (process->totelem > 0) {
copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]);
copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]);
for (i = 1; i < process->totelem; i++) {
for (uint i = 1; i < process->totelem; i++) {
make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb);
}
}

View File

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

View File

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

View File

@ -57,7 +57,7 @@ void mesh_flip_faces(Mesh &mesh, const IndexMask &selection)
}
});
flip_custom_data_type<float4x4>(faces, mesh.corner_data, selection, CD_TANGENT);
flip_custom_data_type<float4>(faces, mesh.corner_data, selection, CD_TANGENT);
flip_custom_data_type<float4>(faces, mesh.corner_data, selection, CD_MLOOPTANGENT);
flip_custom_data_type<short2>(faces, mesh.corner_data, selection, CD_CUSTOMLOOPNORMAL);
flip_custom_data_type<GridPaintMask>(faces, mesh.corner_data, selection, CD_GRID_PAINT_MASK);

View File

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

View File

@ -2431,6 +2431,16 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
BLI_insertlinkbefore(&object->modifiers, object->modifiers.last, new_md);
}
}
if (md->type == eModifierType_Nodes) {
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
if (nmd->node_group && is_auto_smooth_node_tree(*nmd->node_group)) {
/* This object has already been processed by versioning. If the mesh is linked from
* another file its auto-smooth flag may not be cleared, so this check is necessary to
* avoid adding a duplicate modifier. */
has_custom_normals = true;
break;
}
}
}
/* Some modifiers always generate custom normals which disabled sharp edge tagging, making

View File

@ -548,22 +548,14 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
*tangent_mask_curr_p = tangent_mask_curr;
/* Update active layer index */
int act_uv_index = (act_uv_n != -1) ?
CustomData_get_layer_index_n(loopdata, CD_PROP_FLOAT2, act_uv_n) :
-1;
if (act_uv_index != -1) {
int tan_index = CustomData_get_named_layer_index(
loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name);
if (const char *active_uv_name = CustomData_get_active_layer_name(loopdata, CD_PROP_FLOAT2)) {
int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, active_uv_name);
CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
} /* else tangent has been built from orco */
/* Update render layer index */
int ren_uv_index = (ren_uv_n != -1) ?
CustomData_get_layer_index_n(loopdata, CD_PROP_FLOAT2, ren_uv_n) :
-1;
if (ren_uv_index != -1) {
int tan_index = CustomData_get_named_layer_index(
loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name);
if (const char *render_uv_name = CustomData_get_render_layer_name(loopdata, CD_PROP_FLOAT2)) {
int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, render_uv_name);
CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
} /* else tangent has been built from orco */
}

View File

@ -30,6 +30,7 @@
#include "BKE_customdata.hh"
#include "BKE_deform.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.hh"
#include "DEG_depsgraph.hh"
@ -1125,6 +1126,7 @@ bool BKE_mesh_validate(Mesh *mesh, const bool do_verbose, const bool cddata_chec
&changed);
if (changed) {
BKE_mesh_runtime_clear_cache(mesh);
DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY_ALL_MODES);
return true;
}

View File

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

View File

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

View File

@ -4157,7 +4157,7 @@ static blender::Set<int> get_known_node_types_set()
static bool can_read_node_type(const int type)
{
/* Can always read custom node types. */
if (type == NODE_CUSTOM) {
if (ELEM(type, NODE_CUSTOM, NODE_CUSTOM_GROUP)) {
return true;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -834,8 +834,8 @@ static int distribute_compare_orig_index(const void *p1, const void *p2, void *u
return -1;
}
if (index1 == index2) {
/* this pointer comparison appears to make qsort stable for glibc,
* and apparently on solaris too, makes the renders reproducible */
/* This pointer comparison appears to make #qsort stable for GLIBC,
* and apparently on SOLARIS too, makes the renders reproducible. */
if (p1 < p2) {
return -1;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -46,6 +46,7 @@ extern "C" {
# include <libavformat/avformat.h>
# include <libavutil/buffer.h>
# include <libavutil/channel_layout.h>
# include <libavutil/cpu.h>
# include <libavutil/imgutils.h>
# include <libavutil/opt.h>
# include <libavutil/rational.h>
@ -256,14 +257,15 @@ static AVFrame *alloc_picture(AVPixelFormat pix_fmt, int width, int height)
}
/* allocate the actual picture buffer */
int size = av_image_get_buffer_size(pix_fmt, width, height, 1);
const size_t align = av_cpu_max_align();
int size = av_image_get_buffer_size(pix_fmt, width, height, align);
AVBufferRef *buf = av_buffer_alloc(size);
if (buf == nullptr) {
av_frame_free(&f);
return nullptr;
}
av_image_fill_arrays(f->data, f->linesize, buf->data, pix_fmt, width, height, 1);
av_image_fill_arrays(f->data, f->linesize, buf->data, pix_fmt, width, height, align);
f->buf[0] = buf;
f->format = pix_fmt;
f->width = width;
@ -418,15 +420,16 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const ImBuf *image)
/* Copy the Blender pixels into the FFMPEG data-structure, taking care of endianness and flipping
* the image vertically. */
int linesize = rgb_frame->linesize[0];
int linesize_src = rgb_frame->width * 4;
for (int y = 0; y < height; y++) {
uint8_t *target = rgb_frame->data[0] + linesize * (height - y - 1);
const uint8_t *src = pixels + linesize * y;
const uint8_t *src = pixels + linesize_src * y;
# if ENDIAN_ORDER == L_ENDIAN
memcpy(target, src, linesize);
memcpy(target, src, linesize_src);
# elif ENDIAN_ORDER == B_ENDIAN
const uint8_t *end = src + linesize;
const uint8_t *end = src + linesize_src;
while (src != end) {
target[3] = src[0];
target[2] = src[1];

View File

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

View File

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

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