WIP: Basic Blender Project Support (experimental feature) #107655

Draft
Julian Eisel wants to merge 94 commits from blender-projects-basics into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
716 changed files with 18353 additions and 9749 deletions
Showing only changes of commit f0eba2fe6c - Show all commits

View File

@ -605,10 +605,6 @@ else()
set(WITH_METAL_BACKEND OFF)
endif()
if(WITH_METAL_BACKEND)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
endif()
if(WIN32)
getDefaultWindowsPrefixBase(CMAKE_GENERIC_PROGRAM_FILES)
set(CPACK_INSTALL_PREFIX ${CMAKE_GENERIC_PROGRAM_FILES}/${})

View File

@ -22,6 +22,14 @@ elseif(UNIX AND NOT APPLE)
)
endif()
# Boolean crashes with Arm assembly, see T103423.
if(BLENDER_PLATFORM_ARM)
set(GMP_OPTIONS
${GMP_OPTIONS}
--disable-assembly
)
endif()
ExternalProject_Add(external_gmp
URL file://${PACKAGE_DIR}/${GMP_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@ -155,8 +155,8 @@ if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
# M1 chips run Big Sur onwards.
set(OSX_MIN_DEPLOYMENT_TARGET 11.00)
else()
# 10.13 is our min. target, if you use higher sdk, weak linking happens
set(OSX_MIN_DEPLOYMENT_TARGET 10.13)
# 10.15 is our min. target, if you use higher sdk, weak linking happens
set(OSX_MIN_DEPLOYMENT_TARGET 10.15)
endif()
set(CMAKE_OSX_DEPLOYMENT_TARGET "${OSX_MIN_DEPLOYMENT_TARGET}" CACHE STRING "" FORCE)

View File

@ -83,7 +83,7 @@ enum_use_layer_samples = (
enum_sampling_pattern = (
('SOBOL_BURLEY', "Sobol-Burley", "Use on-the-fly computed Owen-scrambled Sobol for random sampling", 0),
('TABULATED_SOBOL', "Tabulated Sobol", "Use precomputed tables of Owen-scrambled Sobol for random sampling", 1),
('TABULATED_SOBOL', "Tabulated Sobol", "Use pre-computed tables of Owen-scrambled Sobol for random sampling", 1),
)
enum_emission_sampling = (
@ -905,7 +905,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
use_fast_gi: BoolProperty(
name="Fast GI Approximation",
description="Approximate diffuse indirect light with background tinted ambient occlusion. This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
description="Approximate diffuse indirect light with background tinted ambient occlusion. "
"This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality",
default=False,
)
@ -1539,13 +1540,16 @@ class CyclesPreferences(bpy.types.AddonPreferences):
use_metalrt: BoolProperty(
name="MetalRT (Experimental)",
description="MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better performance in specific cases. However this support is experimental and some scenes may render incorrectly",
description="MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better "
"performance in specific cases. However this support is experimental and some scenes may render incorrectly",
default=False,
)
kernel_optimization_level: EnumProperty(
name="Kernel Optimization",
description="Kernels can be optimized based on scene content. Optimized kernels are requested at the start of a render. If optimized kernels are not available, rendering will proceed using generic kernels until the optimized set is available in the cache. This can result in additional CPU usage for a brief time (tens of seconds).",
description="Kernels can be optimized based on scene content. Optimized kernels are requested at the start of a render. "
"If optimized kernels are not available, rendering will proceed using generic kernels until the optimized set "
"is available in the cache. This can result in additional CPU usage for a brief time (tens of seconds)",
default='FULL',
items=(
('OFF', "Off", "Disable kernel optimization. Slowest rendering, no extra background CPU usage"),

View File

@ -679,7 +679,7 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
if (num_verts == 0) {
return;
}
const MVert *verts = static_cast<const MVert *>(b_mesh.vertices[0].ptr.data);
const float(*positions)[3] = static_cast<const float(*)[3]>(b_mesh.vertices[0].ptr.data);
/* STEP 1: Find out duplicated vertices and point duplicates to a single
* original vertex.
@ -765,10 +765,8 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
continue;
}
visited_edges.insert(v0, v1);
const MVert &b_vert_0 = verts[v0];
const MVert &b_vert_1 = verts[v1];
float3 co0 = make_float3(b_vert_0.co[0], b_vert_0.co[1], b_vert_0.co[2]);
float3 co1 = make_float3(b_vert_1.co[0], b_vert_1.co[1], b_vert_1.co[2]);
float3 co0 = make_float3(positions[v0][0], positions[v0][1], positions[v0][2]);
float3 co1 = make_float3(positions[v1][0], positions[v1][1], positions[v1][2]);
float3 edge = normalize(co1 - co0);
edge_accum[v0] += edge;
edge_accum[v1] += -edge;
@ -919,7 +917,7 @@ static void create_mesh(Scene *scene,
return;
}
const MVert *verts = static_cast<const MVert *>(b_mesh.vertices[0].ptr.data);
const float(*positions)[3] = static_cast<const float(*)[3]>(b_mesh.vertices[0].ptr.data);
if (!subdivision) {
numtris = numfaces;
@ -942,8 +940,7 @@ static void create_mesh(Scene *scene,
/* create vertex coordinates and normals */
for (int i = 0; i < numverts; i++) {
const MVert &b_vert = verts[i];
mesh->add_vertex(make_float3(b_vert.co[0], b_vert.co[1], b_vert.co[2]));
mesh->add_vertex(make_float3(positions[i][0], positions[i][1], positions[i][2]));
}
AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
@ -1252,14 +1249,13 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
float3 *mP = attr_mP->data_float3() + motion_step * numverts;
float3 *mN = (attr_mN) ? attr_mN->data_float3() + motion_step * numverts : NULL;
const MVert *verts = static_cast<const MVert *>(b_mesh.vertices[0].ptr.data);
const float(*positions)[3] = static_cast<const float(*)[3]>(b_mesh.vertices[0].ptr.data);
/* NOTE: We don't copy more that existing amount of vertices to prevent
* possible memory corruption.
*/
for (int i = 0; i < std::min<size_t>(b_verts_num, numverts); i++) {
const MVert &b_vert = verts[i];
mP[i] = make_float3(b_vert.co[0], b_vert.co[1], b_vert.co[2]);
mP[i] = make_float3(positions[i][0], positions[i][1], positions[i][2]);
}
if (mN) {
const float(*b_vert_normals)[3] = static_cast<const float(*)[3]>(

View File

@ -377,7 +377,8 @@ bool MetalDevice::load_kernels(const uint _kernel_features)
/* Only request generic kernels if they aren't cached in memory. */
if (make_source_and_check_if_compile_needed(PSO_GENERIC)) {
/* If needed, load them asynchronously in order to responsively message progress to the user. */
/* If needed, load them asynchronously in order to responsively message progress to the user.
*/
int this_device_id = this->device_id;
auto compile_kernels_fn = ^() {
compile_and_load(this_device_id, PSO_GENERIC);

View File

@ -58,7 +58,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
sd->P = motion_triangle_point_from_uv(kg, sd, isect_object, isect_prim, sd->u, sd->v, verts);
/* Compute face normal. */
float3 Ng;
if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
if (object_negative_scale_applied(sd->object_flag)) {
Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
}
else {

View File

@ -201,6 +201,11 @@ ccl_device_inline void object_normal_transform(KernelGlobals kg,
*N = normalize(transform_direction_transposed(&tfm, *N));
}
ccl_device_inline bool object_negative_scale_applied(const int object_flag)
{
return ((object_flag & SD_OBJECT_NEGATIVE_SCALE) && (object_flag & SD_OBJECT_TRANSFORM_APPLIED));
}
/* Transform direction vector from object to world space */
ccl_device_inline void object_dir_transform(KernelGlobals kg,

View File

@ -21,7 +21,7 @@ ccl_device_inline float3 triangle_normal(KernelGlobals kg, ccl_private ShaderDat
const float3 v2 = kernel_data_fetch(tri_verts, tri_vindex.w + 2);
/* return normal */
if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
if (object_negative_scale_applied(sd->object_flag)) {
return normalize(cross(v2 - v0, v1 - v0));
}
else {
@ -50,7 +50,7 @@ ccl_device_inline void triangle_point_normal(KernelGlobals kg,
/* get object flags */
int object_flag = kernel_data_fetch(object_flag, object);
/* compute normal */
if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
if (object_negative_scale_applied(object_flag)) {
*Ng = normalize(cross(v2 - v0, v1 - v0));
}
else {

View File

@ -176,8 +176,9 @@ ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg,
/* Geometric normal. */
vtx->ng = normalize(cross(dp_du, dp_dv));
if (sd_vtx->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED)
if (sd_vtx->object_flag & SD_OBJECT_NEGATIVE_SCALE) {
vtx->ng = -vtx->ng;
}
/* Shading normals: Interpolate normals between vertices. */
float n_len;

View File

@ -502,8 +502,15 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
rng_state,
ccl_global float *ccl_restrict render_buffer)
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
if (!(kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) &&
!(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_CAMERA)) {
!(path_flag & PATH_RAY_CAMERA)) {
return;
}
/* Skip AO for paths that were split off for shadow catchers to avoid double-counting. */
if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
return;
}

View File

@ -979,8 +979,10 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase;
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
}
}
/* Update path state */

View File

@ -120,7 +120,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg,
if (path_flag & PATH_RAY_SUBSURFACE_BACKFACING) {
hit_Ng = -hit_Ng;
}
if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
if (object_negative_scale_applied(object_flag)) {
hit_Ng = -hit_Ng;
}

View File

@ -223,11 +223,16 @@ ccl_device bool compute_emitter_centroid_and_dir(KernelGlobals kg,
triangle_world_space_vertices(kg, object, prim_id, -1.0f, vertices);
centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
if (kemitter->emission_sampling == EMISSION_SAMPLING_FRONT) {
const bool is_front_only = (kemitter->emission_sampling == EMISSION_SAMPLING_FRONT);
const bool is_back_only = (kemitter->emission_sampling == EMISSION_SAMPLING_BACK);
if (is_front_only || is_back_only) {
dir = safe_normalize(cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
}
else if (kemitter->emission_sampling == EMISSION_SAMPLING_BACK) {
dir = -safe_normalize(cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
if (is_back_only) {
dir = -dir;
}
if (kernel_data_fetch(object_flag, object) & SD_OBJECT_NEGATIVE_SCALE) {
dir = -dir;
}
}
else {
/* Double-sided: any vector in the plane. */

View File

@ -146,7 +146,7 @@ ccl_device_forceinline bool triangle_light_sample(KernelGlobals kg,
/* flip normal if necessary */
const int object_flag = kernel_data_fetch(object_flag, object);
if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
if (object_flag & SD_OBJECT_NEGATIVE_SCALE) {
ls->Ng = -ls->Ng;
}
ls->eval_fac = 1.0f;

View File

@ -122,6 +122,7 @@ shader node_image_texture(int use_mapping = 0,
vector Nob = transform("world", "object", N);
/* project from direction vector to barycentric coordinates in triangles */
vector signed_Nob = Nob;
Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2]));
Nob /= (Nob[0] + Nob[1] + Nob[2]);
@ -184,9 +185,10 @@ shader node_image_texture(int use_mapping = 0,
float tmp_alpha;
if (weight[0] > 0.0) {
point UV = point((signed_Nob[0] < 0.0) ? 1.0 - p[1] : p[1], p[2], 0.0);
Color += weight[0] * image_texture_lookup(filename,
p[1],
p[2],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,
@ -198,9 +200,10 @@ shader node_image_texture(int use_mapping = 0,
Alpha += weight[0] * tmp_alpha;
}
if (weight[1] > 0.0) {
point UV = point((signed_Nob[1] > 0.0) ? 1.0 - p[0] : p[0], p[2], 0.0);
Color += weight[1] * image_texture_lookup(filename,
p[0],
p[2],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,
@ -212,9 +215,10 @@ shader node_image_texture(int use_mapping = 0,
Alpha += weight[1] * tmp_alpha;
}
if (weight[2] > 0.0) {
point UV = point((signed_Nob[2] > 0.0) ? 1.0 - p[1] : p[1], p[0], 0.0);
Color += weight[2] * image_texture_lookup(filename,
p[1],
p[0],
UV[0],
UV[1],
tmp_alpha,
compress_as_srgb,
ignore_alpha,

View File

@ -224,7 +224,7 @@ ccl_device float3 svm_bevel(
float3 hit_Ng = isect.Ng[hit];
int object = isect.hits[hit].object;
int object_flag = kernel_data_fetch(object_flag, object);
if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
if (object_negative_scale_applied(object_flag)) {
hit_Ng = -hit_Ng;
}

View File

@ -850,8 +850,8 @@ enum ShaderDataObjectFlag {
SD_OBJECT_MOTION = (1 << 1),
/* Vertices have transform applied. */
SD_OBJECT_TRANSFORM_APPLIED = (1 << 2),
/* Vertices have negative scale applied. */
SD_OBJECT_NEGATIVE_SCALE_APPLIED = (1 << 3),
/* The object's transform applies a negative scale. */
SD_OBJECT_NEGATIVE_SCALE = (1 << 3),
/* Object has a volume shader. */
SD_OBJECT_HAS_VOLUME = (1 << 4),
/* Object intersects AABB of an object with volume shader. */
@ -873,7 +873,7 @@ enum ShaderDataObjectFlag {
SD_OBJECT_CAUSTICS = (SD_OBJECT_CAUSTICS_CASTER | SD_OBJECT_CAUSTICS_RECEIVER),
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK | SD_OBJECT_MOTION | SD_OBJECT_TRANSFORM_APPLIED |
SD_OBJECT_NEGATIVE_SCALE_APPLIED | SD_OBJECT_HAS_VOLUME |
SD_OBJECT_NEGATIVE_SCALE | SD_OBJECT_HAS_VOLUME |
SD_OBJECT_INTERSECTS_VOLUME | SD_OBJECT_SHADOW_CATCHER |
SD_OBJECT_HAS_VOLUME_ATTRIBUTES | SD_OBJECT_CAUSTICS |
SD_OBJECT_HAS_VOLUME_MOTION)

View File

@ -32,7 +32,7 @@ static float shutter_curve_eval(float x, array<float> &shutter_curve)
return 1.0f;
}
x *= shutter_curve.size();
x = saturatef(x) * shutter_curve.size() - 1;
int index = (int)x;
float frac = x - index;
if (index < shutter_curve.size() - 1) {

View File

@ -211,6 +211,11 @@ bool OIIOImageLoader::load_pixels(const ImageMetaData &metadata,
if (strcmp(in->format_name(), "dds") == 0) {
do_associate_alpha = true;
}
/* Workaround OIIO bug that sets oiio:UnassociatedAlpha on the last layer
* but not composite image that we read. */
if (strcmp(in->format_name(), "psd") == 0) {
do_associate_alpha = true;
}
}
}

View File

@ -94,14 +94,17 @@ LightTreePrimitive::LightTreePrimitive(Scene *scene, int prim_id, int object_id)
* seems to work fine */
centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
if (shader->emission_sampling == EMISSION_SAMPLING_FRONT) {
/* Front only. */
const bool is_front_only = (shader->emission_sampling == EMISSION_SAMPLING_FRONT);
const bool is_back_only = (shader->emission_sampling == EMISSION_SAMPLING_BACK);
if (is_front_only || is_back_only) {
/* One-sided. */
bcone.axis = safe_normalize(cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
bcone.theta_o = 0;
}
else if (shader->emission_sampling == EMISSION_SAMPLING_BACK) {
/* Back only. */
bcone.axis = -safe_normalize(cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
if (is_back_only) {
bcone.axis = -bcone.axis;
}
if (transform_negative_scale(object->get_tfm())) {
bcone.axis = -bcone.axis;
}
bcone.theta_o = 0;
}
else {

View File

@ -435,6 +435,10 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
state->have_motion = true;
}
if (transform_negative_scale(tfm)) {
flag |= SD_OBJECT_NEGATIVE_SCALE;
}
if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::POINTCLOUD) {
/* TODO: why only mesh? */
Mesh *mesh = static_cast<Mesh *>(geom);
@ -970,8 +974,6 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
}
object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
if (geom->transform_negative_scaled)
object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED;
}
}

View File

@ -289,19 +289,24 @@ RenderWork Session::run_update_for_next_iteration()
RenderWork render_work;
thread_scoped_lock scene_lock(scene->mutex);
thread_scoped_lock reset_lock(delayed_reset_.mutex);
bool have_tiles = true;
bool switched_to_new_tile = false;
bool did_reset = false;
const bool did_reset = delayed_reset_.do_reset;
if (delayed_reset_.do_reset) {
thread_scoped_lock buffers_lock(buffers_mutex_);
do_delayed_reset();
/* Perform delayed reset if requested. */
{
thread_scoped_lock reset_lock(delayed_reset_.mutex);
if (delayed_reset_.do_reset) {
did_reset = true;
/* After reset make sure the tile manager is at the first big tile. */
have_tiles = tile_manager_.next();
switched_to_new_tile = true;
thread_scoped_lock buffers_lock(buffers_mutex_);
do_delayed_reset();
/* After reset make sure the tile manager is at the first big tile. */
have_tiles = tile_manager_.next();
switched_to_new_tile = true;
}
}
/* Update number of samples in the integrator.

View File

@ -16,6 +16,9 @@ void util_cdf_invert(const int resolution,
const bool make_symmetric,
vector<float> &inv_cdf)
{
const int cdf_size = cdf.size();
assert(cdf[0] == 0.0f && cdf[cdf_size - 1] == 1.0f);
const float inv_resolution = 1.0f / (float)resolution;
const float range = to - from;
inv_cdf.resize(resolution);
@ -25,12 +28,12 @@ void util_cdf_invert(const int resolution,
float x = i / (float)half_size;
int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
float t;
if (index < cdf.size() - 1) {
if (index < cdf_size - 1) {
t = (x - cdf[index]) / (cdf[index + 1] - cdf[index]);
}
else {
t = 0.0f;
index = cdf.size() - 1;
index = cdf_size - 1;
}
float y = ((index + t) / (resolution - 1)) * (2.0f * range);
inv_cdf[half_size + i] = 0.5f * (1.0f + y);
@ -39,17 +42,17 @@ void util_cdf_invert(const int resolution,
}
else {
for (int i = 0; i < resolution; i++) {
float x = from + range * (float)i * inv_resolution;
int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
float x = (i + 0.5f) * inv_resolution;
int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin() - 1;
float t;
if (index < cdf.size() - 1) {
if (index < cdf_size - 1) {
t = (x - cdf[index]) / (cdf[index + 1] - cdf[index]);
}
else {
t = 0.0f;
index = resolution;
}
inv_cdf[i] = (index + t) * inv_resolution;
inv_cdf[i] = from + range * (index + t) * inv_resolution;
}
}
}

View File

@ -26,9 +26,11 @@ void util_cdf_evaluate(
cdf[i + 1] = cdf[i] + fabsf(y);
}
/* Normalize the CDF. */
float fac = (cdf[resolution] == 0.0f) ? 0.0f : 1.0f / cdf[resolution];
for (int i = 0; i <= resolution; i++) {
cdf[i] /= cdf[resolution];
cdf[i] *= fac;
}
cdf[resolution] = 1.0f;
}
/* Invert pre-calculated CDF function. */

View File

@ -16,6 +16,12 @@
#include "GHOST_WindowCocoa.h"
#include "GHOST_WindowManager.h"
/* Don't generate OpenGL deprecation warning. This is a known thing, and is not something easily
* solvable in a short term. */
#ifdef __clang__
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
#include "GHOST_ContextCGL.h"
#ifdef WITH_VULKAN_BACKEND

View File

@ -4534,7 +4534,7 @@ static void output_handle_scale(void *data, struct wl_output * /*wl_output*/, co
CLOG_INFO(LOG, 2, "scale");
GWL_Output *output = static_cast<GWL_Output *>(data);
output->scale = factor;
output->system->output_scale_update_maybe_leave(output, false);
output->system->output_scale_update(output);
}
static const struct wl_output_listener output_listener = {
@ -4736,7 +4736,11 @@ static void gwl_registry_wl_output_remove(GWL_Display *display,
if (!on_exit) {
/* Needed for WLROOTS, does nothing if surface leave callbacks have already run. */
output->system->output_scale_update_maybe_leave(output, true);
if (output->system->output_unref(output->wl_output)) {
CLOG_WARN(LOG,
"mis-behaving compositor failed to call \"surface_listener.leave\" "
"window scale may be invalid!");
}
}
if (output->xdg_output) {
@ -6744,11 +6748,13 @@ void GHOST_SystemWayland::seat_active_set(const struct GWL_Seat *seat)
gwl_display_seat_active_set(display_, seat);
}
void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
bool GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
{
bool changed = false;
#define SURFACE_CLEAR_PTR(surface_test) \
if (surface_test == wl_surface) { \
surface_test = nullptr; \
changed = true; \
} \
((void)0);
@ -6760,37 +6766,62 @@ void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
SURFACE_CLEAR_PTR(seat->wl_surface_window_focus_dnd);
}
#undef SURFACE_CLEAR_PTR
return changed;
}
void GHOST_SystemWayland::output_scale_update_maybe_leave(GWL_Output *output, bool leave)
bool GHOST_SystemWayland::output_unref(wl_output *wl_output)
{
/* Update scale, optionally leaving the outputs beforehand. */
GHOST_WindowManager *window_manager = output->system->getWindowManager();
bool changed = false;
if (!ghost_wl_output_own(wl_output)) {
return changed;
}
/* NOTE: keep in sync with `output_scale_update`. */
GWL_Output *output = ghost_wl_output_user_data(wl_output);
GHOST_WindowManager *window_manager = getWindowManager();
if (window_manager) {
for (GHOST_IWindow *iwin : window_manager->getWindows()) {
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
if (win->outputs_leave(output)) {
changed = true;
}
}
}
for (GWL_Seat *seat : display_->seats) {
if (seat->pointer.outputs.erase(output)) {
changed = true;
}
if (seat->tablet.outputs.erase(output)) {
changed = true;
}
}
return changed;
}
void GHOST_SystemWayland::output_scale_update(GWL_Output *output)
{
/* NOTE: keep in sync with `output_unref`. */
GHOST_WindowManager *window_manager = getWindowManager();
if (window_manager) {
for (GHOST_IWindow *iwin : window_manager->getWindows()) {
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
const std::vector<GWL_Output *> &outputs = win->outputs();
bool found = leave ? win->outputs_leave(output) :
!(std::find(outputs.begin(), outputs.end(), output) == outputs.cend());
if (found) {
if (!(std::find(outputs.begin(), outputs.end(), output) == outputs.cend())) {
win->outputs_changed_update_scale();
}
}
}
for (GWL_Seat *seat : display_->seats) {
bool found;
found = leave ? seat->pointer.outputs.erase(output) : seat->pointer.outputs.count(output);
if (found) {
if (seat->pointer.outputs.count(output)) {
if (seat->cursor.wl_surface_cursor != nullptr) {
update_cursor_scale(
seat->cursor, seat->system->wl_shm(), &seat->pointer, seat->cursor.wl_surface_cursor);
}
}
found = leave ? seat->tablet.outputs.erase(output) : seat->tablet.outputs.count(output);
if (found) {
if (seat->tablet.outputs.count(output)) {
for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));

View File

@ -194,10 +194,25 @@ class GHOST_SystemWayland : public GHOST_System {
/** Set this seat to be active. */
void seat_active_set(const struct GWL_Seat *seat);
void output_scale_update_maybe_leave(GWL_Output *output, bool leave);
/**
* Clear all references to this output.
*
* \note The compositor should have already called the `wl_surface_listener.leave` callback,
* however some compositors may not (see T103586).
* So remove references to the output before it's destroyed to avoid crashing.
*
* \return true when any references were removed.
*/
bool output_unref(struct wl_output *wl_output);
/** Clear all references to this surface to prevent accessing NULL pointers. */
void window_surface_unref(const wl_surface *wl_surface);
void output_scale_update(GWL_Output *output);
/**
* Clear all references to this surface to prevent accessing NULL pointers.
*
* \return true when any references were removed.
*/
bool window_surface_unref(const wl_surface *wl_surface);
bool window_cursor_grab_set(const GHOST_TGrabCursorMode mode,
const GHOST_TGrabCursorMode mode_current,

View File

@ -6,6 +6,12 @@
#include "GHOST_Debug.h"
#include "GHOST_SystemCocoa.h"
/* Don't generate OpenGL deprecation warning. This is a known thing, and is not something easily
* solvable in a short term. */
#ifdef __clang__
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
#include "GHOST_ContextCGL.h"
#ifdef WITH_VULKAN_BACKEND

View File

@ -797,11 +797,6 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
window_->ghost_window = this;
window_->ghost_system = system;
window_->frame.size[0] = int32_t(width);
window_->frame.size[1] = int32_t(height);
window_->is_dialog = is_dialog;
/* NOTE(@campbellbarton): The scale set here to avoid flickering on startup.
* When all monitors use the same scale (which is quite common) there aren't any problems.
*
@ -813,6 +808,16 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
* avoiding a large window flashing before it's made smaller. */
window_->scale = outputs_max_scale_or_default(system_->outputs(), 1, &window_->scale_fractional);
window_->frame.size[0] = int32_t(width);
window_->frame.size[1] = int32_t(height);
/* The window surface must be rounded to the scale,
* failing to do so causes the WAYLAND-server to close the window immediately. */
window_->frame.size[0] = (window_->frame.size[0] / window_->scale) * window_->scale;
window_->frame.size[1] = (window_->frame.size[1] / window_->scale) * window_->scale;
window_->is_dialog = is_dialog;
/* Window surfaces. */
window_->wl_surface = wl_compositor_create_surface(system_->wl_compositor());
ghost_wl_surface_tag(window_->wl_surface);

@ -1 +1 @@
Subproject commit 7084c4ecd97d93459d9d23fd90f81589b09be5df
Subproject commit 7be7aff5a18c550465b3f7634539ed4168af7c51

@ -1 +1 @@
Subproject commit a9d4443c244f89399ec4bcc427e05a07950528cc
Subproject commit c226f867affd12881533a54c8c90ac6eebfaca6c

View File

@ -412,6 +412,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"selected",
"selected and lock unselected",
"selected and unlock unselected",
"screen",
"the lazy dog",
"this legacy pose library to pose assets",
"to the top level of the tree",

View File

@ -542,6 +542,7 @@ class SpellChecker:
"voronoi",
"voxel", "voxels",
"vsync",
"vulkan",
"wireframe",
"zmask",
"ztransp",

View File

@ -1342,7 +1342,7 @@ url_manual_mapping = (
("bpy.types.armature.layers_protected*", "animation/armatures/properties/skeleton.html#bpy-types-armature-layers-protected"),
("bpy.types.assetmetadata.description*", "editors/asset_browser.html#bpy-types-assetmetadata-description"),
("bpy.types.bakesettings.normal_space*", "render/cycles/baking.html#bpy-types-bakesettings-normal-space"),
("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/sculpting/tools/snake_hook.html#bpy-types-brush-crease-pinch-factor"),
("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-crease-pinch-factor"),
("bpy.types.brush.elastic_deform_type*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-type"),
("bpy.types.brush.texture_sample_bias*", "sculpt_paint/brush/texture.html#bpy-types-brush-texture-sample-bias"),
("bpy.types.brush.use_cloth_collision*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-use-cloth-collision"),
@ -1468,6 +1468,7 @@ url_manual_mapping = (
("bpy.types.bakesettings.cage_object*", "render/cycles/baking.html#bpy-types-bakesettings-cage-object"),
("bpy.types.bakesettings.margin_type*", "render/cycles/baking.html#bpy-types-bakesettings-margin-type"),
("bpy.types.bone.use_relative_parent*", "animation/armatures/bones/properties/relations.html#bpy-types-bone-use-relative-parent"),
("bpy.types.brush.area_radius_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-area-radius-factor"),
("bpy.types.brush.auto_smooth_factor*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-auto-smooth-factor"),
("bpy.types.brush.smooth_deform_type*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-smooth-deform-type"),
("bpy.types.brush.use_connected_only*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-connected-only"),
@ -1781,6 +1782,7 @@ url_manual_mapping = (
("bpy.types.functionnodefloattoint*", "modeling/geometry_nodes/utilities/float_to_integer.html#bpy-types-functionnodefloattoint"),
("bpy.types.functionnodeinputcolor*", "modeling/geometry_nodes/input/color.html#bpy-types-functionnodeinputcolor"),
("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/convex_hull.html#bpy-types-geometrynodeconvexhull"),
("bpy.types.geometrynodeimageinput*", "modeling/geometry_nodes/input/image_input.html#bpy-types-geometrynodeimageinput"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/input/input_index.html#bpy-types-geometrynodeinputindex"),
("bpy.types.geometrynodeisviewport*", "modeling/geometry_nodes/input/is_viewport.html#bpy-types-geometrynodeisviewport"),
("bpy.types.geometrynodemeshcircle*", "modeling/geometry_nodes/mesh_primitives/mesh_circle.html#bpy-types-geometrynodemeshcircle"),
@ -2172,10 +2174,11 @@ url_manual_mapping = (
("bpy.types.bakesettings.margin*", "render/cycles/baking.html#bpy-types-bakesettings-margin"),
("bpy.types.bakesettings.target*", "render/cycles/baking.html#bpy-types-bakesettings-target"),
("bpy.types.brush.cloth_damping*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-damping"),
("bpy.types.brush.deform_target*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-deform-target"),
("bpy.types.brush.falloff_shape*", "sculpt_paint/brush/falloff.html#bpy-types-brush-falloff-shape"),
("bpy.types.brush.icon_filepath*", "sculpt_paint/brush/brush.html#bpy-types-brush-icon-filepath"),
("bpy.types.brush.stroke_method*", "sculpt_paint/brush/stroke.html#bpy-types-brush-stroke-method"),
("bpy.types.brush.tip_roundness*", "sculpt_paint/sculpting/tools/clay_strips.html#bpy-types-brush-tip-roundness"),
("bpy.types.brush.tip_roundness*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-tip-roundness"),
("bpy.types.camera.display_size*", "render/cameras.html#bpy-types-camera-display-size"),
("bpy.types.camera.sensor_width*", "render/cameras.html#bpy-types-camera-sensor-width"),
("bpy.types.compositornodedblur*", "compositing/types/filter/directional_blur.html#bpy-types-compositornodedblur"),
@ -2705,6 +2708,7 @@ url_manual_mapping = (
("bpy.types.armature.rigify*", "addons/rigging/rigify/basics.html#bpy-types-armature-rigify"),
("bpy.types.bone.use_deform*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-use-deform"),
("bpy.types.booleanmodifier*", "modeling/modifiers/generate/booleans.html#bpy-types-booleanmodifier"),
("bpy.types.brush.direction*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-direction"),
("bpy.types.brush.mask_tool*", "sculpt_paint/sculpting/tools/mask.html#bpy-types-brush-mask-tool"),
("bpy.types.constraint.mute*", "animation/constraints/interface/header.html#bpy-types-constraint-mute"),
("bpy.types.constraint.name*", "animation/constraints/interface/header.html#bpy-types-constraint-name"),
@ -2798,6 +2802,7 @@ url_manual_mapping = (
("bpy.ops.wm.save_mainfile*", "files/blend/open_save.html#bpy-ops-wm-save-mainfile"),
("bpy.types.bone.show_wire*", "animation/armatures/bones/properties/display.html#bpy-types-bone-show-wire"),
("bpy.types.brush.hardness*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-hardness"),
("bpy.types.brush.strength*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-strength"),
("bpy.types.curves.surface*", "modeling/curves/primitives.html#bpy-types-curves-surface"),
("bpy.types.curvesmodifier*", "editors/video_sequencer/sequencer/sidebar/modifiers.html#bpy-types-curvesmodifier"),
("bpy.types.ffmpegsettings*", "render/output/properties/output.html#bpy-types-ffmpegsettings"),
@ -3111,6 +3116,7 @@ url_manual_mapping = (
("bpy.types.bonegroups*", "animation/armatures/properties/bone_groups.html#bpy-types-bonegroups"),
("bpy.types.bpy_struct*", "files/data_blocks.html#bpy-types-bpy-struct"),
("bpy.types.brush.rate*", "sculpt_paint/brush/stroke.html#bpy-types-brush-rate"),
("bpy.types.brush.size*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-size"),
("bpy.types.collection*", "scene_layout/collections/collections.html#bpy-types-collection"),
("bpy.types.compositor*", "compositing/index.html#bpy-types-compositor"),
("bpy.types.constraint*", "animation/constraints/index.html#bpy-types-constraint"),

View File

@ -605,9 +605,8 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
colliding_names = []
for collection in (
# Built-in names.
{"position": None, "shade_smooth": None, "normal": None, "crease": None},
{"shade_smooth": None, "normal": None, "crease": None},
mesh.attributes,
mesh.uv_layers,
None if ob is None else ob.vertex_groups,
):
if collection is None:

View File

@ -572,7 +572,7 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
bl_label = "GPU Backend"
bl_label = "GPU Back end"
@classmethod
def poll(cls, _context):
@ -589,7 +589,7 @@ class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
col.prop(system, "gpu_backend")
if system.gpu_backend != gpu.platform.backend_type_get():
layout.label(text="Requires a restart of Blender to take effect.", icon='INFO')
layout.label(text="Requires a restart of Blender to take effect", icon='INFO')
class USERPREF_PT_system_os_settings(SystemPanel, CenterAlignMixIn, Panel):

View File

@ -2696,14 +2696,14 @@ class VIEW3D_MT_object_context_menu(Menu):
if selected_objects_len > 1:
layout.operator("object.join")
if obj.type in {'MESH', 'CURVE', 'SURFACE', 'POINTCLOUD', 'META', 'FONT'}:
if obj.type in {'MESH', 'CURVE', 'CURVES', 'SURFACE', 'POINTCLOUD', 'META', 'FONT'}:
layout.operator_menu_enum("object.convert", "target")
if obj.type == 'GPENCIL':
layout.operator_menu_enum("gpencil.convert", "type", text="Convert To")
if (
obj.type in {'MESH', 'CURVE', 'SURFACE', 'GPENCIL', 'LATTICE', 'ARMATURE', 'META', 'FONT'} or
obj.type in {'MESH', 'CURVE', 'CURVES', 'SURFACE', 'GPENCIL', 'LATTICE', 'ARMATURE', 'META', 'FONT', 'POINTCLOUD'} or
(obj.type == 'EMPTY' and obj.instance_collection is not None)
):
layout.operator_context = 'INVOKE_REGION_WIN'
@ -6224,7 +6224,7 @@ class VIEW3D_PT_shading_compositor(Panel):
row.active = not is_macos
row.prop(shading, "use_compositor", expand=True)
if is_macos and shading.use_compositor != "DISABLED":
self.layout.label(text="Compositor not supported on MacOS.", icon='ERROR')
self.layout.label(text="Compositor not supported on MacOS", icon='ERROR')
class VIEW3D_PT_gizmo_display(Panel):

View File

@ -45,11 +45,17 @@ class AssetCatalogService {
Vector<std::unique_ptr<AssetCatalogCollection>> undo_snapshots_;
Vector<std::unique_ptr<AssetCatalogCollection>> redo_snapshots_;
const bool is_read_only_ = false;
public:
static const CatalogFilePath DEFAULT_CATALOG_FILENAME;
struct read_only_tag {
};
public:
AssetCatalogService();
explicit AssetCatalogService(read_only_tag);
explicit AssetCatalogService(const CatalogFilePath &asset_library_root);
/**
@ -62,11 +68,24 @@ class AssetCatalogService {
void tag_has_unsaved_changes(AssetCatalog *edited_catalog);
bool has_unsaved_changes() const;
/**
* Check if this is a read-only service meaning the user shouldn't be able to do edits. This is
* not enforced by internal catalog code, the catalog service user is responsible for it. For
* example the UI should disallow edits.
*/
bool is_read_only() const;
/** Load asset catalog definitions from the files found in the asset library. */
void load_from_disk();
/** Load asset catalog definitions from the given file or directory. */
void load_from_disk(const CatalogFilePath &file_or_directory_path);
/**
* Duplicate the catalogs from \a other_service into this one. Does not rebuild the tree, this
* needs to be done by the caller (call #rebuild_tree()!).
*/
void add_from_existing(const AssetCatalogService &other_service);
/**
* Write the catalog definitions to disk.
*
@ -105,6 +124,15 @@ class AssetCatalogService {
*/
void reload_catalogs();
/**
* Make sure the tree is updated to the latest collection of catalogs stored in this service.
* Does not depend on a CDF file being available so this can be called on a service that stores
* catalogs that are not stored in a CDF.
* Most API functions that modify catalog data will trigger this, unless otherwise specified (for
* batch operations).
*/
void rebuild_tree();
/** Return catalog with the given ID. Return nullptr if not found. */
AssetCatalog *find_catalog(CatalogID catalog_id) const;
@ -222,7 +250,6 @@ class AssetCatalogService {
const CatalogFilePath &blend_file_path);
std::unique_ptr<AssetCatalogTree> read_into_tree();
void rebuild_tree();
/**
* For every catalog, ensure that its parent path also has a known catalog.
@ -270,6 +297,11 @@ class AssetCatalogCollection {
AssetCatalogCollection(AssetCatalogCollection &&other) noexcept = default;
std::unique_ptr<AssetCatalogCollection> deep_copy() const;
/**
* Copy the catalogs from \a other and append them to this collection. Copies no other data
* otherwise.
*/
void add_catalogs_from_existing(const AssetCatalogCollection &other);
protected:
static OwningAssetCatalogMap copy_catalog_map(const OwningAssetCatalogMap &orig);

View File

@ -56,6 +56,8 @@ class AssetLibrary {
*/
std::unique_ptr<AssetStorage> asset_storage_;
std::function<void(AssetLibrary &self)> on_refresh_;
bCallbackFuncStore on_save_callback_store_{};
public:
@ -65,6 +67,8 @@ class AssetLibrary {
std::unique_ptr<AssetCatalogService> catalog_service;
friend class AssetLibraryService;
public:
/**
* \param root_path: If this is an asset library on disk, the top-level directory path.
@ -72,6 +76,16 @@ class AssetLibrary {
AssetLibrary(StringRef root_path = "");
~AssetLibrary();
/**
* Execute \a fn for every asset library that is loaded. The asset library is passed to the
* \a fn call.
*
* \param skip_all_library: When true, the \a fn will also be executed for the "All" asset
* library. This is just a combination of the other ones, so usually
* iterating over it is redundant.
*/
static void foreach_loaded(FunctionRef<void(AssetLibrary &)> fn, bool include_all_library);
void load_catalogs();
/** Load catalogs that have changed on disk. */
@ -128,9 +142,6 @@ class AssetLibrary {
AssetIdentifier asset_identifier_from_library(StringRef relative_asset_path);
StringRefNull root_path() const;
private:
std::optional<int> find_asset_index(const AssetRepresentation &asset);
};
Vector<AssetLibraryReference> all_valid_asset_library_refs();
@ -138,12 +149,22 @@ Vector<AssetLibraryReference> all_valid_asset_library_refs();
} // namespace blender::asset_system
/**
* Load the data for an asset library, but not the asset representations themselves (loading these
* is currently not done in the asset system).
*
* For the "All" asset library (#ASSET_LIBRARY_ALL), every other known asset library will be
* loaded as well. So a call to #AssetLibrary::foreach_loaded() can be expected to iterate over all
* libraries.
*
* \warning Catalogs are reloaded, invalidating catalog pointers. Do not store catalog pointers,
* store CatalogIDs instead and lookup the catalog where needed.
*/
blender::asset_system::AssetLibrary *AS_asset_library_load(
const Main *bmain, const AssetLibraryReference &library_reference);
std::string AS_asset_library_root_path_from_library_ref(
const AssetLibraryReference &library_reference);
/**
* Try to find an appropriate location for an asset library root from a file or directory path.
* Does not check if \a input_path exists.

View File

@ -43,6 +43,11 @@ AssetCatalogService::AssetCatalogService()
{
}
AssetCatalogService::AssetCatalogService(read_only_tag) : AssetCatalogService()
{
const_cast<bool &>(is_read_only_) = true;
}
AssetCatalogService::AssetCatalogService(const CatalogFilePath &asset_library_root)
: AssetCatalogService()
{
@ -51,6 +56,8 @@ AssetCatalogService::AssetCatalogService(const CatalogFilePath &asset_library_ro
void AssetCatalogService::tag_has_unsaved_changes(AssetCatalog *edited_catalog)
{
BLI_assert(!is_read_only_);
if (edited_catalog) {
edited_catalog->flags.has_unsaved_changes = true;
}
@ -85,6 +92,11 @@ bool AssetCatalogService::has_unsaved_changes() const
return catalog_collection_->has_unsaved_changes_;
}
bool AssetCatalogService::is_read_only() const
{
return is_read_only_;
}
void AssetCatalogService::tag_all_catalogs_as_unsaved_changes()
{
for (auto &catalog : catalog_collection_->catalogs_.values()) {
@ -322,6 +334,11 @@ void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_director
rebuild_tree();
}
void AssetCatalogService::add_from_existing(const AssetCatalogService &other_service)
{
catalog_collection_->add_catalogs_from_existing(*other_service.catalog_collection_);
}
void AssetCatalogService::load_directory_recursive(const CatalogFilePath &directory_path)
{
/* TODO(@sybren): implement proper multi-file support. For now, just load
@ -452,6 +469,8 @@ bool AssetCatalogService::is_catalog_known_with_unsaved_changes(const CatalogID
bool AssetCatalogService::write_to_disk(const CatalogFilePath &blend_file_path)
{
BLI_assert(!is_read_only_);
if (!write_to_disk_ex(blend_file_path)) {
return false;
}
@ -625,6 +644,7 @@ void AssetCatalogService::undo()
void AssetCatalogService::redo()
{
BLI_assert(!is_read_only_);
BLI_assert_msg(is_redo_possbile(), "Redo stack is empty");
undo_snapshots_.append(std::move(catalog_collection_));
@ -634,6 +654,7 @@ void AssetCatalogService::redo()
void AssetCatalogService::undo_push()
{
BLI_assert(!is_read_only_);
std::unique_ptr<AssetCatalogCollection> snapshot = catalog_collection_->deep_copy();
undo_snapshots_.append(std::move(snapshot));
redo_snapshots_.clear();
@ -657,15 +678,24 @@ std::unique_ptr<AssetCatalogCollection> AssetCatalogCollection::deep_copy() cons
return copy;
}
static void copy_catalog_map_into_existing(const OwningAssetCatalogMap &source,
OwningAssetCatalogMap &dest)
{
for (const auto &orig_catalog_uptr : source.values()) {
auto copy_catalog_uptr = std::make_unique<AssetCatalog>(*orig_catalog_uptr);
dest.add_new(copy_catalog_uptr->catalog_id, std::move(copy_catalog_uptr));
}
}
void AssetCatalogCollection::add_catalogs_from_existing(const AssetCatalogCollection &other)
{
copy_catalog_map_into_existing(other.catalogs_, catalogs_);
}
OwningAssetCatalogMap AssetCatalogCollection::copy_catalog_map(const OwningAssetCatalogMap &orig)
{
OwningAssetCatalogMap copy;
for (const auto &orig_catalog_uptr : orig.values()) {
auto copy_catalog_uptr = std::make_unique<AssetCatalog>(*orig_catalog_uptr);
copy.add_new(copy_catalog_uptr->catalog_id, std::move(copy_catalog_uptr));
}
copy_catalog_map_into_existing(orig, copy);
return copy;
}

View File

@ -65,6 +65,12 @@ bool AS_asset_library_has_any_unsaved_catalogs()
return service->has_any_unsaved_catalogs();
}
std::string AS_asset_library_root_path_from_library_ref(
const AssetLibraryReference &library_reference)
{
return AssetLibraryService::root_path_from_library_ref(library_reference);
}
std::string AS_asset_library_find_suitable_root_path_from_path(
const blender::StringRefNull input_path)
{
@ -114,9 +120,11 @@ void AS_asset_library_refresh_catalog_simplename(struct ::AssetLibrary *asset_li
void AS_asset_library_remap_ids(const IDRemapper *mappings)
{
AssetLibraryService *service = AssetLibraryService::get();
service->foreach_loaded_asset_library([mappings](asset_system::AssetLibrary &library) {
library.remap_ids_and_remove_invalid(*mappings);
});
service->foreach_loaded_asset_library(
[mappings](asset_system::AssetLibrary &library) {
library.remap_ids_and_remove_invalid(*mappings);
},
true);
}
namespace blender::asset_system {
@ -135,6 +143,13 @@ AssetLibrary::~AssetLibrary()
}
}
void AssetLibrary::foreach_loaded(FunctionRef<void(AssetLibrary &)> fn,
const bool include_all_library)
{
AssetLibraryService *service = AssetLibraryService::get();
service->foreach_loaded_asset_library(fn, include_all_library);
}
void AssetLibrary::load_catalogs()
{
auto catalog_service = std::make_unique<AssetCatalogService>(root_path());
@ -144,7 +159,9 @@ void AssetLibrary::load_catalogs()
void AssetLibrary::refresh()
{
this->catalog_service->reload_catalogs();
if (on_refresh_) {
on_refresh_(*this);
}
}
AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path,

View File

@ -14,6 +14,7 @@
#include "CLG_log.h"
#include "AS_asset_catalog_tree.hh"
#include "AS_asset_library.hh"
#include "asset_library_service.hh"
#include "utils.hh"
@ -56,23 +57,29 @@ void AssetLibraryService::destroy()
AssetLibrary *AssetLibraryService::get_asset_library(
const Main *bmain, const AssetLibraryReference &library_reference)
{
if (library_reference.type == ASSET_LIBRARY_LOCAL) {
/* For the "Current File" library we get the asset library root path based on main. */
std::string root_path = bmain ? AS_asset_library_find_suitable_root_path_from_main(bmain) : "";
const eAssetLibraryType type = eAssetLibraryType(library_reference.type);
if (root_path.empty()) {
/* File wasn't saved yet. */
return get_asset_library_current_file();
switch (type) {
case ASSET_LIBRARY_LOCAL: {
/* For the "Current File" library we get the asset library root path based on main. */
std::string root_path = bmain ? AS_asset_library_find_suitable_root_path_from_main(bmain) :
"";
if (root_path.empty()) {
/* File wasn't saved yet. */
return get_asset_library_current_file();
}
return get_asset_library_on_disk(root_path);
}
case ASSET_LIBRARY_ALL:
return get_asset_library_all(bmain);
case ASSET_LIBRARY_CUSTOM_FROM_PREFERENCES: {
std::string root_path = root_path_from_library_ref(library_reference);
return get_asset_library_on_disk(root_path);
}
if (library_reference.type == ASSET_LIBRARY_CUSTOM_FROM_PREFERENCES) {
CustomAssetLibraryDefinition *user_library = BKE_asset_library_custom_find_from_index(
&U.asset_libraries, library_reference.custom_library_index);
if (user_library) {
return get_asset_library_on_disk(user_library->path);
if (!root_path.empty()) {
return get_asset_library_on_disk(root_path);
}
break;
}
}
/* TODO project libraries */
@ -101,6 +108,8 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(StringRefNull root_
lib->on_blend_save_handler_register();
lib->load_catalogs();
/* Reload catalogs on refresh. */
lib->on_refresh_ = [](AssetLibrary &self) { self.catalog_service->reload_catalogs(); };
on_disk_libraries_.add_new(normalized_root_path, std::move(lib_uptr));
CLOG_INFO(&LOG, 2, "get \"%s\" (loaded)", normalized_root_path.c_str());
@ -111,6 +120,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_current_file()
{
if (current_file_library_) {
CLOG_INFO(&LOG, 2, "get current file lib (cached)");
current_file_library_->refresh();
}
else {
CLOG_INFO(&LOG, 2, "get current file lib (loaded)");
@ -122,6 +132,74 @@ AssetLibrary *AssetLibraryService::get_asset_library_current_file()
return lib;
}
static void rebuild_all_library(AssetLibrary &all_library, const bool reload_catalogs)
{
/* Start with empty catalog storage. */
all_library.catalog_service = std::make_unique<AssetCatalogService>(
AssetCatalogService::read_only_tag());
AssetLibrary::foreach_loaded(
[&](AssetLibrary &nested) {
if (reload_catalogs) {
nested.catalog_service->reload_catalogs();
}
all_library.catalog_service->add_from_existing(*nested.catalog_service);
},
false);
all_library.catalog_service->rebuild_tree();
}
AssetLibrary *AssetLibraryService::get_asset_library_all(const Main *bmain)
{
/* (Re-)load all other asset libraries. */
for (AssetLibraryReference &library_ref : all_valid_asset_library_refs()) {
/* Skip self :) */
if (library_ref.type == ASSET_LIBRARY_ALL) {
continue;
}
/* Ensure all asset libraries are loaded. */
get_asset_library(bmain, library_ref);
}
if (all_library_) {
CLOG_INFO(&LOG, 2, "get all lib (cached)");
all_library_->refresh();
return all_library_.get();
}
CLOG_INFO(&LOG, 2, "get all lib (loaded)");
all_library_ = std::make_unique<AssetLibrary>();
/* Don't reload catalogs on this initial read, they've just been loaded above. */
rebuild_all_library(*all_library_, /*reload_catlogs=*/false);
all_library_->on_refresh_ = [](AssetLibrary &all_library) {
rebuild_all_library(all_library, /*reload_catalogs=*/true);
};
return all_library_.get();
}
std::string AssetLibraryService::root_path_from_library_ref(
const AssetLibraryReference &library_reference)
{
if (ELEM(library_reference.type, ASSET_LIBRARY_ALL, ASSET_LIBRARY_LOCAL)) {
return "";
}
BLI_assert(library_reference.type == ASSET_LIBRARY_CUSTOM);
BLI_assert(library_reference.custom_library_index >= 0);
bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index(
&U, library_reference.custom_library_index);
if (!user_library || !user_library->path[0]) {
return "";
}
return user_library->path;
}
void AssetLibraryService::allocate_service_instance()
{
instance_ = std::make_unique<AssetLibraryService>();
@ -165,21 +243,25 @@ void AssetLibraryService::app_handler_unregister()
bool AssetLibraryService::has_any_unsaved_catalogs() const
{
if (current_file_library_ && current_file_library_->catalog_service->has_unsaved_changes()) {
return true;
}
bool has_unsaved_changes = false;
for (const auto &asset_lib_uptr : on_disk_libraries_.values()) {
if (asset_lib_uptr->catalog_service->has_unsaved_changes()) {
return true;
}
}
return false;
foreach_loaded_asset_library(
[&has_unsaved_changes](AssetLibrary &library) {
if (library.catalog_service->has_unsaved_changes()) {
has_unsaved_changes = true;
}
},
true);
return has_unsaved_changes;
}
void AssetLibraryService::foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn) const
void AssetLibraryService::foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn,
const bool include_all_library) const
{
if (include_all_library && all_library_) {
fn(*all_library_);
}
if (current_file_library_) {
fn(*current_file_library_);
}

View File

@ -40,6 +40,8 @@ class AssetLibraryService {
* the file was saved, a valid path for the library can be determined and #on_disk_libraries_
* above should be used. */
std::unique_ptr<AssetLibrary> current_file_library_;
/** The "all" asset library, merging all other libraries into one. */
std::unique_ptr<AssetLibrary> all_library_;
/* Handlers for managing the life cycle of the AssetLibraryService instance. */
bCallbackFuncStore on_load_callback_store_;
@ -55,6 +57,8 @@ class AssetLibraryService {
/** Destroy the AssetLibraryService singleton. It will be reallocated by #get() if necessary. */
static void destroy();
static std::string root_path_from_library_ref(const AssetLibraryReference &library_reference);
AssetLibrary *get_asset_library(const Main *bmain,
const AssetLibraryReference &library_reference);
@ -66,10 +70,15 @@ class AssetLibraryService {
/** Get the "Current File" asset library. */
AssetLibrary *get_asset_library_current_file();
/** Get the "All" asset library, which loads all others and merges them into one. */
AssetLibrary *get_asset_library_all(const Main *bmain);
/** Returns whether there are any known asset libraries with unsaved catalog edits. */
bool has_any_unsaved_catalogs() const;
void foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn) const;
/** See AssetLibrary::foreach_loaded(). */
void foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn,
bool include_all_library) const;
protected:
/** Allocate a new instance of the service and assign it to `instance_`. */

View File

@ -257,6 +257,22 @@ static const char32_t *blf_get_sample_text(FT_Face face)
count_bits_i((uint)os2_table->ulUnicodeRange3) +
count_bits_i((uint)os2_table->ulUnicodeRange4);
/* Use OS/2 Table code page range bits to differentiate between (combined) CJK fonts.
* See https://learn.microsoft.com/en-us/typography/opentype/spec/os2#cpr */
FT_ULong codepages = os2_table->ulCodePageRange1;
if (codepages & (1 << 19) || codepages & (1 << 21)) {
return U"\ud55c\uad6d\uc5b4"; /* 한국어 Korean. */
}
if (codepages & (1 << 20)) {
return U"\u7E41\u9AD4\u5B57"; /* 繁體字 Traditional Chinese. */
}
if (codepages & (1 << 17) && !(codepages & (1 << 18))) {
return U"\u65E5\u672C\u8A9E"; /* 日本語 Japanese. */
}
if (codepages & (1 << 18) && !(codepages & (1 << 17))) {
return U"\u7B80\u4F53\u5B57"; /* 简体字 Simplified Chinese. */
}
for (uint i = 0; i < ARRAY_SIZE(unicode_samples); ++i) {
const UnicodeSample *s = &unicode_samples[i];
if (os2_table && s->field && s->mask) {

View File

@ -61,7 +61,6 @@ struct CustomData_MeshMasks;
struct Depsgraph;
struct MEdge;
struct MFace;
struct MVert;
struct Mesh;
struct ModifierData;
struct Object;
@ -125,7 +124,10 @@ struct DerivedMesh {
* and freed on the next ->release(). consider using getVert/Edge/Face if
* you are only interested in a few verts/edges/faces.
*/
struct MVert *(*getVertArray)(DerivedMesh *dm);
/**
* \warning The real return type is `float(*)[3]`.
*/
float *(*getVertArray)(DerivedMesh *dm);
struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
struct MLoop *(*getLoopArray)(DerivedMesh *dm);
struct MPoly *(*getPolyArray)(DerivedMesh *dm);
@ -133,7 +135,7 @@ struct DerivedMesh {
/** Copy all verts/edges/faces from the derived mesh into
* *{vert/edge/face}_r (must point to a buffer large enough)
*/
void (*copyVertArray)(DerivedMesh *dm, struct MVert *r_vert);
void (*copyVertArray)(DerivedMesh *dm, float (*r_positions)[3]);
void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge);
void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop);
void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly);

View File

@ -47,6 +47,8 @@ class AnonymousAttributeID {
return name_;
}
virtual std::string user_name() const;
void user_add() const
{
users_.fetch_add(1);

View File

@ -131,6 +131,10 @@ struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const
bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname);
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer);
const char *BKE_uv_map_edge_select_name_get(const char *uv_map_name, char *buffer);
const char *BKE_uv_map_pin_name_get(const char *uv_map_name, char *buffer);
#ifdef __cplusplus
}
#endif

View File

@ -8,7 +8,7 @@
#include "BLI_function_ref.hh"
#include "BLI_generic_span.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BKE_anonymous_attribute_id.hh"
@ -17,7 +17,9 @@
struct Mesh;
struct PointCloud;
namespace blender::fn {
namespace multi_function {
class MultiFunction;
}
class GField;
} // namespace blender::fn
@ -174,7 +176,7 @@ struct AttributeValidator {
/**
* Single input, single output function that corrects attribute values if necessary.
*/
const fn::MultiFunction *function;
const fn::multi_function::MultiFunction *function;
operator bool() const
{

View File

@ -25,7 +25,6 @@ extern "C" {
struct BMEditMesh;
struct MFace;
struct MVert;
struct Mesh;
struct PointCloud;
@ -59,7 +58,7 @@ typedef struct BVHTreeFromMesh {
BVHTree_RayCastCallback raycast_callback;
/* Vertex array, so that callbacks have instant access to data. */
const struct MVert *vert;
const float (*vert_positions)[3];
const struct MEdge *edge;
const struct MFace *face;
const struct MLoop *loop;
@ -123,7 +122,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
* (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
const float (*vert_positions)[3],
int verts_num,
const blender::BitVector<> &verts_mask,
int verts_num_active,
@ -154,7 +153,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
* (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
const float (*vert_positions)[3],
const struct MEdge *edge,
int edges_num,
const blender::BitVector<> &edges_mask,
@ -181,7 +180,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
* Builds a BVH-tree where nodes are the looptri faces of the given mesh.
*/
BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
const float (*vert_positions)[3],
const struct MLoop *mloop,
const struct MLoopTri *looptri,
int looptri_num,

View File

@ -72,7 +72,7 @@ typedef struct Cloth {
unsigned char pad2;
short pad3;
struct BVHTree *bvhtree; /* collision tree for this cloth object */
struct BVHTree *bvhselftree; /* collision tree for this cloth object */
struct BVHTree *bvhselftree; /* collision tree for this cloth object (may be same as bvhtree) */
struct MVertTri *tri;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct EdgeSet *edgeset; /* used for selfcollisions */

View File

@ -14,7 +14,6 @@ struct BVHTree;
struct Collection;
struct CollisionModifierData;
struct Depsgraph;
struct MVert;
struct MVertTri;
struct Object;
struct Scene;
@ -55,6 +54,8 @@ typedef struct CollPair {
#else
int ap1, ap2, ap3, bp1, bp2, bp3;
#endif
/* Barycentric weights of the collision point. */
float aw1, aw2, aw3, bw1, bw2, bw3;
int pointsb[4];
} CollPair;
@ -88,13 +89,13 @@ typedef struct FaceCollPair {
// used in modifier.cc from collision.c
/////////////////////////////////////////////////
struct BVHTree *bvhtree_build_from_mvert(const struct MVert *mvert,
struct BVHTree *bvhtree_build_from_mvert(const float (*positions)[3],
const struct MVertTri *tri,
int tri_num,
float epsilon);
void bvhtree_update_from_mvert(struct BVHTree *bvhtree,
const struct MVert *mvert,
const struct MVert *mvert_moving,
const float (*positions)[3],
const float (*positions_moving)[3],
const struct MVertTri *tri,
int tri_num,
bool moving);

View File

@ -7,7 +7,7 @@
#pragma once
#include "BLI_float3x3.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
struct Depsgraph;

View File

@ -2,7 +2,6 @@
#pragma once
struct CurvesGeometry;
struct Mesh;
/** \file
@ -11,6 +10,7 @@ struct Mesh;
namespace blender::bke {
class CurvesGeometry;
class AnonymousAttributePropagationInfo;
/**

View File

@ -17,7 +17,7 @@
#include "BLI_float4x4.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_shared_cache.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"

View File

@ -31,6 +31,28 @@ struct CustomData_MeshMasks;
struct ID;
typedef uint64_t eCustomDataMask;
/* These names are used as prefixes for UV layer names to find the associated boolean
* layers. They should never be longer than 2 chars, as MAX_CUSTOMDATA_LAYER_NAME
* has 4 extra bytes above what can be used for the base layer name, and these
* prefixes are placed between 2 '.'s at the start of the layer name.
* For example The uv vert selection layer of a layer named 'UVMap.001'
* will be called '.vs.UVMap.001' . */
#define UV_VERTSEL_NAME "vs"
#define UV_EDGESEL_NAME "es"
#define UV_PINNED_NAME "pn"
/**
* UV map related customdata offsets into BMesh attribute blocks. See #BM_uv_map_get_offsets.
* Defined in #BKE_customdata.h to avoid including bmesh.h in many unrelated areas.
* An offset of -1 means that the corresponding layer does not exist.
*/
typedef struct BMUVOffsets {
int uv;
int select_vert;
int select_edge;
int pin;
} BMUVOffsets;
/* A data type large enough to hold 1 element from any custom-data layer type. */
typedef struct {
unsigned char data[64];
@ -125,7 +147,7 @@ void CustomData_data_mix_value(
/**
* Compares if data1 is equal to data2. type is a valid CustomData type
* enum (e.g. #CD_MLOOPUV). the layer type's equal function is used to compare
* enum (e.g. #CD_PROP_FLOAT). the layer type's equal function is used to compare
* the data, if it exists, otherwise #memcmp is used.
*/
bool CustomData_data_equals(int type, const void *data1, const void *data2);
@ -422,6 +444,7 @@ int CustomData_get_n_offset(const struct CustomData *data, int type, int n);
int CustomData_get_layer_index(const struct CustomData *data, int type);
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n);
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name);
int CustomData_get_named_layer_index_notype(const struct CustomData *data, const char *name);
int CustomData_get_active_layer_index(const struct CustomData *data, int type);
int CustomData_get_render_layer_index(const struct CustomData *data, int type);
int CustomData_get_clone_layer_index(const struct CustomData *data, int type);
@ -531,6 +554,13 @@ bool CustomData_layertype_is_dynamic(int type);
*/
int CustomData_layertype_layers_max(int type);
#ifdef __cplusplus
/** \return The maximum length for a layer name with the given prefix. */
int CustomData_name_max_length_calc(blender::StringRef name);
#endif
/**
* Make sure the name of layer at index is unique.
*/
@ -604,8 +634,9 @@ enum {
CD_FAKE_SEAM = CD_FAKE | 100, /* UV seam flag for edges. */
/* Multiple types of mesh elements... */
CD_FAKE_UV = CD_FAKE |
CD_MLOOPUV, /* UV flag, because we handle both loop's UVs and poly's textures. */
CD_FAKE_UV =
CD_FAKE |
CD_PROP_FLOAT2, /* UV flag, because we handle both loop's UVs and poly's textures. */
CD_FAKE_LNOR = CD_FAKE |
CD_CUSTOMLOOPNORMAL, /* Because we play with clnor and temp lnor layers here. */

View File

@ -9,6 +9,7 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "DNA_customdata_types.h"
/**
* \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
@ -19,7 +20,7 @@ extern "C" {
*/
void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len,
const float (*poly_normals)[3],
const float (*loop_normals)[3],

View File

@ -268,7 +268,7 @@ class AnonymousAttributeFieldInput : public GeometryFieldInput {
AnonymousAttributeFieldInput(AutoAnonymousAttributeID anonymous_id,
const CPPType &type,
std::string producer_name)
: GeometryFieldInput(type, anonymous_id->name()),
: GeometryFieldInput(type, anonymous_id->user_name()),
anonymous_id_(std::move(anonymous_id)),
producer_name_(producer_name)
{

View File

@ -14,7 +14,7 @@
#include "BLI_function_ref.hh"
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BLI_user_counter.hh"
#include "BLI_vector_set.hh"

View File

@ -9,7 +9,7 @@
#include "DNA_image_types.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
namespace blender::bke::image {

View File

@ -13,7 +13,6 @@ struct Lattice;
struct ListBase;
struct Main;
struct Mesh;
struct MVert;
struct Object;
/* Kernel prototypes */
@ -132,7 +131,9 @@ void BKE_keyblock_update_from_mesh(const struct Mesh *me, struct KeyBlock *kb);
void BKE_keyblock_convert_from_mesh(const struct Mesh *me,
const struct Key *key,
struct KeyBlock *kb);
void BKE_keyblock_convert_to_mesh(const struct KeyBlock *kb, struct MVert *mvert, int totvert);
void BKE_keyblock_convert_to_mesh(const struct KeyBlock *kb,
float (*vert_positions)[3],
int totvert);
/**
* Computes normals (vertices, polygons and/or loops ones) of given mesh for given shape key.

View File

@ -401,7 +401,7 @@ bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct
* Compare local and reference data-blocks and create new override operations as needed,
* or reset to reference values if overriding is not allowed.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Defining override operations is only mandatory before saving a `.blend` file on disk
* (not for undo!).
@ -417,7 +417,7 @@ void BKE_lib_override_library_operations_create(struct Main *bmain,
/**
* Check all overrides from given \a bmain and create/update overriding operations as needed.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*/
void BKE_lib_override_library_main_operations_create(struct Main *bmain,
bool force_auto,
@ -427,7 +427,7 @@ void BKE_lib_override_library_main_operations_create(struct Main *bmain,
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.
@ -439,7 +439,7 @@ void BKE_lib_override_library_operations_restore(struct Main *bmain,
* Restore forbidden modified override properties to the values of their matching properties in the
* linked reference ID, for all liboverride IDs tagged as needing such process in given `bmain`.
*
* \param r_report_flags #eRNAOverrideMatchResult flags giving info about the result of this call.
* \param r_report_flags: #eRNAOverrideMatchResult flags giving info about the result of this call.
*
* \note Typically used as part of BKE_lib_override_library_main_operations_create process, since
* modifying RNA properties from non-main threads is not safe.

View File

@ -36,9 +36,7 @@ struct MEdge;
struct MFace;
struct MLoop;
struct MLoopTri;
struct MLoopUV;
struct MPoly;
struct MVert;
struct Main;
struct MemArena;
struct Mesh;
@ -193,6 +191,8 @@ struct Mesh *BKE_mesh_new_nomain_from_curve(const struct Object *ob);
struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
const struct ListBase *dispbase);
bool BKE_mesh_attribute_required(const char *name);
bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
@ -324,7 +324,7 @@ void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]
*/
void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
const struct MPoly *mpoly,
const struct MVert *mvert,
const float (*vert_positions)[3],
int totloop,
int totpoly,
struct MLoopTri *mlooptri);
@ -338,7 +338,7 @@ void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
*/
void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
const struct MPoly *mpoly,
const struct MVert *mvert,
const float (*vert_positions)[3],
int totloop,
int totpoly,
struct MLoopTri *mlooptri,
@ -420,12 +420,8 @@ bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray,
const float (*vert_positions)[3],
float r_no[3]);
void BKE_mesh_calc_poly_normal_coords(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const float (*vertex_coords)[3],
float r_no[3]);
/**
* Calculate face normals directly into a result array.
@ -433,7 +429,7 @@ void BKE_mesh_calc_poly_normal_coords(const struct MPoly *mpoly,
* \note Usually #BKE_mesh_poly_normals_ensure is the preferred way to access face normals,
* since they may already be calculated and cached on the mesh.
*/
void BKE_mesh_calc_normals_poly(const struct MVert *mvert,
void BKE_mesh_calc_normals_poly(const float (*vert_positions)[3],
int mvert_len,
const struct MLoop *mloop,
int mloop_len,
@ -447,7 +443,7 @@ void BKE_mesh_calc_normals_poly(const struct MVert *mvert,
* \note Usually #BKE_mesh_vertex_normals_ensure is the preferred way to access vertex normals,
* since they may already be calculated and cached on the mesh.
*/
void BKE_mesh_calc_normals_poly_and_vertex(const struct MVert *mvert,
void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
int mvert_len,
const struct MLoop *mloop,
int mloop_len,
@ -597,7 +593,7 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
*
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
*/
void BKE_mesh_normals_loop_split(const struct MVert *mverts,
void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
const float (*vert_normals)[3],
int numVerts,
const struct MEdge *medges,
@ -614,7 +610,7 @@ void BKE_mesh_normals_loop_split(const struct MVert *mverts,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2]);
void BKE_mesh_normals_loop_custom_set(const struct MVert *mverts,
void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
int numVerts,
struct MEdge *medges,
@ -626,7 +622,7 @@ void BKE_mesh_normals_loop_custom_set(const struct MVert *mverts,
const float (*poly_normals)[3],
int numPolys,
short (*r_clnors_data)[2]);
void BKE_mesh_normals_loop_custom_from_verts_set(const struct MVert *mverts,
void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
float (*r_custom_vert_normals)[3],
int numVerts,
@ -689,17 +685,16 @@ void BKE_mesh_set_custom_normals_from_verts(struct Mesh *mesh, float (*r_custom_
void BKE_mesh_calc_poly_center(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray,
const float (*vert_positions)[3],
float r_cent[3]);
/* NOTE: passing poly-normal is only a speedup so we can skip calculating it. */
float BKE_mesh_calc_poly_area(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray);
const float (*vert_positions)[3]);
float BKE_mesh_calc_area(const struct Mesh *me);
float BKE_mesh_calc_poly_uv_area(const struct MPoly *mpoly, const struct MLoopUV *uv_array);
void BKE_mesh_calc_poly_angles(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray,
const float (*vert_positions)[3],
float angles[]);
void BKE_mesh_poly_edgehash_insert(struct EdgeHash *ehash,
@ -729,7 +724,7 @@ bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3]);
* \param r_volume: Volume (unsigned).
* \param r_center: Center of mass.
*/
void BKE_mesh_calc_volume(const struct MVert *mverts,
void BKE_mesh_calc_volume(const float (*vert_positions)[3],
int mverts_num,
const struct MLoopTri *mlooptri,
int looptri_num,
@ -888,7 +883,7 @@ bool BKE_mesh_validate_material_indices(struct Mesh *me);
* by importers that load normals (for example).
*/
bool BKE_mesh_validate_arrays(struct Mesh *me,
struct MVert *mverts,
float (*vert_positions)[3],
unsigned int totvert,
struct MEdge *medges,
unsigned int totedge,
@ -992,13 +987,14 @@ BLI_INLINE int *BKE_mesh_material_indices_for_write(Mesh *mesh)
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, NULL, mesh->totpoly, "material_index");
}
BLI_INLINE const MVert *BKE_mesh_verts(const Mesh *mesh)
BLI_INLINE const float (*BKE_mesh_vert_positions(const Mesh *mesh))[3]
{
return (const MVert *)CustomData_get_layer(&mesh->vdata, CD_MVERT);
return (const float(*)[3])CustomData_get_layer_named(&mesh->vdata, CD_PROP_FLOAT3, "position");
}
BLI_INLINE MVert *BKE_mesh_verts_for_write(Mesh *mesh)
BLI_INLINE float (*BKE_mesh_vert_positions_for_write(Mesh *mesh))[3]
{
return (MVert *)CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
return (float(*)[3])CustomData_duplicate_referenced_layer_named(
&mesh->vdata, CD_PROP_FLOAT3, "position", mesh->totvert);
}
BLI_INLINE const MEdge *BKE_mesh_edges(const Mesh *mesh)
@ -1049,15 +1045,17 @@ BLI_INLINE MDeformVert *BKE_mesh_deform_verts_for_write(Mesh *mesh)
#ifdef __cplusplus
# include "BLI_math_vector_types.hh"
# include "BLI_span.hh"
inline blender::Span<MVert> Mesh::verts() const
inline blender::Span<blender::float3> Mesh::vert_positions() const
{
return {BKE_mesh_verts(this), this->totvert};
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_positions(this)), this->totvert};
}
inline blender::MutableSpan<MVert> Mesh::verts_for_write()
inline blender::MutableSpan<blender::float3> Mesh::vert_positions_for_write()
{
return {BKE_mesh_verts_for_write(this), this->totvert};
return {reinterpret_cast<blender::float3 *>(BKE_mesh_vert_positions_for_write(this)),
this->totvert};
}
inline blender::Span<MEdge> Mesh::edges() const

View File

@ -29,10 +29,10 @@ void BKE_bmesh_prefair_and_fair_verts(struct BMesh *bm,
bool *affect_verts,
eMeshFairingDepth depth);
/* This function can optionally use the MVert coordinates of deform_mverts to read and write the
* fairing result. When NULL, the function will use mesh->mverts directly. */
/* This function can optionally use the vertex coordinates of deform_mverts to read and write the
* fairing result. When NULL, the function will use mesh positions directly. */
void BKE_mesh_prefair_and_fair_verts(struct Mesh *mesh,
struct MVert *deform_mverts,
float (*deform_vert_positions)[3],
bool *affect_verts,
eMeshFairingDepth depth);

View File

@ -10,7 +10,9 @@
#include "BLI_utildefines.h"
#ifdef __cplusplus
# include "BLI_resource_scope.hh"
# include "BLI_span.hh"
# include "BLI_vector.hh"
# include "DNA_customdata_types.h"
#endif
@ -24,6 +26,11 @@ struct MFace;
#ifdef __cplusplus
void BKE_mesh_legacy_convert_uvs_to_struct(Mesh *mesh,
blender::ResourceScope &temp_mloopuv_for_convert,
blender::Vector<CustomDataLayer, 16> &layers_to_write);
void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh);
/**
* Move face sets to the legacy type from a generic type.
*/
@ -88,6 +95,13 @@ void BKE_mesh_legacy_convert_loose_edges_to_flag(struct Mesh *mesh);
void BKE_mesh_legacy_attribute_flags_to_strings(struct Mesh *mesh);
void BKE_mesh_legacy_attribute_strings_to_flags(struct Mesh *mesh);
struct MVert *BKE_mesh_legacy_convert_positions_to_verts(
Mesh *mesh,
blender::ResourceScope &temp_arrays_for_convert,
blender::Vector<CustomDataLayer, 16> &vert_layers_to_write);
void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh);
#endif
/**

View File

@ -17,9 +17,7 @@ extern "C" {
struct MEdge;
struct MLoop;
struct MLoopTri;
struct MLoopUV;
struct MPoly;
struct MVert;
/* UvVertMap */
#define STD_UV_CONNECT_LIMIT 0.0001f
@ -106,7 +104,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly,
const bool *hide_poly,
const bool *select_poly,
const struct MLoop *mloop,
const struct MLoopUV *mloopuv,
const float (*mloopuv)[2],
unsigned int totpoly,
unsigned int totvert,
const float limit[2],
@ -146,7 +144,6 @@ void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
*/
void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
int **r_mem,
const struct MVert *mvert,
int totvert,
const struct MLoopTri *mlooptri,
int totlooptri,
@ -260,7 +257,7 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store,
int num_innercut_items,
int *innercut_item_indices);
typedef bool (*MeshRemapIslandsCalc)(const struct MVert *verts,
typedef bool (*MeshRemapIslandsCalc)(const float (*vert_positions)[3],
int totvert,
const struct MEdge *edges,
int totedge,
@ -277,7 +274,7 @@ typedef bool (*MeshRemapIslandsCalc)(const struct MVert *verts,
* Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams),
* not some UV layers coordinates.
*/
bool BKE_mesh_calc_islands_loop_poly_edgeseam(const struct MVert *verts,
bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
int totvert,
const struct MEdge *edges,
int totedge,
@ -290,7 +287,7 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const struct MVert *verts,
/**
* Calculate UV islands.
*
* \note If no MLoopUV layer is passed, we only consider edges tagged as seams as UV boundaries.
* \note If no UV layer is passed, we only consider edges tagged as seams as UV boundaries.
* This has the advantages of simplicity, and being valid/common to all UV maps.
* However, it means actual UV islands without matching UV seams will not be handled correctly.
* If a valid UV layer is passed as \a luvs parameter,
@ -300,7 +297,7 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const struct MVert *verts,
* Not sure it would be worth the more complex code, though,
* those loops are supposed to be really quick to do.
*/
bool BKE_mesh_calc_islands_loop_poly_uvmap(struct MVert *verts,
bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
int totvert,
struct MEdge *edges,
int totedge,
@ -308,7 +305,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(struct MVert *verts,
int totpoly,
struct MLoop *loops,
int totloop,
const struct MLoopUV *luvs,
const float (*luvs)[2],
MeshIslandStore *r_island_store);
/**

View File

@ -12,7 +12,6 @@ extern "C" {
struct CustomData;
struct CustomData_MeshMasks;
struct MVert;
struct MemArena;
struct Mesh;
@ -158,14 +157,14 @@ void BKE_mesh_remap_calc_source_cddata_masks_from_map_modes(
* in favor of a global good matching.
*/
float BKE_mesh_remap_calc_difference_from_mesh(const struct SpaceTransform *space_transform,
const struct MVert *verts_dst,
const float (*vert_positions_dst)[3],
int numverts_dst,
struct Mesh *me_src);
/**
* Set r_space_transform so that best bbox of dst matches best bbox of src.
*/
void BKE_mesh_remap_find_best_match_from_mesh(const struct MVert *verts_dst,
void BKE_mesh_remap_find_best_match_from_mesh(const float (*vert_positions_dst)[3],
int numverts_dst,
struct Mesh *me_src,
struct SpaceTransform *r_space_transform);
@ -174,7 +173,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(int mode,
const struct SpaceTransform *space_transform,
float max_dist,
float ray_radius,
const struct MVert *verts_dst,
const float (*vert_positions_dst)[3],
int numverts_dst,
bool dirty_nors_dst,
struct Mesh *me_src,
@ -185,7 +184,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(int mode,
const struct SpaceTransform *space_transform,
float max_dist,
float ray_radius,
const struct MVert *verts_dst,
const float (*vert_positions_dst)[3],
int numverts_dst,
const struct MEdge *edges_dst,
int numedges_dst,
@ -199,7 +198,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode,
float max_dist,
float ray_radius,
struct Mesh *mesh_dst,
const struct MVert *verts_dst,
const float (*vert_positions_dst)[3],
int numverts_dst,
const struct MEdge *edges_dst,
int numedges_dst,
@ -221,7 +220,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(int mode,
float max_dist,
float ray_radius,
const struct Mesh *mesh_dst,
const struct MVert *verts_dst,
const float (*vert_positions_dst)[3],
const struct MLoop *loops_dst,
const struct MPoly *polys_dst,
int numpolys_dst,

View File

@ -8,7 +8,7 @@
#include "BLI_function_ref.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "DNA_meshdata_types.h"
@ -127,7 +127,7 @@ int sample_surface_points_projected(
Vector<int> &r_looptri_indices,
Vector<float3> &r_positions);
float3 compute_bary_coord_in_triangle(Span<MVert> verts,
float3 compute_bary_coord_in_triangle(Span<float3> vert_positions,
Span<MLoop> loops,
const MLoopTri &looptri,
const float3 &position);

View File

@ -17,12 +17,12 @@ struct ReportList;
* split normals can be used to recreate the full tangent space.
* NOTE: * The mesh should be made of only tris and quads!
*/
void BKE_mesh_calc_loop_tangent_single_ex(const struct MVert *mverts,
void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
int numVerts,
const struct MLoop *mloops,
float (*r_looptangent)[4],
const float (*loop_normals)[3],
const struct MLoopUV *loopuv,
const float (*loopuv)[2],
int numLoops,
const struct MPoly *mpolys,
int numPolys,
@ -41,7 +41,7 @@ void BKE_mesh_calc_loop_tangent_single(struct Mesh *mesh,
/**
* See: #BKE_editmesh_loop_tangent_calc (matching logic).
*/
void BKE_mesh_calc_loop_tangent_ex(const struct MVert *mvert,
void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
const struct MPoly *mpoly,
uint mpoly_len,
const struct MLoop *mloop,
@ -50,7 +50,7 @@ void BKE_mesh_calc_loop_tangent_ex(const struct MVert *mvert,
struct CustomData *loopdata,
bool calc_active_tangent,
const char (*tangent_names)[64],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len,
const float (*vert_normals)[3],
const float (*poly_normals)[3],
@ -63,7 +63,7 @@ void BKE_mesh_calc_loop_tangent_ex(const struct MVert *mvert,
void BKE_mesh_calc_loop_tangents(struct Mesh *me_eval,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len);
/* Helpers */
@ -81,7 +81,7 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(struct CustomData *uv_data,
*/
void BKE_mesh_calc_loop_tangent_step_0(const struct CustomData *loopData,
bool calc_active_tangent,
const char (*tangent_names)[64],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_count,
bool *rcalc_act,
bool *rcalc_ren,

View File

@ -16,7 +16,7 @@
# include "BLI_array.hh"
# include "BLI_bit_vector.hh"
# include "BLI_bounds_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
# include "BLI_span.hh"
@ -47,7 +47,7 @@ typedef enum eMeshBatchDirtyMode {
/** #MeshRuntime.wrapper_type */
typedef enum eMeshWrapperType {
/** Use mesh data (#Mesh.mvert, #Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
/** Use mesh data (#Mesh.vert_positions(), #Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
ME_WRAPPER_TYPE_MDATA = 0,
/** Use edit-mesh data (#Mesh.edit_mesh, #MeshRuntime.edit_data). */
ME_WRAPPER_TYPE_BMESH = 1,

View File

@ -27,7 +27,6 @@ struct SubdivCCG;
struct MLoop;
struct MLoopTri;
struct MPoly;
struct MVert;
/**
* Delete mesh mdisps and grid paint masks.

View File

@ -107,9 +107,6 @@ class GeoNodeExecParams;
class NodeDeclarationBuilder;
class GatherLinkSearchOpParams;
} // namespace nodes
namespace fn {
class MFDataType;
} // namespace fn
namespace realtime_compositor {
class Context;
class NodeOperation;
@ -693,7 +690,7 @@ void nodeRemoveNode(struct Main *bmain,
void nodeDimensionsGet(const struct bNode *node, float *r_width, float *r_height);
void nodeTagUpdateID(struct bNode *node);
void nodeInternalLinks(struct bNode *node, struct bNodeLink ***r_links, int *r_len);
void nodeInternalLinks(struct bNode *node, struct bNodeLink **r_links, int *r_len);
#ifdef __cplusplus

View File

@ -169,13 +169,6 @@ class bNodeSocketRuntime : NonCopyable, NonMovable {
/** #eNodeTreeChangedFlag. */
uint32_t changed_flag = 0;
/**
* The location of the sockets, in the view-space of the node editor.
* \note Only calculated when drawing.
*/
float locx = 0;
float locy = 0;
/**
* Runtime-only cache of the number of input links, for multi-input sockets,
* including dragged node links that aren't actually in the tree.
@ -261,7 +254,7 @@ class bNodeRuntime : NonCopyable, NonMovable {
float anim_ofsx;
/** List of cached internal links (input to output), for muted nodes and operators. */
Vector<bNodeLink *> internal_links;
Vector<bNodeLink> internal_links;
/** Eagerly maintained cache of the node's index in the tree. */
int index_in_tree = -1;
@ -633,7 +626,7 @@ inline bool bNode::is_group_output() const
return this->type == NODE_GROUP_OUTPUT;
}
inline blender::Span<const bNodeLink *> bNode::internal_links() const
inline blender::Span<bNodeLink> bNode::internal_links() const
{
return this->runtime->internal_links;
}

View File

@ -39,7 +39,6 @@ struct ImageUser;
struct ListBase;
struct MLoop;
struct MLoopTri;
struct MVert;
struct Main;
struct Mesh;
struct MeshElemMap;
@ -577,7 +576,7 @@ typedef struct SculptSession {
struct Depsgraph *depsgraph;
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
struct MVert *mvert;
float (*vert_positions)[3];
const struct MPoly *mpoly;
const struct MLoop *mloop;

View File

@ -36,7 +36,6 @@ struct LinkNode;
struct MCol;
struct MFace;
struct MTFace;
struct MVert;
struct Main;
struct ModifierData;
struct Object;
@ -267,7 +266,7 @@ BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float ve
}
/* ----------- functions needed outside particlesystem ---------------- */
/* particle.c */
/* particle.cc */
/* Few helpers for count-all etc. */
@ -540,7 +539,7 @@ void BKE_particlesystem_reset_all(struct Object *object);
/* ----------- functions needed only inside particlesystem ------------ */
/* particle.c */
/* particle.cc */
void psys_disable_all(struct Object *ob);
void psys_enable_all(struct Object *ob);
@ -583,7 +582,7 @@ void psys_get_texture(struct ParticleSimulationData *sim,
* Interpolate a location on a face based on face coordinates.
*/
void psys_interpolate_face(struct Mesh *mesh,
const struct MVert *mvert,
const float (*vert_positions)[3],
const float (*vert_normals)[3],
struct MFace *mface,
struct MTFace *tface,

View File

@ -32,7 +32,6 @@ struct IsectRayPrecalc;
struct MLoop;
struct MLoopTri;
struct MPoly;
struct MVert;
struct Mesh;
struct MeshElemMap;
struct PBVH;
@ -267,7 +266,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
struct Mesh *mesh,
const struct MPoly *mpoly,
const struct MLoop *mloop,
struct MVert *verts,
float (*vert_positions)[3],
int totvert,
struct CustomData *vdata,
struct CustomData *ldata,
@ -478,10 +477,7 @@ void BKE_pbvh_node_get_grids(PBVH *pbvh,
int *gridsize,
struct CCGElem ***r_griddata);
void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert);
void BKE_pbvh_node_get_verts(PBVH *pbvh,
PBVHNode *node,
const int **r_vert_indices,
struct MVert **r_verts);
const int *BKE_pbvh_node_get_vert_indices(PBVHNode *node);
void BKE_pbvh_node_get_loops(PBVH *pbvh,
PBVHNode *node,
const int **r_loop_indices,
@ -587,12 +583,13 @@ typedef struct PBVHVertexIter {
int gridsize;
/* mesh */
struct MVert *mverts;
float (*vert_positions)[3];
float (*vert_normals)[3];
const bool *hide_vert;
int totvert;
const int *vert_indices;
float *vmask;
bool is_mesh;
/* bmesh */
struct GSetIterator bm_unique_verts;
@ -602,7 +599,6 @@ typedef struct PBVHVertexIter {
/* result: these are all computed in the macro, but we assume
* that compiler optimization's will skip the ones we don't use */
struct MVert *mvert;
struct BMVert *bm_vert;
float *co;
float *no;
@ -647,8 +643,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
} \
} \
else if (vi.mverts) { \
vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
else if (vi.vert_positions) { \
if (vi.respect_hide) { \
vi.visible = !(vi.hide_vert && vi.hide_vert[vi.vert_indices[vi.gx]]); \
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
@ -658,7 +653,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
else { \
BLI_assert(vi.visible); \
} \
vi.co = vi.mvert->co; \
vi.co = vi.vert_positions[vi.vert_indices[vi.gx]]; \
vi.no = vi.vert_normals[vi.vert_indices[vi.gx]]; \
vi.index = vi.vertex.i = vi.vert_indices[vi.i]; \
if (vi.vmask) { \
@ -770,7 +765,7 @@ void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings,
bool use_threading,
int totnode);
struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
float (*BKE_pbvh_get_vert_positions(const PBVH *pbvh))[3];
const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3];
const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh);
bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh);

View File

@ -4,7 +4,7 @@
#pragma once
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_rect.h"
#include "BLI_vector.hh"

View File

@ -11,7 +11,7 @@
# include <mutex>
# include "BLI_bounds_types.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_shared_cache.hh"
#endif

View File

@ -94,7 +94,7 @@ typedef struct SubdivStats {
double topology_refiner_creation_time;
/* Total time spent in BKE_subdiv_to_mesh(). */
double subdiv_to_mesh_time;
/* Geometry (MVert and co) creation time during SUBDIV_TYO_MESH. */
/* Geometry (mesh vertices) creation time during SUBDIV_TYO_MESH. */
double subdiv_to_mesh_geometry_time;
/* Time spent on evaluator creation from topology refiner. */
double evaluator_creation_time;

View File

@ -16,7 +16,6 @@ extern "C" {
struct Mesh;
struct MeshElemMap;
struct MEdge;
struct MVert;
struct Subdiv;
typedef struct SubdivToMeshSettings {
@ -39,7 +38,7 @@ struct Mesh *BKE_subdiv_to_mesh(struct Subdiv *subdiv,
/* Interpolate a position along the `coarse_edge` at the relative `u` coordinate. If `is_simple` is
* false, this will perform a B-Spline interpolation using the edge neighbors, otherwise a linear
* interpolation will be done base on the edge vertices. */
void BKE_subdiv_mesh_interpolate_position_on_edge(const struct MVert *coarse_verts,
void BKE_subdiv_mesh_interpolate_position_on_edge(const float (*coarse_positions)[3],
const struct MEdge *coarse_edges,
const struct MeshElemMap *vert_to_edge_map,
int coarse_edge_index,

View File

@ -8,19 +8,19 @@
namespace blender::bke {
struct ConversionFunctions {
const fn::MultiFunction *multi_function;
const mf::MultiFunction *multi_function;
void (*convert_single_to_initialized)(const void *src, void *dst);
void (*convert_single_to_uninitialized)(const void *src, void *dst);
};
class DataTypeConversions {
private:
Map<std::pair<fn::MFDataType, fn::MFDataType>, ConversionFunctions> conversions_;
Map<std::pair<mf::DataType, mf::DataType>, ConversionFunctions> conversions_;
public:
void add(fn::MFDataType from_type,
fn::MFDataType to_type,
const fn::MultiFunction &fn,
void add(mf::DataType from_type,
mf::DataType to_type,
const mf::MultiFunction &fn,
void (*convert_single_to_initialized)(const void *src, void *dst),
void (*convert_single_to_uninitialized)(const void *src, void *dst))
{
@ -28,19 +28,18 @@ class DataTypeConversions {
{&fn, convert_single_to_initialized, convert_single_to_uninitialized});
}
const ConversionFunctions *get_conversion_functions(fn::MFDataType from, fn::MFDataType to) const
const ConversionFunctions *get_conversion_functions(mf::DataType from, mf::DataType to) const
{
return conversions_.lookup_ptr({from, to});
}
const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const
{
return this->get_conversion_functions(fn::MFDataType::ForSingle(from),
fn::MFDataType::ForSingle(to));
return this->get_conversion_functions(mf::DataType::ForSingle(from),
mf::DataType::ForSingle(to));
}
const fn::MultiFunction *get_conversion_multi_function(fn::MFDataType from,
fn::MFDataType to) const
const mf::MultiFunction *get_conversion_multi_function(mf::DataType from, mf::DataType to) const
{
const ConversionFunctions *functions = this->get_conversion_functions(from, to);
return functions ? functions->multi_function : nullptr;
@ -49,7 +48,7 @@ class DataTypeConversions {
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
{
return conversions_.contains(
{fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type)});
{mf::DataType::ForSingle(from_type), mf::DataType::ForSingle(to_type)});
}
void convert_to_uninitialized(const CPPType &from_type,

View File

@ -160,7 +160,7 @@ bool BKE_volume_save(const struct Volume *volume,
#ifdef __cplusplus
# include "BLI_float4x4.hh"
# include "BLI_math_vec_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_string_ref.hh"
bool BKE_volume_min_max(const Volume *volume, blender::float3 &r_min, blender::float3 &r_max);

View File

@ -62,7 +62,7 @@ void fill_mesh_from_openvdb_data(const Span<openvdb::Vec3s> vdb_verts,
int vert_offset,
int poly_offset,
int loop_offset,
MutableSpan<MVert> verts,
MutableSpan<float3> vert_positions,
MutableSpan<MPoly> polys,
MutableSpan<MLoop> loops);

View File

@ -247,7 +247,7 @@ set(SRC
intern/paint.cc
intern/paint_canvas.cc
intern/paint_toolslots.c
intern/particle.c
intern/particle.cc
intern/particle_child.c
intern/particle_distribute.c
intern/particle_system.c

View File

@ -24,7 +24,7 @@
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "BLI_utildefines.h"
@ -92,18 +92,19 @@ static void editbmesh_calc_modifier_final_normals_or_defer(
/* -------------------------------------------------------------------- */
static MVert *dm_getVertArray(DerivedMesh *dm)
static float *dm_getVertArray(DerivedMesh *dm)
{
MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT);
float(*positions)[3] = (float(*)[3])CustomData_get_layer_named(
&dm->vertData, CD_PROP_FLOAT3, "position");
if (!mvert) {
mvert = (MVert *)CustomData_add_layer(
&dm->vertData, CD_MVERT, CD_SET_DEFAULT, nullptr, dm->getNumVerts(dm));
CustomData_set_layer_flag(&dm->vertData, CD_MVERT, CD_FLAG_TEMPORARY);
dm->copyVertArray(dm, mvert);
if (!positions) {
positions = (float(*)[3])CustomData_add_layer_named(
&dm->vertData, CD_PROP_FLOAT3, CD_SET_DEFAULT, nullptr, dm->getNumVerts(dm), "position");
CustomData_set_layer_flag(&dm->vertData, CD_PROP_FLOAT3, CD_FLAG_TEMPORARY);
dm->copyVertArray(dm, positions);
}
return mvert;
return (float *)positions;
}
static MEdge *dm_getEdgeArray(DerivedMesh *dm)
@ -286,7 +287,7 @@ void DM_ensure_looptri_data(DerivedMesh *dm)
BLI_assert(dm->looptris.array_wip == nullptr);
SWAP(MLoopTri *, dm->looptris.array, dm->looptris.array_wip);
std::swap(dm->looptris.array, dm->looptris.array_wip);
if ((looptris_num > dm->looptris.num_alloc) || (looptris_num < dm->looptris.num_alloc * 2) ||
(totpoly == 0)) {
@ -350,10 +351,6 @@ static void mesh_set_only_copy(Mesh *mesh, const CustomData_MeshMasks *mask)
void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
{
if (type == CD_MVERT) {
return dm->getVertArray(dm);
}
return CustomData_get_layer(&dm->vertData, type);
}
@ -672,10 +669,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
/* Deformed vertex locations array. Deform only modifier need this type of
* float array rather than MVert*. Tracked along with mesh_final as an
* optimization to avoid copying coordinates back and forth if there are
* multiple sequential deform only modifiers. */
/* TODO: Remove use of `deformed_verts` in mesh modifier stack
* since mesh positions are now stored in a contiguous array. */
float(*deformed_verts)[3] = nullptr;
int num_deformed_verts = mesh_input->totvert;
bool isPrevDeform = false;
@ -1262,10 +1257,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
GeometrySet geometry_set_final;
/* Deformed vertex locations array. Deform only modifier need this type of
* float array rather than MVert*. Tracked along with mesh_final as an
* optimization to avoid copying coordinates back and forth if there are
* multiple sequential deform only modifiers. */
/* TODO: Remove use of `deformed_verts` in mesh modifier stack
* since mesh positions are now stored in a contiguous array. */
float(*deformed_verts)[3] = nullptr;
int num_deformed_verts = 0;
bool isPrevDeform = false;
@ -1697,7 +1690,7 @@ static void object_get_datamask(const Depsgraph *depsgraph,
/* check if we need tfaces & mcols due to face select or texture paint */
if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) {
r_mask->lmask |= CD_MASK_MLOOPUV | CD_MASK_PROP_BYTE_COLOR;
r_mask->lmask |= CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_BYTE_COLOR;
r_mask->fmask |= CD_MASK_MTFACE;
}
@ -1928,9 +1921,9 @@ void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int to
MEM_freeN(userData.vertex_visit);
}
else {
const Span<MVert> verts = me_eval->verts();
const Span<float3> positions = me_eval->vert_positions();
for (int i = 0; i < totcos; i++) {
copy_v3_v3(r_cos[i], verts[i].co);
copy_v3_v3(r_cos[i], positions[i]);
}
}
}
@ -1943,7 +1936,7 @@ static void mesh_init_origspace(Mesh *mesh)
CD_ORIGSPACE_MLOOP);
const int numpoly = mesh->totpoly;
// const int numloop = mesh->totloop;
const Span<MVert> verts = mesh->verts();
const Span<float3> positions = mesh->vert_positions();
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
@ -1968,12 +1961,13 @@ static void mesh_init_origspace(Mesh *mesh)
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX};
float translate[2], scale[2];
BKE_mesh_calc_poly_normal(mp, l, verts.data(), p_nor);
BKE_mesh_calc_poly_normal(
mp, l, reinterpret_cast<const float(*)[3]>(positions.data()), p_nor);
axis_dominant_v3_to_m3(mat, p_nor);
vcos_2d.resize(mp->totloop);
for (j = 0; j < mp->totloop; j++, l++) {
mul_v3_m3v3(co, mat, verts[l->v].co);
mul_v3_m3v3(co, mat, positions[l->v]);
copy_v2_v2(vcos_2d[j], co);
for (k = 0; k < 2; k++) {

View File

@ -4,6 +4,11 @@
namespace blender::bke {
std::string AnonymousAttributeID::user_name() const
{
return this->name();
}
bool AnonymousAttributePropagationInfo::propagate(const AnonymousAttributeID &anonymous_id) const
{
if (this->propagate_all) {

View File

@ -31,6 +31,7 @@
#include "BKE_curves.hh"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
#include "BKE_pointcloud.h"
#include "BKE_report.h"
@ -140,6 +141,19 @@ bool BKE_attribute_allow_procedural_access(const char *attribute_name)
return blender::bke::allow_procedural_attribute_access(attribute_name);
}
static bool bke_id_attribute_rename_if_exists(ID *id,
const char *old_name,
const char *new_name,
ReportList *reports)
{
CustomDataLayer *layer = BKE_id_attribute_search(
id, old_name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
if (layer == nullptr) {
return false;
}
return BKE_id_attribute_rename(id, old_name, new_name, reports);
}
bool BKE_id_attribute_rename(ID *id,
const char *old_name,
const char *new_name,
@ -154,8 +168,18 @@ bool BKE_id_attribute_rename(ID *id,
BKE_report(reports, RPT_ERROR, "Attribute name can not be empty");
return false;
}
if (STREQ(old_name, new_name)) {
return false;
/* NOTE: Checking if the new name matches the old name only makes sense when the name
* is clamped to it's maximum length, otherwise assigning an over-long name multiple times
* will add `.001` suffix unnecessarily. */
{
const int maxlength = CustomData_name_max_length_calc(new_name);
/* NOTE: A function that performs a clamped comparison without copying would be handy here. */
char new_name_clamped[MAX_CUSTOMDATA_LAYER_NAME];
BLI_strncpy_utf8(new_name_clamped, new_name, maxlength);
if (STREQ(old_name, new_name_clamped)) {
return false;
}
}
CustomDataLayer *layer = BKE_id_attribute_search(
@ -168,6 +192,24 @@ bool BKE_id_attribute_rename(ID *id,
char result_name[MAX_CUSTOMDATA_LAYER_NAME];
BKE_id_attribute_calc_unique_name(id, new_name, result_name);
if (layer->type == CD_PROP_FLOAT2 && GS(id->name) == ID_ME) {
/* Rename UV sub-attributes. */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
char buffer_dst[MAX_CUSTOMDATA_LAYER_NAME];
bke_id_attribute_rename_if_exists(id,
BKE_uv_map_vert_select_name_get(layer->name, buffer_src),
BKE_uv_map_vert_select_name_get(result_name, buffer_dst),
reports);
bke_id_attribute_rename_if_exists(id,
BKE_uv_map_edge_select_name_get(layer->name, buffer_src),
BKE_uv_map_edge_select_name_get(result_name, buffer_dst),
reports);
bke_id_attribute_rename_if_exists(id,
BKE_uv_map_pin_name_get(layer->name, buffer_src),
BKE_uv_map_pin_name_get(result_name, buffer_dst),
reports);
}
if (StringRef(old_name) == BKE_id_attributes_active_color_name(id)) {
BKE_id_attributes_active_color_set(id, result_name);
}
@ -212,18 +254,18 @@ static bool unique_name_cb(void *arg, const char *name)
bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
{
AttrUniqueData data{id};
const int maxlength = CustomData_name_max_length_calc(name);
/* Set default name if none specified.
* NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */
if (!name || name[0] == '\0') {
BLI_strncpy(outname, IFACE_("Attribute"), MAX_CUSTOMDATA_LAYER_NAME);
BLI_strncpy(outname, IFACE_("Attribute"), maxlength);
}
else {
BLI_strncpy_utf8(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
BLI_strncpy_utf8(outname, name, maxlength);
}
return BLI_uniquename_cb(
unique_name_cb, &data, nullptr, '.', outname, MAX_CUSTOMDATA_LAYER_NAME);
return BLI_uniquename_cb(unique_name_cb, &data, nullptr, '.', outname, maxlength);
}
CustomDataLayer *BKE_id_attribute_new(
@ -262,6 +304,24 @@ CustomDataLayer *BKE_id_attribute_new(
return (index == -1) ? nullptr : &(customdata->layers[index]);
}
static void bke_id_attribute_copy_if_exists(ID *id, const char *srcname, const char *dstname)
{
using namespace blender::bke;
std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(*id);
if (!attributes) {
return;
}
GAttributeReader src = attributes->lookup(srcname);
if (!src) {
return;
}
const eCustomDataType type = cpp_type_to_custom_data_type(src.varray.type());
attributes->add(dstname, src.domain, type, AttributeInitVArray(src.varray));
}
CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList *reports)
{
using namespace blender::bke;
@ -291,6 +351,22 @@ CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList
const eCustomDataType type = cpp_type_to_custom_data_type(src.varray.type());
attributes->add(uniquename, src.domain, type, AttributeInitVArray(src.varray));
if (GS(id->name) == ID_ME && type == CD_PROP_FLOAT2) {
/* Duplicate UV sub-attributes. */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
char buffer_dst[MAX_CUSTOMDATA_LAYER_NAME];
bke_id_attribute_copy_if_exists(id,
BKE_uv_map_vert_select_name_get(name, buffer_src),
BKE_uv_map_vert_select_name_get(uniquename, buffer_dst));
bke_id_attribute_copy_if_exists(id,
BKE_uv_map_edge_select_name_get(name, buffer_src),
BKE_uv_map_edge_select_name_get(uniquename, buffer_dst));
bke_id_attribute_copy_if_exists(id,
BKE_uv_map_pin_name_get(name, buffer_src),
BKE_uv_map_pin_name_get(uniquename, buffer_dst));
}
return BKE_id_attribute_search(id, uniquename, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
}
@ -315,11 +391,27 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
if (BMEditMesh *em = mesh->edit_mesh) {
for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
if (CustomData *data = info[domain].customdata) {
int layer_index = CustomData_get_named_layer_index_notype(data, name);
if (layer_index >= 0) {
if (data->layers[layer_index].type == CD_PROP_FLOAT2) {
/* free associated UV map bool layers */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_free_named(
em->bm, data, BKE_uv_map_vert_select_name_get(name, buffer_src));
BM_data_layer_free_named(
em->bm, data, BKE_uv_map_edge_select_name_get(name, buffer_src));
BM_data_layer_free_named(em->bm, data, BKE_uv_map_pin_name_get(name, buffer_src));
}
}
/* Because it's possible that name is owned by the layer and will be freed
* when freeing the layer, do these checks before freeing. */
const bool is_active_color_attribute = name == StringRef(mesh->active_color_attribute);
const bool is_default_color_attribute = name == StringRef(mesh->default_color_attribute);
if (BM_data_layer_free_named(em->bm, data, name)) {
if (name == StringRef(mesh->active_color_attribute)) {
if (is_active_color_attribute) {
MEM_SAFE_FREE(mesh->active_color_attribute);
}
else if (name == StringRef(mesh->default_color_attribute)) {
else if (is_default_color_attribute) {
MEM_SAFE_FREE(mesh->default_color_attribute);
}
return true;
@ -331,10 +423,23 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
}
std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(*id);
if (!attributes) {
return false;
}
if (GS(id->name) == ID_ME) {
std::optional<blender::bke::AttributeMetaData> metadata = attributes->lookup_meta_data(name);
if (metadata->data_type == CD_PROP_FLOAT2) {
/* remove UV sub-attributes. */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
BKE_id_attribute_remove(id, BKE_uv_map_vert_select_name_get(name, buffer_src), reports);
BKE_id_attribute_remove(id, BKE_uv_map_edge_select_name_get(name, buffer_src), reports);
BKE_id_attribute_remove(id, BKE_uv_map_pin_name_get(name, buffer_src), reports);
}
}
return attributes->remove(name);
}
@ -478,6 +583,8 @@ bool BKE_id_attribute_required(const ID *id, const char *name)
return BKE_pointcloud_attribute_required((const PointCloud *)id, name);
case ID_CV:
return BKE_curves_attribute_required((const Curves *)id, name);
case ID_ME:
return BKE_mesh_attribute_required(name);
default:
return false;
}
@ -612,7 +719,7 @@ static void get_domains_types(eAttrDomain domains[ATTR_DOMAIN_NUM])
}
/* Swap corner and face. */
SWAP(eAttrDomain, domains[ATTR_DOMAIN_FACE], domains[ATTR_DOMAIN_CORNER]);
std::swap(domains[ATTR_DOMAIN_FACE], domains[ATTR_DOMAIN_CORNER]);
}
int BKE_id_attribute_to_index(const ID *id,
@ -781,3 +888,27 @@ void BKE_id_attribute_copy_domains_temp(short id_type,
*((short *)r_id->name) = id_type;
}
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_VERTSEL_NAME) == 2);
BLI_assert(strlen(uv_map_name) < MAX_CUSTOMDATA_LAYER_NAME - 4);
BLI_snprintf(buffer, MAX_CUSTOMDATA_LAYER_NAME, ".%s.%s", UV_VERTSEL_NAME, uv_map_name);
return buffer;
}
const char *BKE_uv_map_edge_select_name_get(const char *uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_EDGESEL_NAME) == 2);
BLI_assert(strlen(uv_map_name) < MAX_CUSTOMDATA_LAYER_NAME - 4);
BLI_snprintf(buffer, MAX_CUSTOMDATA_LAYER_NAME, ".%s.%s", UV_EDGESEL_NAME, uv_map_name);
return buffer;
}
const char *BKE_uv_map_pin_name_get(const char *uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_PINNED_NAME) == 2);
BLI_assert(strlen(uv_map_name) < MAX_CUSTOMDATA_LAYER_NAME - 4);
BLI_snprintf(buffer, MAX_CUSTOMDATA_LAYER_NAME, ".%s.%s", UV_PINNED_NAME, uv_map_name);
return buffer;
}

View File

@ -16,7 +16,7 @@
#include "BLI_array_utils.hh"
#include "BLI_color.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "FN_field.hh"
@ -54,8 +54,25 @@ const char *no_procedural_access_message =
bool allow_procedural_attribute_access(StringRef attribute_name)
{
return !attribute_name.startswith(".sculpt") && !attribute_name.startswith(".select") &&
!attribute_name.startswith(".hide");
if (attribute_name.startswith(".select")) {
return false;
}
if (attribute_name.startswith(".sculpt")) {
return false;
}
if (attribute_name.startswith(".hide")) {
return false;
}
if (attribute_name.startswith("." UV_VERTSEL_NAME ".")) {
return false;
}
if (attribute_name.startswith("." UV_EDGESEL_NAME ".")) {
return false;
}
if (attribute_name.startswith("." UV_PINNED_NAME ".")) {
return false;
}
return true;
}
static int attribute_data_type_complexity(const eCustomDataType data_type)
@ -204,7 +221,7 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
const AttributeIDRef &attribute_id)
{
if (!attribute_id.is_anonymous()) {
char attribute_name_c[MAX_NAME];
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
&custom_data, data_type, alloctype, layer_data, domain_num, attribute_name_c);
@ -522,88 +539,6 @@ bool CustomDataAttributeProvider::foreach_attribute(const void *owner,
return true;
}
GAttributeReader NamedLegacyCustomDataProvider::try_get_for_read(
const void *owner, const AttributeIDRef &attribute_id) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const int domain_num = custom_data_access_.get_element_num(owner);
return {as_read_attribute_(layer.data, domain_num), domain_};
}
}
}
return {};
}
GAttributeWriter NamedLegacyCustomDataProvider::try_get_for_write(
void *owner, const AttributeIDRef &attribute_id) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const int element_num = custom_data_access_.get_element_num(owner);
void *data = CustomData_duplicate_referenced_layer_named(
custom_data, stored_type_, layer.name, element_num);
return {as_write_attribute_(data, element_num), domain_};
}
}
}
return {};
}
bool NamedLegacyCustomDataProvider::try_delete(void *owner,
const AttributeIDRef &attribute_id) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return false;
}
for (const int i : IndexRange(custom_data->totlayer)) {
const CustomDataLayer &layer = custom_data->layers[i];
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const int element_num = custom_data_access_.get_element_num(owner);
CustomData_free_layer(custom_data, stored_type_, element_num, i);
return true;
}
}
}
return false;
}
bool NamedLegacyCustomDataProvider::foreach_attribute(
const void *owner, const AttributeForeachCallback callback) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return true;
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
AttributeMetaData meta_data{domain_, attribute_type_};
if (!callback(layer.name, meta_data)) {
return false;
}
}
}
return true;
}
void NamedLegacyCustomDataProvider::foreach_domain(
const FunctionRef<void(eAttrDomain)> callback) const
{
callback(domain_);
}
CustomDataAttributes::CustomDataAttributes()
{
CustomData_reset(&data);

View File

@ -170,44 +170,6 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
}
};
/**
* This attribute provider is used for uv maps and vertex colors.
*/
class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
private:
using AsReadAttribute = GVArray (*)(const void *data, int domain_num);
using AsWriteAttribute = GVMutableArray (*)(void *data, int domain_num);
const eAttrDomain domain_;
const eCustomDataType attribute_type_;
const eCustomDataType stored_type_;
const CustomDataAccessInfo custom_data_access_;
const AsReadAttribute as_read_attribute_;
const AsWriteAttribute as_write_attribute_;
public:
NamedLegacyCustomDataProvider(const eAttrDomain domain,
const eCustomDataType attribute_type,
const eCustomDataType stored_type,
const CustomDataAccessInfo custom_data_access,
const AsReadAttribute as_read_attribute,
const AsWriteAttribute as_write_attribute)
: domain_(domain),
attribute_type_(attribute_type),
stored_type_(stored_type),
custom_data_access_(custom_data_access),
as_read_attribute_(as_read_attribute),
as_write_attribute_(as_write_attribute)
{
}
GAttributeReader try_get_for_read(const void *owner,
const AttributeIDRef &attribute_id) const final;
GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final;
bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final;
bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final;
void foreach_domain(const FunctionRef<void(eAttrDomain)> callback) const final;
};
template<typename T> GVArray make_array_read_attribute(const void *data, const int domain_num)
{
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_num));
@ -220,8 +182,7 @@ template<typename T> GVMutableArray make_array_write_attribute(void *data, const
/**
* This provider is used to provide access to builtin attributes. It supports making internal types
* available as different types. For example, the vertex position attribute is stored as part of
* the #MVert struct, but is exposed as float3 attribute.
* available as different types.
*
* It also supports named builtin attributes, and will look up attributes in #CustomData by name
* if the stored type is the same as the attribute type.

View File

@ -407,7 +407,7 @@ static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
/* NOTE: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
SWAP(IDProperty *, id_new->properties, id_old->properties);
std::swap(id_new->properties, id_old->properties);
}
IDTypeInfo IDType_ID_BR = {

View File

@ -30,6 +30,7 @@
#include "MEM_guardedalloc.h"
using blender::BitVector;
using blender::float3;
using blender::IndexRange;
using blender::Span;
using blender::VArray;
@ -236,14 +237,14 @@ static void mesh_faces_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const MVert *vert = data->vert;
const float(*positions)[3] = data->vert_positions;
const MFace *face = data->face + index;
const float *t0, *t1, *t2, *t3;
t0 = vert[face->v1].co;
t1 = vert[face->v2].co;
t2 = vert[face->v3].co;
t3 = face->v4 ? vert[face->v4].co : nullptr;
t0 = positions[face->v1];
t1 = positions[face->v2];
t2 = positions[face->v3];
t3 = face->v4 ? positions[face->v4] : nullptr;
do {
float nearest_tmp[3], dist_sq;
@ -271,12 +272,12 @@ static void mesh_looptri_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const MVert *vert = data->vert;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const float *vtri_co[3] = {
vert[data->loop[lt->tri[0]].v].co,
vert[data->loop[lt->tri[1]].v].co,
vert[data->loop[lt->tri[2]].v].co,
positions[data->loop[lt->tri[0]].v],
positions[data->loop[lt->tri[1]].v],
positions[data->loop[lt->tri[2]].v],
};
float nearest_tmp[3], dist_sq;
@ -332,14 +333,14 @@ static void mesh_faces_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const MVert *vert = data->vert;
const float(*positions)[3] = data->vert_positions;
const MFace *face = &data->face[index];
const float *t0, *t1, *t2, *t3;
t0 = vert[face->v1].co;
t1 = vert[face->v2].co;
t2 = vert[face->v3].co;
t3 = face->v4 ? vert[face->v4].co : nullptr;
t0 = positions[face->v1];
t1 = positions[face->v2];
t2 = positions[face->v3];
t3 = face->v4 ? positions[face->v4] : nullptr;
do {
float dist;
@ -371,12 +372,12 @@ static void mesh_looptri_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const MVert *vert = data->vert;
const float(*positions)[3] = data->vert_positions;
const MLoopTri *lt = &data->looptri[index];
const float *vtri_co[3] = {
vert[data->loop[lt->tri[0]].v].co,
vert[data->loop[lt->tri[1]].v].co,
vert[data->loop[lt->tri[2]].v].co,
positions[data->loop[lt->tri[0]].v],
positions[data->loop[lt->tri[1]].v],
positions[data->loop[lt->tri[2]].v],
};
float dist;
@ -441,13 +442,13 @@ static void mesh_edges_nearest_point(void *userdata,
BVHTreeNearest *nearest)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const MVert *vert = data->vert;
const float(*positions)[3] = data->vert_positions;
const MEdge *edge = data->edge + index;
float nearest_tmp[3], dist_sq;
const float *t0, *t1;
t0 = vert[edge->v1].co;
t1 = vert[edge->v2].co;
t0 = positions[edge->v1];
t1 = positions[edge->v2];
closest_to_line_segment_v3(nearest_tmp, co, t0, t1);
dist_sq = len_squared_v3v3(nearest_tmp, co);
@ -506,7 +507,7 @@ static void mesh_verts_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float *v = data->vert[index].co;
const float *v = data->vert_positions[index];
mesh_verts_spherecast_do(index, v, ray, hit);
}
@ -523,15 +524,15 @@ static void mesh_edges_spherecast(void *userdata,
BVHTreeRayHit *hit)
{
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const MVert *vert = data->vert;
const float(*positions)[3] = data->vert_positions;
const MEdge *edge = &data->edge[index];
const float radius_sq = square_f(ray->radius);
float dist;
const float *v1, *v2, *r1;
float r2[3], i1[3], i2[3];
v1 = vert[edge->v1].co;
v2 = vert[edge->v2].co;
v1 = positions[edge->v1];
v2 = positions[edge->v2];
/* In case we get a zero-length edge, handle it as a point! */
if (equals_v3v3(v1, v2)) {
@ -574,7 +575,7 @@ static void mesh_edges_spherecast(void *userdata,
static void bvhtree_from_mesh_setup_data(BVHTree *tree,
const BVHCacheType bvh_cache_type,
const MVert *vert,
const float (*positions)[3],
const MEdge *edge,
const MFace *face,
const MLoop *loop,
@ -585,7 +586,7 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree,
r_data->tree = tree;
r_data->vert = vert;
r_data->vert_positions = positions;
r_data->edge = edge;
r_data->face = face;
r_data->loop = loop;
@ -703,7 +704,7 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(float epsilon,
static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon,
int tree_type,
int axis,
const MVert *vert,
const float (*positions)[3],
const int verts_num,
const BitVector<> &verts_mask,
int verts_num_active)
@ -727,7 +728,7 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(float epsilon,
if (!verts_mask.is_empty() && !verts_mask[i]) {
continue;
}
BLI_bvhtree_insert(tree, i, vert[i].co, 1);
BLI_bvhtree_insert(tree, i, positions[i], 1);
}
BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
@ -761,7 +762,7 @@ BVHTree *bvhtree_from_editmesh_verts(
}
BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
const MVert *vert,
const float (*vert_positions)[3],
const int verts_num,
const BitVector<> &verts_mask,
int verts_num_active,
@ -770,14 +771,14 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
int axis)
{
BVHTree *tree = bvhtree_from_mesh_verts_create_tree(
epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
epsilon, tree_type, axis, vert_positions, verts_num, verts_mask, verts_num_active);
bvhtree_balance(tree, false);
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_VERTS, vert, nullptr, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_VERTS, vert_positions, nullptr, nullptr, nullptr, nullptr, data);
}
return tree;
@ -829,7 +830,7 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(float epsilon,
return tree;
}
static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert,
static BVHTree *bvhtree_from_mesh_edges_create_tree(const float (*positions)[3],
const MEdge *edge,
const int edge_num,
const BitVector<> &edges_mask,
@ -859,8 +860,8 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(const MVert *vert,
continue;
}
float co[2][3];
copy_v3_v3(co[0], vert[edge[i].v1].co);
copy_v3_v3(co[1], vert[edge[i].v2].co);
copy_v3_v3(co[0], positions[edge[i].v1]);
copy_v3_v3(co[1], positions[edge[i].v2]);
BLI_bvhtree_insert(tree, i, co[0], 2);
}
@ -895,7 +896,7 @@ BVHTree *bvhtree_from_editmesh_edges(
}
BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
const MVert *vert,
const float (*vert_positions)[3],
const MEdge *edge,
const int edges_num,
const BitVector<> &edges_mask,
@ -905,14 +906,14 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
int axis)
{
BVHTree *tree = bvhtree_from_mesh_edges_create_tree(
vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis);
vert_positions, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis);
bvhtree_balance(tree, false);
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_EDGES, vert, edge, nullptr, nullptr, nullptr, data);
tree, BVHTREE_FROM_EDGES, vert_positions, edge, nullptr, nullptr, nullptr, data);
}
return tree;
@ -927,7 +928,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
int tree_type,
int axis,
const MVert *vert,
const float (*positions)[3],
const MFace *face,
const int faces_num,
const BitVector<> &faces_mask,
@ -951,18 +952,18 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(float epsilon,
return nullptr;
}
if (vert && face) {
if (positions && face) {
for (int i = 0; i < faces_num; i++) {
float co[4][3];
if (!faces_mask.is_empty() && !faces_mask[i]) {
continue;
}
copy_v3_v3(co[0], vert[face[i].v1].co);
copy_v3_v3(co[1], vert[face[i].v2].co);
copy_v3_v3(co[2], vert[face[i].v3].co);
copy_v3_v3(co[0], positions[face[i].v1]);
copy_v3_v3(co[1], positions[face[i].v2]);
copy_v3_v3(co[2], positions[face[i].v3]);
if (face[i].v4) {
copy_v3_v3(co[3], vert[face[i].v4].co);
copy_v3_v3(co[3], positions[face[i].v4]);
}
BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
@ -1033,7 +1034,7 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon,
static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
int tree_type,
int axis,
const MVert *vert,
const float (*positions)[3],
const MLoop *mloop,
const MLoopTri *looptri,
const int looptri_num,
@ -1057,16 +1058,16 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(float epsilon,
return nullptr;
}
if (vert && looptri) {
if (positions && looptri) {
for (int i = 0; i < looptri_num; i++) {
float co[3][3];
if (!looptri_mask.is_empty() && !looptri_mask[i]) {
continue;
}
copy_v3_v3(co[0], vert[mloop[looptri[i].tri[0]].v].co);
copy_v3_v3(co[1], vert[mloop[looptri[i].tri[1]].v].co);
copy_v3_v3(co[2], vert[mloop[looptri[i].tri[2]].v].co);
copy_v3_v3(co[0], positions[mloop[looptri[i].tri[0]].v]);
copy_v3_v3(co[1], positions[mloop[looptri[i].tri[1]].v]);
copy_v3_v3(co[2], positions[mloop[looptri[i].tri[2]].v]);
BLI_bvhtree_insert(tree, i, co[0], 3);
}
@ -1104,7 +1105,7 @@ BVHTree *bvhtree_from_editmesh_looptri(
}
BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
const struct MVert *vert,
const float (*vert_positions)[3],
const struct MLoop *mloop,
const struct MLoopTri *looptri,
const int looptri_num,
@ -1117,7 +1118,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
BVHTree *tree = bvhtree_from_mesh_looptri_create_tree(epsilon,
tree_type,
axis,
vert,
vert_positions,
mloop,
looptri,
looptri_num,
@ -1129,7 +1130,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
if (data) {
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(
tree, BVHTREE_FROM_LOOPTRI, vert, nullptr, nullptr, mloop, looptri, data);
tree, BVHTREE_FROM_LOOPTRI, vert_positions, nullptr, nullptr, mloop, looptri, data);
}
return tree;
@ -1212,14 +1213,14 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
looptri = BKE_mesh_runtime_looptri_ensure(mesh);
looptri_len = BKE_mesh_runtime_looptri_len(mesh);
}
const Span<MVert> verts = mesh->verts();
const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data());
const Span<MEdge> edges = mesh->edges();
const Span<MLoop> loops = mesh->loops();
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_setup_data(nullptr,
bvh_cache_type,
verts.data(),
positions,
edges.data(),
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
loops.data(),
@ -1247,7 +1248,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
ATTR_FALLTHROUGH;
case BVHTREE_FROM_VERTS:
data->tree = bvhtree_from_mesh_verts_create_tree(
0.0f, tree_type, 6, verts.data(), mesh->totvert, mask, mask_bits_act_len);
0.0f, tree_type, 6, positions, mesh->totvert, mask, mask_bits_act_len);
break;
case BVHTREE_FROM_LOOSEEDGES:
@ -1255,7 +1256,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
ATTR_FALLTHROUGH;
case BVHTREE_FROM_EDGES:
data->tree = bvhtree_from_mesh_edges_create_tree(
verts.data(), edges.data(), mesh->totedge, mask, mask_bits_act_len, 0.0f, tree_type, 6);
positions, edges.data(), mesh->totedge, mask, mask_bits_act_len, 0.0f, tree_type, 6);
break;
case BVHTREE_FROM_FACES:
@ -1264,7 +1265,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
0.0f,
tree_type,
6,
verts.data(),
positions,
(const MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE),
mesh->totface,
{},
@ -1284,7 +1285,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
data->tree = bvhtree_from_mesh_looptri_create_tree(0.0f,
tree_type,
6,
verts.data(),
positions,
loops.data(),
looptri,
looptri_len,

View File

@ -1119,6 +1119,9 @@ float BKE_camera_multiview_shift_x(const RenderData *rd,
if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
return data->shiftx;
}
if (data->type == CAM_PANO) {
return data->shiftx;
}
/* SCE_VIEWS_SETUP_BASIC */
return camera_stereo3d_shift_x(camera, viewname);
}

View File

@ -38,7 +38,7 @@ typedef struct {
/* these point to data in the DerivedMesh custom data layers,
* they are only here for efficiency and convenience */
MVert *mvert;
float (*vert_positions)[3];
const float (*vert_normals)[3];
MEdge *medge;
MFace *mface;
@ -75,10 +75,10 @@ static int cdDM_getNumPolys(DerivedMesh *dm)
return dm->numPolyData;
}
static void cdDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
static void cdDM_copyVertArray(DerivedMesh *dm, float (*r_positions)[3])
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
memcpy(r_vert, cddm->mvert, sizeof(*r_vert) * dm->numVertData);
memcpy(r_positions, cddm->vert_positions, sizeof(float[3]) * dm->numVertData);
}
static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
@ -103,7 +103,7 @@ static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
copy_v3_v3(r_co, cddm->mvert[index].co);
copy_v3_v3(r_co, cddm->vert_positions[index]);
}
static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
@ -121,8 +121,12 @@ static void cdDM_recalc_looptri(DerivedMesh *dm)
DM_ensure_looptri_data(dm);
BLI_assert(totpoly == 0 || cddm->dm.looptris.array_wip != NULL);
BKE_mesh_recalc_looptri(
cddm->mloop, cddm->mpoly, cddm->mvert, totloop, totpoly, cddm->dm.looptris.array_wip);
BKE_mesh_recalc_looptri(cddm->mloop,
cddm->mpoly,
cddm->vert_positions,
totloop,
totpoly,
cddm->dm.looptris.array_wip);
BLI_assert(cddm->dm.looptris.array == NULL);
atomic_cas_ptr(
@ -217,7 +221,7 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, alloctype, mesh->totloop);
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
cddm->vert_positions = CustomData_get_layer_named(&dm->vertData, CD_PROP_FLOAT3, "position");
/* Though this may be an unnecessary calculation, simply retrieving the layer may return nothing
* or dirty normals. */
cddm->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);

View File

@ -247,18 +247,18 @@ static bool do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int
static int do_step_cloth(
Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr)
{
using namespace blender;
/* simulate 1 frame forward */
ClothVertex *verts = nullptr;
Cloth *cloth;
ListBase *effectors = nullptr;
MVert *mvert;
uint i = 0;
int ret = 0;
bool vert_mass_changed = false;
cloth = clmd->clothObject;
verts = cloth->verts;
mvert = BKE_mesh_verts_for_write(result);
const Span<float3> positions = result->vert_positions();
vert_mass_changed = verts->mass != clmd->sim_parms->mass;
/* force any pinned verts to their constrained location. */
@ -268,7 +268,7 @@ static int do_step_cloth(
copy_v3_v3(verts->txold, verts->x);
/* Get the current position. */
copy_v3_v3(verts->xconst, mvert[i].co);
copy_v3_v3(verts->xconst, positions[i]);
mul_m4_v3(ob->object_to_world, verts->xconst);
if (vert_mass_changed) {
@ -461,7 +461,7 @@ void cloth_free_modifier(ClothModifierData *clmd)
BLI_bvhtree_free(cloth->bvhtree);
}
if (cloth->bvhselftree) {
if (cloth->bvhselftree && cloth->bvhselftree != cloth->bvhtree) {
BLI_bvhtree_free(cloth->bvhselftree);
}
@ -538,7 +538,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd)
BLI_bvhtree_free(cloth->bvhtree);
}
if (cloth->bvhselftree) {
if (cloth->bvhselftree && cloth->bvhselftree != cloth->bvhtree) {
BLI_bvhtree_free(cloth->bvhselftree);
}
@ -715,6 +715,7 @@ static float cloth_shrink_factor(ClothModifierData *clmd, ClothVertex *verts, in
static bool cloth_from_object(
Object *ob, ClothModifierData *clmd, Mesh *mesh, float /*framenr*/, int first)
{
using namespace blender;
int i = 0;
ClothVertex *verts = nullptr;
const float(*shapekey_rest)[3] = nullptr;
@ -758,14 +759,14 @@ static bool cloth_from_object(
CustomData_get_layer(&mesh->vdata, CD_CLOTH_ORCO));
}
MVert *mvert = BKE_mesh_verts_for_write(mesh);
const Span<float3> positions = mesh->vert_positions();
verts = clmd->clothObject->verts;
/* set initial values */
for (i = 0; i < mesh->totvert; i++, verts++) {
if (first) {
copy_v3_v3(verts->x, mvert[i].co);
copy_v3_v3(verts->x, positions[i]);
mul_m4_v3(ob->object_to_world, verts->x);
@ -820,7 +821,14 @@ static bool cloth_from_object(
}
clmd->clothObject->bvhtree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->epsilon);
clmd->clothObject->bvhselftree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->selfepsilon);
if (compare_ff(clmd->coll_parms->selfepsilon, clmd->coll_parms->epsilon, 1e-6f)) {
/* Share the BVH tree if the epsilon is the same. */
clmd->clothObject->bvhselftree = clmd->clothObject->bvhtree;
}
else {
clmd->clothObject->bvhselftree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->selfepsilon);
}
return true;
}
@ -1152,13 +1160,14 @@ static void cloth_update_springs(ClothModifierData *clmd)
/* Update rest verts, for dynamically deformable cloth */
static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh)
{
using namespace blender;
uint i = 0;
const MVert *mvert = BKE_mesh_verts(mesh);
const Span<float3> positions = mesh->vert_positions();
ClothVertex *verts = clmd->clothObject->verts;
/* vertex count is already ensured to match */
for (i = 0; i < mesh->totvert; i++, verts++) {
copy_v3_v3(verts->xrest, mvert[i].co);
copy_v3_v3(verts->xrest, positions[i]);
mul_m4_v3(ob->object_to_world, verts->xrest);
}
}
@ -1166,13 +1175,14 @@ static void cloth_update_verts(Object *ob, ClothModifierData *clmd, Mesh *mesh)
/* Write rest vert locations to a copy of the mesh. */
static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
{
using namespace blender;
Mesh *new_mesh = BKE_mesh_copy_for_eval(mesh, false);
ClothVertex *verts = clmd->clothObject->verts;
MVert *mvert = BKE_mesh_verts_for_write(new_mesh);
MutableSpan<float3> positions = mesh->vert_positions_for_write();
/* vertex count is already ensured to match */
for (uint i = 0; i < mesh->totvert; i++, verts++) {
copy_v3_v3(mvert[i].co, verts->xrest);
for (const int i : positions.index_range()) {
positions[i] = verts[i].xrest;
}
BKE_mesh_tag_coords_changed(new_mesh);
@ -1388,7 +1398,7 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata,
float co[3], no[3], new_co[3];
float radius;
copy_v3_v3(co, treedata->vert[v_idx].co);
copy_v3_v3(co, treedata->vert_positions[v_idx]);
negate_v3_v3(no, vert_normals[v_idx]);
float vec_len = sin(max_diversion);

View File

@ -72,16 +72,16 @@ void collision_move_object(CollisionModifierData *collmd,
/* the collider doesn't move this frame */
if (collmd->is_static) {
for (i = 0; i < collmd->mvert_num; i++) {
zero_v3(collmd->current_v[i].co);
zero_v3(collmd->current_v[i]);
}
return;
}
for (i = 0; i < collmd->mvert_num; i++) {
interp_v3_v3v3(collmd->current_x[i].co, collmd->x[i].co, collmd->xnew[i].co, prevstep);
interp_v3_v3v3(collmd->current_xnew[i].co, collmd->x[i].co, collmd->xnew[i].co, step);
sub_v3_v3v3(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co);
interp_v3_v3v3(collmd->current_x[i], collmd->x[i], collmd->xnew[i], prevstep);
interp_v3_v3v3(collmd->current_xnew[i], collmd->x[i], collmd->xnew[i], step);
sub_v3_v3v3(collmd->current_v[i], collmd->current_xnew[i], collmd->current_x[i]);
}
bvhtree_update_from_mvert(collmd->bvhtree,
@ -92,7 +92,7 @@ void collision_move_object(CollisionModifierData *collmd,
moving_bvh);
}
BVHTree *bvhtree_build_from_mvert(const MVert *mvert,
BVHTree *bvhtree_build_from_mvert(const float (*positions)[3],
const struct MVertTri *tri,
int tri_num,
float epsilon)
@ -105,9 +105,9 @@ BVHTree *bvhtree_build_from_mvert(const MVert *mvert,
for (i = 0, vt = tri; i < tri_num; i++, vt++) {
float co[3][3];
copy_v3_v3(co[0], mvert[vt->tri[0]].co);
copy_v3_v3(co[1], mvert[vt->tri[1]].co);
copy_v3_v3(co[2], mvert[vt->tri[2]].co);
copy_v3_v3(co[0], positions[vt->tri[0]]);
copy_v3_v3(co[1], positions[vt->tri[1]]);
copy_v3_v3(co[2], positions[vt->tri[2]]);
BLI_bvhtree_insert(tree, i, co[0], 3);
}
@ -119,18 +119,18 @@ BVHTree *bvhtree_build_from_mvert(const MVert *mvert,
}
void bvhtree_update_from_mvert(BVHTree *bvhtree,
const MVert *mvert,
const MVert *mvert_moving,
const float (*positions)[3],
const float (*positions_moving)[3],
const MVertTri *tri,
int tri_num,
bool moving)
{
if ((bvhtree == NULL) || (mvert == NULL)) {
if ((bvhtree == NULL) || (positions == NULL)) {
return;
}
if (mvert_moving == NULL) {
if (positions_moving == NULL) {
moving = false;
}
@ -140,17 +140,17 @@ void bvhtree_update_from_mvert(BVHTree *bvhtree,
float co[3][3];
bool ret;
copy_v3_v3(co[0], mvert[vt->tri[0]].co);
copy_v3_v3(co[1], mvert[vt->tri[1]].co);
copy_v3_v3(co[2], mvert[vt->tri[2]].co);
copy_v3_v3(co[0], positions[vt->tri[0]]);
copy_v3_v3(co[1], positions[vt->tri[1]]);
copy_v3_v3(co[2], positions[vt->tri[2]]);
/* copy new locations into array */
if (moving) {
float co_moving[3][3];
/* update moving positions */
copy_v3_v3(co_moving[0], mvert_moving[vt->tri[0]].co);
copy_v3_v3(co_moving[1], mvert_moving[vt->tri[1]].co);
copy_v3_v3(co_moving[2], mvert_moving[vt->tri[2]].co);
copy_v3_v3(co_moving[0], positions_moving[vt->tri[0]]);
copy_v3_v3(co_moving[1], positions_moving[vt->tri[1]]);
copy_v3_v3(co_moving[2], positions_moving[vt->tri[2]]);
ret = BLI_bvhtree_update_node(bvhtree, i, &co[0][0], &co_moving[0][0], 3);
}
@ -670,7 +670,6 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
const bool is_hair = (clmd->hairdata != NULL);
for (int i = 0; i < collision_count; i++, collpair++) {
float i1[3], i2[3], i3[3];
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
zero_v3(i1);
zero_v3(i2);
@ -682,23 +681,13 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
}
/* Compute barycentric coordinates and relative "velocity" for both collision points. */
float w1 = collpair->aw1, w2 = collpair->aw2, w3 = collpair->aw3;
float u1 = collpair->bw1, u2 = collpair->bw2, u3 = collpair->bw3;
if (is_hair) {
w2 = line_point_factor_v3(
collpair->pa, cloth->verts[collpair->ap1].tx, cloth->verts[collpair->ap2].tx);
w1 = 1.0f - w2;
interp_v3_v3v3(v1, cloth->verts[collpair->ap1].tv, cloth->verts[collpair->ap2].tv, w2);
}
else {
collision_compute_barycentric(collpair->pa,
cloth->verts[collpair->ap1].tx,
cloth->verts[collpair->ap2].tx,
cloth->verts[collpair->ap3].tx,
&w1,
&w2,
&w3);
collision_interpolateOnTriangle(v1,
cloth->verts[collpair->ap1].tv,
cloth->verts[collpair->ap2].tv,
@ -708,18 +697,10 @@ static int cloth_collision_response_static(ClothModifierData *clmd,
w3);
}
collision_compute_barycentric(collpair->pb,
collmd->current_xnew[collpair->bp1].co,
collmd->current_xnew[collpair->bp2].co,
collmd->current_xnew[collpair->bp3].co,
&u1,
&u2,
&u3);
collision_interpolateOnTriangle(v2,
collmd->current_v[collpair->bp1].co,
collmd->current_v[collpair->bp2].co,
collmd->current_v[collpair->bp3].co,
collmd->current_v[collpair->bp1],
collmd->current_v[collpair->bp2],
collmd->current_v[collpair->bp3],
u1,
u2,
u3);
@ -834,7 +815,6 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
for (int i = 0; i < collision_count; i++, collpair++) {
float ia[3][3] = {{0.0f}};
float ib[3][3] = {{0.0f}};
float w1, w2, w3, u1, u2, u3;
float v1[3], v2[3], relativeVelocity[3];
/* Only handle static collisions here. */
@ -842,22 +822,9 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
continue;
}
/* Compute barycentric coordinates for both collision points. */
collision_compute_barycentric(collpair->pa,
cloth->verts[collpair->ap1].tx,
cloth->verts[collpair->ap2].tx,
cloth->verts[collpair->ap3].tx,
&w1,
&w2,
&w3);
collision_compute_barycentric(collpair->pb,
cloth->verts[collpair->bp1].tx,
cloth->verts[collpair->bp2].tx,
cloth->verts[collpair->bp3].tx,
&u1,
&u2,
&u3);
/* Retrieve barycentric coordinates for both collision points. */
float w1 = collpair->aw1, w2 = collpair->aw2, w3 = collpair->aw3;
float u1 = collpair->bw1, u2 = collpair->bw2, u3 = collpair->bw3;
/* Calculate relative "velocity". */
collision_interpolateOnTriangle(v1,
@ -1025,9 +992,9 @@ static void cloth_collision(void *__restrict userdata,
distance = compute_collision_point_tri_tri(verts1[tri_a->tri[0]].tx,
verts1[tri_a->tri[1]].tx,
verts1[tri_a->tri[2]].tx,
collmd->current_xnew[tri_b->tri[0]].co,
collmd->current_xnew[tri_b->tri[1]].co,
collmd->current_xnew[tri_b->tri[2]].co,
collmd->current_xnew[tri_b->tri[0]],
collmd->current_xnew[tri_b->tri[1]],
collmd->current_xnew[tri_b->tri[2]],
data->culling,
data->use_normal,
pa,
@ -1053,6 +1020,23 @@ static void cloth_collision(void *__restrict userdata,
collpair[index].flag = 0;
data->collided = true;
/* Compute barycentric coordinates for both collision points. */
collision_compute_barycentric(pa,
verts1[tri_a->tri[0]].tx,
verts1[tri_a->tri[1]].tx,
verts1[tri_a->tri[2]].tx,
&collpair[index].aw1,
&collpair[index].aw2,
&collpair[index].aw3);
collision_compute_barycentric(pb,
collmd->current_xnew[tri_b->tri[0]],
collmd->current_xnew[tri_b->tri[1]],
collmd->current_xnew[tri_b->tri[2]],
&collpair[index].bw1,
&collpair[index].bw2,
&collpair[index].bw3);
}
else {
collpair[index].flag = COLLISION_INACTIVE;
@ -1159,6 +1143,23 @@ static void cloth_selfcollision(void *__restrict userdata,
collpair[index].flag = 0;
data->collided = true;
/* Compute barycentric coordinates for both collision points. */
collision_compute_barycentric(pa,
verts1[tri_a->tri[0]].tx,
verts1[tri_a->tri[1]].tx,
verts1[tri_a->tri[2]].tx,
&collpair[index].aw1,
&collpair[index].aw2,
&collpair[index].aw3);
collision_compute_barycentric(pb,
verts1[tri_b->tri[0]].tx,
verts1[tri_b->tri[1]].tx,
verts1[tri_b->tri[2]].tx,
&collpair[index].bw1,
&collpair[index].bw2,
&collpair[index].bw3);
}
else {
collpair[index].flag = COLLISION_INACTIVE;
@ -1190,9 +1191,9 @@ static void hair_collision(void *__restrict userdata,
/* Compute distance and normal. */
distance = compute_collision_point_edge_tri(verts1[edge_coll->v1].tx,
verts1[edge_coll->v2].tx,
collmd->current_x[tri_coll->tri[0]].co,
collmd->current_x[tri_coll->tri[1]].co,
collmd->current_x[tri_coll->tri[2]].co,
collmd->current_x[tri_coll->tri[0]],
collmd->current_x[tri_coll->tri[1]],
collmd->current_x[tri_coll->tri[2]],
data->culling,
data->use_normal,
pa,
@ -1217,6 +1218,20 @@ static void hair_collision(void *__restrict userdata,
collpair[index].flag = 0;
data->collided = true;
/* Compute barycentric coordinates for the collision points. */
collpair[index].aw2 = line_point_factor_v3(
pa, verts1[edge_coll->v1].tx, verts1[edge_coll->v2].tx);
collpair[index].aw1 = 1.0f - collpair[index].aw2;
collision_compute_barycentric(pb,
collmd->current_xnew[tri_coll->tri[0]],
collmd->current_xnew[tri_coll->tri[1]],
collmd->current_xnew[tri_coll->tri[2]],
&collpair[index].bw1,
&collpair[index].bw2,
&collpair[index].bw3);
}
else {
collpair[index].flag = COLLISION_INACTIVE;
@ -1559,6 +1574,7 @@ int cloth_bvh_collision(
BVHTreeOverlap **overlap_obj = NULL;
uint coll_count_self = 0;
BVHTreeOverlap *overlap_self = NULL;
bool bvh_updated = false;
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh == NULL) {
return 0;
@ -1569,6 +1585,7 @@ int cloth_bvh_collision(
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
bvhtree_update_from_cloth(clmd, false, false);
bvh_updated = true;
/* Enable self collision if this is a hair sim */
const bool is_hair = (clmd->hairdata != NULL);
@ -1605,7 +1622,9 @@ int cloth_bvh_collision(
}
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) {
bvhtree_update_from_cloth(clmd, false, true);
if (cloth->bvhselftree != cloth->bvhtree || !bvh_updated) {
bvhtree_update_from_cloth(clmd, false, true);
}
overlap_self = BLI_bvhtree_overlap_self(
cloth->bvhselftree, &coll_count_self, cloth_bvh_self_overlap_cb, clmd);
@ -1728,17 +1747,17 @@ void collision_get_collider_velocity(float vel_old[3],
/* compute barycentric coordinates */
collision_compute_barycentric(collpair->pb,
collmd->current_x[collpair->bp1].co,
collmd->current_x[collpair->bp2].co,
collmd->current_x[collpair->bp3].co,
collmd->current_x[collpair->bp1],
collmd->current_x[collpair->bp2],
collmd->current_x[collpair->bp3],
&u1,
&u2,
&u3);
collision_interpolateOnTriangle(vel_new,
collmd->current_v[collpair->bp1].co,
collmd->current_v[collpair->bp2].co,
collmd->current_v[collpair->bp3].co,
collmd->current_v[collpair->bp1],
collmd->current_v[collpair->bp2],
collmd->current_v[collpair->bp3],
u1,
u2,
u3);

View File

@ -548,7 +548,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
else if (me_eval) {
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT);
const MVert *verts = BKE_mesh_verts(me_eval);
const float(*positions)[3] = BKE_mesh_vert_positions(me_eval);
int numVerts = me_eval->totvert;
/* check that dvert is a valid pointers (just in case) */
@ -557,11 +557,10 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
/* get the average of all verts with that are in the vertex-group */
for (int i = 0; i < numVerts; i++) {
const MDeformVert *dv = &dvert[i];
const MVert *mv = &verts[i];
const MDeformWeight *dw = BKE_defvert_find_index(dv, defgroup);
if (dw && dw->weight > 0.0f) {
madd_v3_v3fl(vec, mv->co, dw->weight);
madd_v3_v3fl(vec, positions[i], dw->weight);
madd_v3_v3fl(normal, vert_normals[i], dw->weight);
weightsum += dw->weight;
}

View File

@ -188,7 +188,7 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
/* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
const Span<MVert> verts = me->verts();
const Span<float3> positions = me->vert_positions();
const Span<MPoly> polys = me->polys();
const Span<MLoop> loops = me->loops();
@ -214,9 +214,9 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
co_next = origcos[ml_next->v];
}
else {
co_prev = verts[ml_prev->v].co;
co_curr = verts[ml_curr->v].co;
co_next = verts[ml_next->v].co;
co_prev = positions[ml_prev->v];
co_curr = positions[ml_curr->v];
co_next = positions[ml_next->v];
}
set_crazy_vertex_quat(

View File

@ -16,7 +16,7 @@
#include "BLI_ghash.h"
#include "BLI_index_range.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@ -704,7 +704,7 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
*newnu = blender::dna::shallow_copy(*src);
if (pntsu == 1) {
SWAP(int, pntsu, pntsv);
std::swap(pntsu, pntsv);
}
newnu->pntsu = pntsu;
newnu->pntsv = pntsv;
@ -3048,7 +3048,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_
bevp2 = bevp1 + (bl->nr - 1);
nr = bl->nr / 2;
while (nr--) {
SWAP(BevPoint, *bevp1, *bevp2);
std::swap(*bevp1, *bevp2);
bevp1++;
bevp2--;
}
@ -4437,7 +4437,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
a /= 2;
while (a > 0) {
if (bezt1 != bezt2) {
SWAP(BezTriple, *bezt1, *bezt2);
std::swap(*bezt1, *bezt2);
}
swap_v3_v3(bezt1->vec[0], bezt1->vec[2]);
@ -4446,12 +4446,12 @@ void BKE_nurb_direction_switch(Nurb *nu)
swap_v3_v3(bezt2->vec[0], bezt2->vec[2]);
}
SWAP(uint8_t, bezt1->h1, bezt1->h2);
SWAP(uint8_t, bezt1->f1, bezt1->f3);
std::swap(bezt1->h1, bezt1->h2);
std::swap(bezt1->f1, bezt1->f3);
if (bezt1 != bezt2) {
SWAP(uint8_t, bezt2->h1, bezt2->h2);
SWAP(uint8_t, bezt2->f1, bezt2->f3);
std::swap(bezt2->h1, bezt2->h2);
std::swap(bezt2->f1, bezt2->f3);
bezt1->tilt = -bezt1->tilt;
bezt2->tilt = -bezt2->tilt;
}
@ -4469,7 +4469,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
bp2 = bp1 + (a - 1);
a /= 2;
while (bp1 != bp2 && a > 0) {
SWAP(BPoint, *bp1, *bp2);
std::swap(*bp1, *bp2);
a--;
bp1->tilt = -bp1->tilt;
bp2->tilt = -bp2->tilt;
@ -4491,7 +4491,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
fp2 = fp1 + (a - 1);
a /= 2;
while (fp1 != fp2 && a > 0) {
SWAP(float, *fp1, *fp2);
std::swap(*fp1, *fp2);
a--;
fp1++;
fp2--;
@ -4530,7 +4530,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
a /= 2;
while (bp1 != bp2 && a > 0) {
SWAP(BPoint, *bp1, *bp2);
std::swap(*bp1, *bp2);
a--;
bp1++;
bp2--;

View File

@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array.hh"
#include "BLI_devirtualize_parameters.hh"
#include "BLI_set.hh"
#include "BLI_task.hh"
@ -189,7 +188,7 @@ static void fill_mesh_positions(const int main_point_num,
const Span<float3> tangents,
const Span<float3> normals,
const Span<float> radii,
MutableSpan<MVert> mesh_positions)
MutableSpan<float3> mesh_positions)
{
if (profile_point_num == 1) {
for (const int i_ring : IndexRange(main_point_num)) {
@ -198,9 +197,7 @@ static void fill_mesh_positions(const int main_point_num,
if (!radii.is_empty()) {
point_matrix.apply_scale(radii[i_ring]);
}
MVert &vert = mesh_positions[i_ring];
copy_v3_v3(vert.co, point_matrix * profile_positions.first());
mesh_positions[i_ring] = point_matrix * profile_positions.first();
}
}
else {
@ -213,8 +210,7 @@ static void fill_mesh_positions(const int main_point_num,
const int ring_vert_start = i_ring * profile_point_num;
for (const int i_profile : IndexRange(profile_point_num)) {
MVert &vert = mesh_positions[ring_vert_start + i_profile];
copy_v3_v3(vert.co, point_matrix * profile_positions[i_profile]);
mesh_positions[ring_vert_start + i_profile] = point_matrix * profile_positions[i_profile];
}
}
}
@ -644,7 +640,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
offsets.vert.last(), offsets.edge.last(), 0, offsets.loop.last(), offsets.poly.last());
mesh->flag |= ME_AUTOSMOOTH;
mesh->smoothresh = DEG2RADF(180.0f);
MutableSpan<MVert> verts = mesh->verts_for_write();
MutableSpan<float3> positions = mesh->vert_positions_for_write();
MutableSpan<MEdge> edges = mesh->edges_for_write();
MutableSpan<MPoly> polys = mesh->polys_for_write();
MutableSpan<MLoop> loops = mesh->loops_for_write();
@ -692,7 +688,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
tangents.slice(info.main_points),
normals.slice(info.main_points),
radii.is_empty() ? radii : radii.slice(info.main_points),
verts.slice(info.vert_range));
positions.slice(info.vert_range));
});
if (profile.curve_type_counts()[CURVE_TYPE_BEZIER] > 0) {

View File

@ -58,6 +58,7 @@
/* only for customdata_data_transfer_interp_normal_normals */
#include "data_transfer_intern.h"
using blender::float2;
using blender::IndexRange;
using blender::Set;
using blender::Span;
@ -1011,110 +1012,9 @@ static void layerInterp_mloopcol(const void **sources,
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MLoopUV, #CD_MLOOPUV)
/** \name Callbacks for #OrigSpaceLoop
* \{ */
static void layerCopyValue_mloopuv(const void *source,
void *dest,
const int mixmode,
const float mixfactor)
{
const MLoopUV *luv1 = static_cast<const MLoopUV *>(source);
MLoopUV *luv2 = static_cast<MLoopUV *>(dest);
/* We only support a limited subset of advanced mixing here -
* namely the mixfactor interpolation. */
if (mixmode == CDT_MIX_NOMIX) {
copy_v2_v2(luv2->uv, luv1->uv);
}
else {
interp_v2_v2v2(luv2->uv, luv2->uv, luv1->uv, mixfactor);
}
}
static bool layerEqual_mloopuv(const void *data1, const void *data2)
{
const MLoopUV *luv1 = static_cast<const MLoopUV *>(data1);
const MLoopUV *luv2 = static_cast<const MLoopUV *>(data2);
return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
}
static void layerMultiply_mloopuv(void *data, const float fac)
{
MLoopUV *luv = static_cast<MLoopUV *>(data);
mul_v2_fl(luv->uv, fac);
}
static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
{
MLoopUV *min = static_cast<MLoopUV *>(vmin);
MLoopUV *max = static_cast<MLoopUV *>(vmax);
INIT_MINMAX2(min->uv, max->uv);
}
static void layerDoMinMax_mloopuv(const void *data, void *vmin, void *vmax)
{
const MLoopUV *luv = static_cast<const MLoopUV *>(data);
MLoopUV *min = static_cast<MLoopUV *>(vmin);
MLoopUV *max = static_cast<MLoopUV *>(vmax);
minmax_v2v2_v2(min->uv, max->uv, luv->uv);
}
static void layerAdd_mloopuv(void *data1, const void *data2)
{
MLoopUV *l1 = static_cast<MLoopUV *>(data1);
const MLoopUV *l2 = static_cast<const MLoopUV *>(data2);
add_v2_v2(l1->uv, l2->uv);
}
static void layerInterp_mloopuv(const void **sources,
const float *weights,
const float * /*sub_weights*/,
int count,
void *dest)
{
float uv[2];
int flag = 0;
zero_v2(uv);
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const MLoopUV *src = static_cast<const MLoopUV *>(sources[i]);
madd_v2_v2fl(uv, src->uv, interp_weight);
if (interp_weight > 0.0f) {
flag |= src->flag;
}
}
/* Delay writing to the destination in case dest is in sources. */
copy_v2_v2(((MLoopUV *)dest)->uv, uv);
((MLoopUV *)dest)->flag = flag;
}
static bool layerValidate_mloopuv(void *data, const uint totitems, const bool do_fixes)
{
MLoopUV *uv = static_cast<MLoopUV *>(data);
bool has_errors = false;
for (int i = 0; i < totitems; i++, uv++) {
if (!is_finite_v2(uv->uv)) {
if (do_fixes) {
zero_v2(uv->uv);
}
has_errors = true;
}
}
return has_errors;
}
/* origspace is almost exact copy of mloopuv's, keep in sync */
static void layerCopyValue_mloop_origspace(const void *source,
void *dest,
@ -1616,6 +1516,46 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool
return has_errors;
}
static bool layerEqual_propfloat2(const void *data1, const void *data2)
{
const float2 &a = *static_cast<const float2 *>(data1);
const float2 &b = *static_cast<const float2 *>(data2);
return blender::math::distance_squared(a, b) < 0.00001f;
}
static void layerInitMinMax_propfloat2(void *vmin, void *vmax)
{
float2 &min = *static_cast<float2 *>(vmin);
float2 &max = *static_cast<float2 *>(vmax);
INIT_MINMAX2(min, max);
}
static void layerDoMinMax_propfloat2(const void *data, void *vmin, void *vmax)
{
const float2 &value = *static_cast<const float2 *>(data);
float2 &a = *static_cast<float2 *>(vmin);
float2 &b = *static_cast<float2 *>(vmax);
blender::math::min_max(value, a, b);
}
static void layerCopyValue_propfloat2(const void *source,
void *dest,
const int mixmode,
const float mixfactor)
{
const float2 &a = *static_cast<const float2 *>(source);
float2 &b = *static_cast<float2 *>(dest);
/* We only support a limited subset of advanced mixing here-
* namely the mixfactor interpolation. */
if (mixmode == CDT_MIX_NOMIX) {
b = a;
}
else {
b = blender::math::interpolate(b, a, mixfactor);
}
}
/** \} */
/* -------------------------------------------------------------------- */
@ -1638,7 +1578,7 @@ static void layerInterp_propbool(const void **sources,
}
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
/* 0: CD_MVERT */ /* DEPRECATED */
{sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 1: CD_MSTICKY */ /* DEPRECATED */
{sizeof(float[2]), "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
@ -1757,28 +1697,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* NOTE: when we expose the UV Map / TexFace split to the user,
* change this back to face Texture. */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 16: CD_MLOOPUV */
{sizeof(MLoopUV),
"MLoopUV",
1,
N_("UVMap"),
nullptr,
nullptr,
layerInterp_mloopuv,
nullptr,
nullptr,
nullptr,
layerValidate_mloopuv,
layerEqual_mloopuv,
layerMultiply_mloopuv,
layerInitMinMax_mloopuv,
layerAdd_mloopuv,
layerDoMinMax_mloopuv,
layerCopyValue_mloopuv,
nullptr,
nullptr,
nullptr,
layerMaxNum_tface},
/* 16: CD_MLOOPUV */ /* DEPRECATED */
{sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap")},
/* 17: CD_PROP_BYTE_COLOR */
{sizeof(MLoopCol),
"MLoopCol",
@ -2025,10 +1945,12 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
nullptr,
nullptr,
layerValidate_propfloat2,
nullptr,
layerEqual_propfloat2,
layerMultiply_propfloat2,
nullptr,
layerAdd_propfloat2},
layerInitMinMax_propfloat2,
layerAdd_propfloat2,
layerDoMinMax_propfloat2,
layerCopyValue_propfloat2},
/* 50: CD_PROP_BOOL */
{sizeof(bool),
"bool",
@ -2106,30 +2028,30 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
};
const CustomData_MeshMasks CD_MASK_BAREMESH = {
/* vmask */ CD_MASK_MVERT,
/* vmask */ CD_MASK_PROP_FLOAT3,
/* emask */ CD_MASK_MEDGE,
/* fmask */ 0,
/* pmask */ CD_MASK_MPOLY | CD_MASK_FACEMAP,
/* lmask */ CD_MASK_MLOOP,
};
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
/* vmask */ CD_MASK_MVERT | CD_MASK_ORIGINDEX,
/* vmask */ CD_MASK_PROP_FLOAT3 | CD_MASK_ORIGINDEX,
/* emask */ CD_MASK_MEDGE | CD_MASK_ORIGINDEX,
/* fmask */ 0,
/* pmask */ CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
/* lmask */ CD_MASK_MLOOP,
};
const CustomData_MeshMasks CD_MASK_MESH = {
/* vmask */ (CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK |
CD_MASK_PROP_ALL | CD_MASK_CREASE | CD_MASK_BWEIGHT),
/* vmask */ (CD_MASK_PROP_FLOAT3 | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN |
CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_CREASE | CD_MASK_BWEIGHT),
/* emask */
(CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_BWEIGHT | CD_MASK_CREASE),
/* fmask */ 0,
/* pmask */
(CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
(CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK |
CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
/* vmask */ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
@ -2142,8 +2064,8 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
/* pmask */
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
(CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
};
const CustomData_MeshMasks CD_MASK_BMESH = {
/* vmask */ (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
@ -2153,11 +2075,10 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
/* pmask */
(CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK |
CD_MASK_PROP_ALL),
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_EVERYTHING = {
/* vmask */ (CD_MASK_MVERT | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT |
/* vmask */ (CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT |
CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO |
CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK |
CD_MASK_PROP_ALL | CD_MASK_CREASE),
@ -2172,7 +2093,7 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
(CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP |
CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_MLOOPUV |
(CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL |
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
@ -2372,6 +2293,7 @@ bool CustomData_merge(const CustomData *source,
static bool attribute_stored_in_bmesh_flag(const StringRef name)
{
return ELEM(name,
"position",
".hide_vert",
".hide_edge",
".hide_poly",
@ -2398,7 +2320,7 @@ CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData
CustomData dst = *src;
dst.layers = static_cast<CustomDataLayer *>(
MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__));
dst.totlayer = dst_layers.size();
dst.maxlayer = dst.totlayer = dst_layers.size();
memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes());
CustomData_update_typemap(&dst);
@ -2585,6 +2507,17 @@ int CustomData_get_named_layer_index(const CustomData *data, const int type, con
return -1;
}
int CustomData_get_named_layer_index_notype(const CustomData *data, const char *name)
{
for (int i = 0; i < data->totlayer; i++) {
if (STREQ(data->layers[i].name, name)) {
return i;
}
}
return -1;
}
int CustomData_get_active_layer_index(const CustomData *data, const int type)
{
const int layer_index = data->typemap[type];
@ -4233,6 +4166,9 @@ void CustomData_from_bmesh_block(const CustomData *source,
/* copies a layer at a time */
int dest_i = 0;
for (int src_i = 0; src_i < source->totlayer; src_i++) {
if (source->layers[src_i].flag & CD_FLAG_NOCOPY) {
continue;
}
/* find the first dest layer with type >= the source type
* (this should work because layers are ordered by type)
@ -4373,6 +4309,20 @@ static bool customdata_unique_check(void *arg, const char *name)
return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
}
int CustomData_name_max_length_calc(const blender::StringRef name)
{
if (name.startswith(".")) {
return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX;
}
for (const blender::StringRef prefix :
{"." UV_VERTSEL_NAME, UV_EDGESEL_NAME ".", UV_PINNED_NAME "."}) {
if (name.startswith(prefix)) {
return MAX_CUSTOMDATA_LAYER_NAME;
}
}
return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX;
}
void CustomData_set_layer_unique_name(CustomData *data, const int index)
{
CustomDataLayer *nlayer = &data->layers[index];
@ -4384,14 +4334,15 @@ void CustomData_set_layer_unique_name(CustomData *data, const int index)
return;
}
const int max_length = CustomData_name_max_length_calc(nlayer->name);
/* Set default name if none specified. Note we only call DATA_() when
* needed to avoid overhead of locale lookups in the depsgraph. */
if (nlayer->name[0] == '\0') {
STRNCPY(nlayer->name, DATA_(typeInfo->defaultname));
}
BLI_uniquename_cb(
customdata_unique_check, &data_arg, nullptr, '.', nlayer->name, sizeof(nlayer->name));
BLI_uniquename_cb(customdata_unique_check, &data_arg, nullptr, '.', nlayer->name, max_length);
}
void CustomData_validate_layer_name(const CustomData *data,
@ -4476,8 +4427,9 @@ static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t c
switch (layer->type) {
/* When more instances of corrupt files are found, add them here. */
case CD_PROP_BOOL: /* See T84935. */
case CD_MLOOPUV: /* See T90620. */
case CD_PROP_BOOL: /* See T84935. */
case CD_MLOOPUV: /* See T90620. */
case CD_PROP_FLOAT2: /* See T90620. */
layer->data = MEM_calloc_arrayN(count, typeInfo->size, layerType_getName(layer->type));
BLI_assert(layer->data);
if (typeInfo->set_default_value) {

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