diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2021-07-18 14:14:23 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2021-07-18 14:14:23 +0300 |
commit | ca50a1f762703d477ee84cf494dec601fd540299 (patch) | |
tree | fbd86a77e77015d7cc6becc1255a63e436a45b2a /source/blender/modifiers/intern | |
parent | d35969a74ff7a71fc0ca233ae65a2f1c47eb9a25 (diff) | |
parent | e82c5c660778b3805f50f3f2901923692c17db2a (diff) |
Merge branch 'master' into geometry-nodes-unnamed-attributesgeometry-nodes-unnamed-attributes
Diffstat (limited to 'source/blender/modifiers/intern')
33 files changed, 283 insertions, 220 deletions
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 649d36e3d57..828b8b79664 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -37,6 +37,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_context.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" @@ -122,7 +123,8 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte /* If neither vertex groups nor envelopes are used, the modifier has no bone dependencies. */ if ((amd->deformflag & ARM_DEF_VGROUP) != 0) { /* Enumerate groups that match existing bones. */ - LISTBASE_FOREACH (bDeformGroup *, dg, &ctx->object->defbase) { + const ListBase *defbase = BKE_object_defgroup_list(ctx->object); + LISTBASE_FOREACH (bDeformGroup *, dg, defbase) { if (BKE_pose_channel_find_name(amd->object->pose, dg->name) != NULL) { /* Can't check BONE_NO_DEFORM because it can be animated. */ DEG_add_bone_relation( diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index c5e3833aa4a..722614c4831 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -427,7 +427,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } } - /* Build up offset array, cumulating all settings options */ + /* Build up offset array, accumulating all settings options. */ unit_m4(offset); src_mvert = mesh->mvert; diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index 4b9b24e4e47..bdb791dc8e7 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -109,7 +109,7 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u { BooleanModifierData *bmd = (BooleanModifierData *)md; - walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&bmd->collection, IDWALK_CB_USER); walk(userData, ob, (ID **)&bmd->object, IDWALK_CB_NOP); } diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index c38e5126f6b..52f21e3d3d0 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -101,7 +101,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct range_vn_i(faceMap, numPoly_src, 0); struct Scene *scene = DEG_get_input_scene(ctx->depsgraph); - frac = (BKE_scene_frame_get(scene) - bmd->start) / bmd->length; + frac = (BKE_scene_ctime_get(scene) - bmd->start) / bmd->length; CLAMP(frac, 0.0f, 1.0f); if (bmd->flag & MOD_BUILD_FLAG_REVERSE) { frac = 1.0f - frac; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 40d027f3044..4487adcfdda 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -206,6 +206,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tclmd->point_cache->step = clmd->point_cache->step; tclmd->point_cache->startframe = clmd->point_cache->startframe; tclmd->point_cache->endframe = clmd->point_cache->endframe; + tclmd->point_cache->flag |= (clmd->point_cache->flag & PTCACHE_FLAGS_COPY); } } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index fef235b456b..9e8f5bee396 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -267,7 +267,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd, { const float eps = FLT_EPSILON * 10.0f; const uint numEdges = (uint)mesh->totedge; - /* note: the way this smoothing method works, its approx half as strong as the simple-smooth, + /* NOTE: the way this smoothing method works, its approx half as strong as the simple-smooth, * and 2.0 rarely spikes, double the value for consistent behavior. */ const float lambda = csmd->lambda * 2.0f; const MEdge *edges = mesh->medge; diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 20dbb299767..aae6d257766 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -167,7 +167,7 @@ static void deformVertsEM(ModifierData *md, int defgrp_index = -1; if (ctx->object->type == OB_MESH && cmd->name[0] != '\0') { - defgrp_index = BKE_object_defgroup_name_index(ctx->object, cmd->name); + defgrp_index = BKE_id_defgroup_name_index(&mesh->id, cmd->name); if (defgrp_index != -1) { use_dverts = true; } diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index dbdc76f0edc..e2b2cc58d48 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -203,7 +203,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BKE_reports_init(&reports, RPT_STORE); - /* Note: no islands precision for now here. */ + /* NOTE: no islands precision for now here. */ if (BKE_object_data_transfer_ex(ctx->depsgraph, scene, ob_source, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 4e53243d820..bf197dca7e5 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -756,9 +756,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh) /* override original facepa (original pointer is saved in caller function) */ - /* BMESH_TODO, (totfsplit * 2) over allocation is used since the quads are + /* TODO(campbell): `(totfsplit * 2)` over allocation is used since the quads are * later interpreted as tri's, for this to work right I think we probably - * have to stop using tessface - campbell */ + * have to stop using tessface. */ facepa = MEM_calloc_arrayN((totface + (totfsplit * 2)), sizeof(int), "explode_facepa"); // memcpy(facepa, emd->facepa, totface*sizeof(int)); @@ -919,7 +919,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, EdgeHashIterator *ehi; float *vertco = NULL, imat[4][4]; float rot[4]; - float cfra; + float ctime; /* float timestep; */ const int *facepa = emd->facepa; int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0; @@ -940,7 +940,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* timestep = psys_get_timestep(&sim); */ - cfra = BKE_scene_frame_get(scene); + ctime = BKE_scene_ctime_get(scene); /* hash table for vertice <-> particle relations */ vertpahash = BLI_edgehash_new(__func__); @@ -962,7 +962,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* do mindex + totvert to ensure the vertex index to be the first * with BLI_edgehashIterator_getKey */ - if (pa == NULL || cfra < pa->time) { + if (pa == NULL || ctime < pa->time) { mindex = totvert + totpart; } else { @@ -1022,7 +1022,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, psys_get_birth_coords(&sim, pa, &birth, 0, 0); - state.time = cfra; + state.time = ctime; psys_get_particle_state(&sim, ed_v2, &state, 1); vertco = explode->mvert[v].co; @@ -1076,7 +1076,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, orig_v4 = source.v4; /* Same as above in the first loop over mesh's faces. */ - if (pa == NULL || cfra < pa->time) { + if (pa == NULL || ctime < pa->time) { mindex = totvert + totpart; } else { @@ -1096,7 +1096,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* override uv channel for particle age */ if (mtface) { - float age = (pa != NULL) ? (cfra - pa->time) / pa->lifetime : 0.0f; + float age = (pa != NULL) ? (ctime - pa->time) / pa->lifetime : 0.0f; /* Clamp to this range to avoid flipping to the other side of the coordinates. */ CLAMP(age, 0.001f, 0.999f); diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index ff581e92cdd..18ce37c5d85 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -94,7 +94,7 @@ static void requiredDataMask(Object *UNUSED(ob), r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; } if (hmd->indexar != NULL) { - /* TODO check which origindex are actually needed? */ + /* TODO: check which origindex are actually needed? */ r_cddata_masks->vmask |= CD_MASK_ORIGINDEX; r_cddata_masks->emask |= CD_MASK_ORIGINDEX; r_cddata_masks->pmask |= CD_MASK_ORIGINDEX; diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index a77f6cfe8ba..9aa8e3dd7c8 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -119,7 +119,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte /* A vertex will be in the mask if a selected bone influences it more than a certain threshold. */ static void compute_vertex_mask__armature_mode(MDeformVert *dvert, - Object *ob, + Mesh *mesh, Object *armature_ob, float threshold, MutableSpan<bool> r_vertex_mask) @@ -127,7 +127,7 @@ static void compute_vertex_mask__armature_mode(MDeformVert *dvert, /* Element i is true if there is a selected bone that uses vertex group i. */ Vector<bool> selected_bone_uses_group; - for (bDeformGroup *def : ListBaseWrapper<bDeformGroup>(ob->defbase)) { + LISTBASE_FOREACH (bDeformGroup *, def, &mesh->vertex_group_names) { bPoseChannel *pchan = BKE_pose_channel_find_name(armature_ob->pose, def->name); bool bone_for_group_exists = pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED); selected_bone_uses_group.append(bone_for_group_exists); @@ -325,10 +325,9 @@ void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, * 2. Find edges and polygons only using those vertices. * 3. Create a new mesh that only uses the found vertices, edges and polygons. */ -static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md); - Object *ob = ctx->object; const bool invert_mask = mmd->flag & MOD_MASK_INV; /* Return empty or input mesh when there are no vertex groups. */ @@ -339,7 +338,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Quick test to see if we can return early. */ if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (mesh->totvert == 0) || - BLI_listbase_is_empty(&ob->defbase)) { + BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } @@ -348,15 +347,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Object *armature_ob = mmd->ob_arm; /* Return input mesh if there is no armature with bones. */ - if (ELEM(NULL, armature_ob, armature_ob->pose, ob->defbase.first)) { + if (ELEM(NULL, armature_ob, armature_ob->pose)) { return mesh; } vertex_mask = Array<bool>(mesh->totvert); - compute_vertex_mask__armature_mode(dvert, ob, armature_ob, mmd->threshold, vertex_mask); + compute_vertex_mask__armature_mode(dvert, mesh, armature_ob, mmd->threshold, vertex_mask); } else { - int defgrp_index = BKE_object_defgroup_name_index(ob, mmd->vgroup); + int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, mmd->vgroup); /* Return input mesh if the vertex group does not exist. */ if (defgrp_index == -1) { diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 6ec3277ee7a..e0507320628 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -104,20 +104,20 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* -------------------------------------------------------------------- */ /* Interpret Time (the reading functions also do some of this ) */ if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) { - const float cfra = BKE_scene_frame_get(scene); + const float ctime = BKE_scene_ctime_get(scene); switch (mcmd->time_mode) { case MOD_MESHCACHE_TIME_FRAME: { - time = cfra; + time = ctime; break; } case MOD_MESHCACHE_TIME_SECONDS: { - time = cfra / fps; + time = ctime / fps; break; } case MOD_MESHCACHE_TIME_FACTOR: default: { - time = cfra / fps; + time = ctime / fps; break; } } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index f7f7c7b0276..87fce26c45e 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -48,6 +48,7 @@ #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" +#include "BKE_attribute_math.hh" #include "BKE_customdata.h" #include "BKE_geometry_set_instances.hh" #include "BKE_global.h" @@ -56,7 +57,6 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_modifier.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "BKE_pointcloud.h" #include "BKE_screen.h" @@ -83,8 +83,10 @@ #include "NOD_derived_node_tree.hh" #include "NOD_geometry.h" +#include "NOD_geometry_nodes_eval_log.hh" #include "NOD_node_tree_multi_function.hh" +using blender::destruct_ptr; using blender::float3; using blender::FunctionRef; using blender::IndexRange; @@ -97,6 +99,7 @@ using blender::Vector; using blender::fn::GMutablePointer; using blender::fn::GPointer; using blender::nodes::GeoNodeExecParams; +using blender::threading::EnumerableThreadSpecific; using namespace blender::fn::multi_function_types; using namespace blender::nodes::derived_node_tree_types; @@ -734,19 +737,6 @@ static void initialize_group_input(NodesModifierData &nmd, property_type->init_cpp_value(*property, r_value); } -static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> trees, - const Object &object, - const ModifierData &modifier) -{ - const NodeTreeEvaluationContext context = {object, modifier}; - - for (const blender::nodes::NodeTreeRef *tree : trees) { - bNodeTree *btree_cow = tree->btree(); - bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow); - BKE_nodetree_ui_storage_free_for_context(*btree_original, context); - } -} - static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) { wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; @@ -766,24 +756,6 @@ static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) return spreadsheets; } -using PreviewSocketMap = blender::MultiValueMap<DSocket, uint64_t>; - -static DSocket try_find_preview_socket_in_node(const DNode node) -{ - for (const SocketRef *socket : node->outputs()) { - if (socket->bsocket()->type == SOCK_GEOMETRY) { - return {node.context(), socket}; - } - } - for (const SocketRef *socket : node->inputs()) { - if (socket->bsocket()->type == SOCK_GEOMETRY && - (socket->bsocket()->flag & SOCK_MULTI_INPUT) == 0) { - return {node.context(), socket}; - } - } - return {}; -} - static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadsheet, NodesModifierData *nmd, const ModifierEvalContext *ctx, @@ -837,9 +809,10 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre } const NodeTreeRef &tree_ref = context->tree(); - for (const NodeRef *node_ref : tree_ref.nodes()) { + for (const NodeRef *node_ref : tree_ref.nodes_by_type("GeometryNodeViewer")) { if (node_ref->name() == last_context->node_name) { - return try_find_preview_socket_in_node({context, node_ref}); + const DNode viewer_node{context, node_ref}; + return viewer_node.input(0); } } return {}; @@ -848,7 +821,7 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre static void find_sockets_to_preview(NodesModifierData *nmd, const ModifierEvalContext *ctx, const DerivedNodeTree &tree, - PreviewSocketMap &r_sockets_to_preview) + Set<DSocket> &r_sockets_to_preview) { Main *bmain = DEG_get_bmain(ctx->depsgraph); @@ -858,51 +831,16 @@ static void find_sockets_to_preview(NodesModifierData *nmd, for (SpaceSpreadsheet *sspreadsheet : spreadsheets) { const DSocket socket = try_get_socket_to_preview_for_spreadsheet(sspreadsheet, nmd, ctx, tree); if (socket) { - const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet); - r_sockets_to_preview.add_non_duplicates(socket, key); + r_sockets_to_preview.add(socket); } } } -static void log_preview_socket_value(const Span<GPointer> values, - Object *object, - Span<uint64_t> keys) +static void clear_runtime_data(NodesModifierData *nmd) { - GeometrySet geometry_set = *(const GeometrySet *)values[0].get(); - geometry_set.ensure_owns_direct_data(); - for (uint64_t key : keys) { - BKE_object_preview_geometry_set_add(object, key, new GeometrySet(geometry_set)); - } -} - -static void log_ui_hints(const DSocket socket, - const Span<GPointer> values, - Object *self_object, - NodesModifierData *nmd) -{ - const DNode node = socket.node(); - if (node->is_reroute_node() || socket->typeinfo()->type != SOCK_GEOMETRY) { - return; - } - bNodeTree *btree_cow = node->btree(); - bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow); - const NodeTreeEvaluationContext context{*self_object, nmd->modifier}; - for (const GPointer &data : values) { - if (data.type() == &CPPType::get<GeometrySet>()) { - const GeometrySet &geometry_set = *(const GeometrySet *)data.get(); - blender::bke::geometry_set_instances_attribute_foreach( - geometry_set, - [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) { - BKE_nodetree_attribute_hint_add(*btree_original, - context, - *node->bnode(), - attribute_name, - meta_data.domain, - meta_data.data_type); - return true; - }, - 8); - } + if (nmd->runtime_eval_log != nullptr) { + delete (geo_log::ModifierLog *)nmd->runtime_eval_log; + nmd->runtime_eval_log = nullptr; } } @@ -958,30 +896,32 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree, Vector<DInputSocket> group_outputs; group_outputs.append({root_context, &socket_to_compute}); - PreviewSocketMap preview_sockets; - find_sockets_to_preview(nmd, ctx, tree, preview_sockets); - - auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) { - if (!logging_enabled(ctx)) { - return; - } - Span<uint64_t> keys = preview_sockets.lookup(socket); - if (!keys.is_empty()) { - log_preview_socket_value(values, ctx->object, keys); - } - log_ui_hints(socket, values, ctx->object, nmd); - }; + std::optional<geo_log::GeoLogger> geo_logger; blender::modifiers::geometry_nodes::GeometryNodesEvaluationParams eval_params; + + if (logging_enabled(ctx)) { + Set<DSocket> preview_sockets; + find_sockets_to_preview(nmd, ctx, tree, preview_sockets); + eval_params.force_compute_sockets.extend(preview_sockets.begin(), preview_sockets.end()); + geo_logger.emplace(std::move(preview_sockets)); + } + eval_params.input_values = group_inputs; eval_params.output_sockets = group_outputs; eval_params.mf_by_node = &mf_by_node; eval_params.modifier_ = nmd; eval_params.depsgraph = ctx->depsgraph; eval_params.self_object = ctx->object; - eval_params.log_socket_value_fn = log_socket_value; + eval_params.geo_logger = geo_logger.has_value() ? &*geo_logger : nullptr; blender::modifiers::geometry_nodes::evaluate_geometry_nodes(eval_params); + if (geo_logger.has_value()) { + NodesModifierData *nmd_orig = (NodesModifierData *)BKE_modifier_get_original(&nmd->modifier); + clear_runtime_data(nmd_orig); + nmd_orig->runtime_eval_log = new geo_log::ModifierLog(*geo_logger); + } + BLI_assert(eval_params.r_output_values.size() == 1); GMutablePointer result = eval_params.r_output_values[0]; return result.relocate_out<GeometrySet>(); @@ -1071,10 +1011,6 @@ static void modifyGeometry(ModifierData *md, return; } - if (logging_enabled(ctx)) { - reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md); - } - geometry_set = compute_geometry( tree, input_nodes, *group_outputs[0], std::move(geometry_set), nmd, ctx); } @@ -1082,13 +1018,14 @@ static void modifyGeometry(ModifierData *md, static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { GeometrySet geometry_set = GeometrySet::create_with_mesh(mesh, GeometryOwnershipType::Editable); - geometry_set.get_component_for_write<MeshComponent>().copy_vertex_group_names_from_object( - *ctx->object); + modifyGeometry(md, ctx, geometry_set); - /* This function is only called when applying modifiers. In this case it makes sense to realize - * instances, otherwise in some cases there might be no results when applying the modifier. */ - geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set); + if (ctx->flag & MOD_APPLY_TO_BASE_MESH) { + /* In this case it makes sense to realize instances, otherwise in some cases there might be no + * results when applying the modifier. */ + geometry_set = blender::bke::geometry_set_realize_mesh_for_modifier(geometry_set); + } Mesh *new_mesh = geometry_set.get_component_for_write<MeshComponent>().release(); if (new_mesh == nullptr) { @@ -1219,6 +1156,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md); BLO_read_data_address(reader, &nmd->settings.properties); IDP_BlendDataRead(reader, &nmd->settings.properties); + nmd->runtime_eval_log = nullptr; } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -1228,6 +1166,8 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla BKE_modifier_copydata_generic(md, target, flag); + tnmd->runtime_eval_log = nullptr; + if (nmd->settings.properties != nullptr) { tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag); } @@ -1240,6 +1180,8 @@ static void freeData(ModifierData *md) IDP_FreeProperty_ex(nmd->settings.properties, false); nmd->settings.properties = nullptr; } + + clear_runtime_data(nmd); } static void requiredDataMask(Object *UNUSED(ob), diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index c2f2f358b9e..cf18f60ec22 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -411,6 +411,9 @@ class GeometryNodesEvaluator { for (const DInputSocket &socket : params_.output_sockets) { nodes_to_check.push(socket.node()); } + for (const DSocket &socket : params_.force_compute_sockets) { + nodes_to_check.push(socket.node()); + } /* Use the local allocator because the states do not need to outlive the evaluator. */ LinearAllocator<> &allocator = local_allocators_.local(); while (!nodes_to_check.is_empty()) { @@ -544,7 +547,8 @@ class GeometryNodesEvaluator { }, {}); if (output_state.potential_users == 0) { - /* If it does not have any potential users, it is unused. */ + /* If it does not have any potential users, it is unused. It might become required again in + * `schedule_initial_nodes`. */ output_state.output_usage = ValueUsage::Unused; } } @@ -622,11 +626,11 @@ class GeometryNodesEvaluator { for (auto &&item : params_.input_values.items()) { const DOutputSocket socket = item.key; GMutablePointer value = item.value; - this->log_socket_value(socket, value); const DNode node = socket.node(); if (!node_states_.contains_as(node)) { /* The socket is not connected to any output. */ + this->log_socket_value({socket}, value); value.destruct(); continue; } @@ -644,6 +648,20 @@ class GeometryNodesEvaluator { this->set_input_required(locked_node, socket); }); } + for (const DSocket socket : params_.force_compute_sockets) { + const DNode node = socket.node(); + NodeState &node_state = this->get_node_state(node); + this->with_locked_node(node, node_state, [&](LockedNode &locked_node) { + if (socket->is_input()) { + this->set_input_required(locked_node, DInputSocket(socket)); + } + else { + OutputState &output_state = node_state.outputs[socket->index()]; + output_state.output_usage = ValueUsage::Required; + this->schedule_node(locked_node); + } + }); + } } void schedule_node(LockedNode &locked_node) @@ -830,7 +848,6 @@ class GeometryNodesEvaluator { /* Checks if all the linked sockets have been provided already. */ if (multi_value.items.size() == multi_value.expected_size) { input_state.was_ready_for_execution = true; - this->log_socket_value(socket, input_state, multi_value.items); } else if (is_required) { /* The input is required but is not fully provided yet. Therefore the node cannot be @@ -842,7 +859,6 @@ class GeometryNodesEvaluator { SingleInputValue &single_value = *input_state.value.single; if (single_value.value != nullptr) { input_state.was_ready_for_execution = true; - this->log_socket_value(socket, GPointer{input_state.type, single_value.value}); } else if (is_required) { /* The input is required but has not been provided yet. Therefore the node cannot be @@ -1192,10 +1208,14 @@ class GeometryNodesEvaluator { this->with_locked_node(node, node_state, [&](LockedNode &locked_node) { output_state.potential_users -= 1; if (output_state.potential_users == 0) { - /* The output socket has no users anymore. */ - output_state.output_usage = ValueUsage::Unused; - /* Schedule the origin node in case it wants to set its inputs as unused as well. */ - this->schedule_node(locked_node); + /* The socket might be required even though the output is not used by other sockets. That + * can happen when the socket is forced to be computed. */ + if (output_state.output_usage != ValueUsage::Required) { + /* The output socket has no users anymore. */ + output_state.output_usage = ValueUsage::Unused; + /* Schedule the origin node in case it wants to set its inputs as unused as well. */ + this->schedule_node(locked_node); + } } }); } @@ -1216,16 +1236,17 @@ class GeometryNodesEvaluator { { BLI_assert(value_to_forward.get() != nullptr); + Vector<DSocket> sockets_to_log_to; + sockets_to_log_to.append(from_socket); + Vector<DInputSocket> to_sockets; auto handle_target_socket_fn = [&, this](const DInputSocket to_socket) { if (this->should_forward_to_socket(to_socket)) { to_sockets.append(to_socket); } }; - auto handle_skipped_socket_fn = [&, this](const DSocket socket) { - /* Log socket value on intermediate sockets to support e.g. attribute search or spreadsheet - * breadcrumbs on group nodes. */ - this->log_socket_value(socket, value_to_forward); + auto handle_skipped_socket_fn = [&](const DSocket socket) { + sockets_to_log_to.append(socket); }; from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn); @@ -1238,11 +1259,18 @@ class GeometryNodesEvaluator { if (from_type == to_type) { /* All target sockets that do not need a conversion will be handled afterwards. */ to_sockets_same_type.append(to_socket); + /* Multi input socket values are logged once all values are available. */ + if (!to_socket->is_multi_input_socket()) { + sockets_to_log_to.append(to_socket); + } continue; } this->forward_to_socket_with_different_type( allocator, value_to_forward, from_socket, to_socket, to_type); } + + this->log_socket_value(sockets_to_log_to, value_to_forward); + this->forward_to_sockets_with_same_type( allocator, to_sockets_same_type, value_to_forward, from_socket); } @@ -1273,6 +1301,7 @@ class GeometryNodesEvaluator { /* Allocate a buffer for the converted value. */ void *buffer = allocator.allocate(to_type.size(), to_type.alignment()); + GMutablePointer value{to_type, buffer}; if (conversions_.is_convertible(from_type, to_type)) { /* Do the conversion if possible. */ @@ -1282,7 +1311,11 @@ class GeometryNodesEvaluator { /* Cannot convert, use default value instead. */ to_type.copy_construct(to_type.default_value(), buffer); } - this->add_value_to_input_socket(to_socket, from_socket, {to_type, buffer}); + /* Multi input socket values are logged once all values are available. */ + if (!to_socket->is_multi_input_socket()) { + this->log_socket_value({to_socket}, value); + } + this->add_value_to_input_socket(to_socket, from_socket, value); } void forward_to_sockets_with_same_type(LinearAllocator<> &allocator, @@ -1330,6 +1363,10 @@ class GeometryNodesEvaluator { /* Add a new value to the multi-input. */ MultiInputValue &multi_value = *input_state.value.multi; multi_value.items.append({origin, value.get()}); + + if (multi_value.expected_size == multi_value.items.size()) { + this->log_socket_value({socket}, input_state, multi_value.items); + } } else { /* Assign the value to the input. */ @@ -1360,10 +1397,14 @@ class GeometryNodesEvaluator { if (input_socket->is_multi_input_socket()) { MultiInputValue &multi_value = *input_state.value.multi; multi_value.items.append({origin_socket, value.get()}); + if (multi_value.expected_size == multi_value.items.size()) { + this->log_socket_value({input_socket}, input_state, multi_value.items); + } } else { SingleInputValue &single_value = *input_state.value.single; single_value.value = value.get(); + this->log_socket_value({input_socket}, value); } } @@ -1416,29 +1457,27 @@ class GeometryNodesEvaluator { return *node_states_.lookup_key_as(node).state; } - void log_socket_value(const DSocket socket, Span<GPointer> values) + void log_socket_value(DSocket socket, InputState &input_state, Span<MultiInputValueItem> values) { - if (params_.log_socket_value_fn) { - params_.log_socket_value_fn(socket, values); + if (params_.geo_logger == nullptr) { + return; } - } - void log_socket_value(const DSocket socket, - InputState &input_state, - Span<MultiInputValueItem> values) - { Vector<GPointer, 16> value_pointers; value_pointers.reserve(values.size()); const CPPType &type = *input_state.type; for (const MultiInputValueItem &item : values) { value_pointers.append({type, item.value}); } - this->log_socket_value(socket, value_pointers); + params_.geo_logger->local().log_multi_value_socket(socket, value_pointers); } - void log_socket_value(const DSocket socket, GPointer value) + void log_socket_value(Span<DSocket> sockets, GPointer value) { - this->log_socket_value(socket, Span<GPointer>(&value, 1)); + if (params_.geo_logger == nullptr) { + return; + } + params_.geo_logger->local().log_value_for_sockets(sockets, value); } /* In most cases when `NodeState` is accessed, the node has to be locked first to avoid race @@ -1477,6 +1516,7 @@ NodeParamsProvider::NodeParamsProvider(GeometryNodesEvaluator &evaluator, this->self_object = evaluator.params_.self_object; this->modifier = &evaluator.params_.modifier_->modifier; this->depsgraph = evaluator.params_.depsgraph; + this->logger = evaluator.params_.geo_logger; } bool NodeParamsProvider::can_get_input(StringRef identifier) const @@ -1576,8 +1616,6 @@ void NodeParamsProvider::set_output(StringRef identifier, GMutablePointer value) const DOutputSocket socket = this->dnode.output_by_identifier(identifier); BLI_assert(socket); - evaluator_.log_socket_value(socket, value); - OutputState &output_state = node_state_.outputs[socket->index()]; BLI_assert(!output_state.has_been_computed); evaluator_.forward_output(socket, value); diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh index 84249e4244e..f4ee6242dcb 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh @@ -19,30 +19,37 @@ #include "BLI_map.hh" #include "NOD_derived_node_tree.hh" +#include "NOD_geometry_nodes_eval_log.hh" #include "NOD_node_tree_multi_function.hh" #include "FN_generic_pointer.hh" #include "DNA_modifier_types.h" +namespace geo_log = blender::nodes::geometry_nodes_eval_log; + namespace blender::modifiers::geometry_nodes { using namespace nodes::derived_node_tree_types; using fn::GMutablePointer; using fn::GPointer; -using LogSocketValueFn = std::function<void(DSocket, Span<GPointer>)>; - struct GeometryNodesEvaluationParams { blender::LinearAllocator<> allocator; Map<DOutputSocket, GMutablePointer> input_values; Vector<DInputSocket> output_sockets; + /* These sockets will be computed but are not part of the output. Their value can be retrieved in + * `log_socket_value_fn`. These sockets are not part of `output_sockets` because then the + * evaluator would have to keep the socket values in memory until the end, which might not be + * necessary in all cases. Sometimes `log_socket_value_fn` might just want to look at the value + * and then it can be freed. */ + Vector<DSocket> force_compute_sockets; nodes::MultiFunctionByNode *mf_by_node; const NodesModifierData *modifier_; Depsgraph *depsgraph; Object *self_object; - LogSocketValueFn log_socket_value_fn; + geo_log::GeoLogger *geo_logger; Vector<GMutablePointer> r_output_values; }; diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 4bfd6aba4b2..54bb68dc21a 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -335,7 +335,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, if (do_polynors_fix && polygons_check_flip(mloop, nos, &mesh->ldata, mpoly, polynors, num_polys)) { - /* XXX TODO is this still needed? */ + /* XXX TODO: is this still needed? */ // mesh->dirty |= DM_DIRTY_TESS_CDLAYERS; /* We need to recompute vertex normals! */ BKE_mesh_calc_normals(mesh); diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 3de6bb62c8a..8f3206da5be 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -455,7 +455,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes /* displace the geometry */ - /* Note: tried to parallelized that one and previous foam loop, + /* NOTE: tried to parallelized that one and previous foam loop, * but gives 20% slower results... odd. */ { const int num_verts = result->totvert; diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 62ac9d4452d..49b5dabe72d 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -182,7 +182,7 @@ static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *ps totpart = psys->totpart + psys->totchild; - /* TODO make randomization optional? */ + /* TODO: make randomization optional? */ randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart; minp = (int)(totpart * pimd->particle_offset) % (totpart + 1); @@ -442,7 +442,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mul_qt_qtqt(frame, frame, rot); } - /* note: direction is same as normal vector currently, + /* NOTE: direction is same as normal vector currently, * but best to keep this separate so the frame can be * rotated later if necessary */ diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 38cce5e6a50..ef70f3fe6f4 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -120,7 +120,6 @@ static void deformVerts(ModifierData *md, Mesh *mesh_src = mesh; ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; ParticleSystem *psys = NULL; - /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */ if (ctx->object->particlesystem.first) { psys = psmd->psys; diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index b90bf91dcb8..0819b314e32 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -357,7 +357,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1); /* Will the screw be closed? - * Note! smaller than `FLT_EPSILON * 100` + * NOTE: smaller than `FLT_EPSILON * 100` * gives problems with float precision so its never closed. */ if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f) && step_tot > 3) { diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 58d70ef3a4a..543cee18868 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -296,7 +296,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe) bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "convex_hull input=%hv", BM_ELEM_TAG); BMO_op_exec(bm, &op); - if (BMO_error_occurred(bm)) { + if (BMO_error_occurred_at_level(bm, BMO_ERROR_CANCEL)) { BMO_op_finish(bm, &op); return false; } @@ -1202,7 +1202,7 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, BMVert **orig_ slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); - /* Note: could probably calculate merges in one go to be + /* NOTE: could probably calculate merges in one go to be * faster */ v_safe = shortest_edge->v1; diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 95fb87bb54c..e97190b1878 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -242,9 +242,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; - const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object, - smd->shell_defgrp_name); - const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name); + const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name); + const int rim_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->rim_defgrp_name); /* array size is doubled in case of using a shell */ const uint stride = do_shell ? 2 : 1; @@ -505,7 +504,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex } } - /* note, copied vertex layers don't have flipped normals yet. do this after applying offset */ + /* NOTE: copied vertex layers don't have flipped normals yet. do this after applying offset. */ if ((smd->flag & MOD_SOLIDIFY_EVEN) == 0) { /* no even thickness, very simple */ float scalar_short; @@ -1028,14 +1027,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex if (do_rim) { uint i; - /* bugger, need to re-calculate the normals for the new edge faces. + /* NOTE(campbell): Unfortunately re-calculate the normals for the new edge faces is necessary. * This could be done in many ways, but probably the quickest way * is to calculate the average normals for side faces only. * Then blend them with the normals of the edge verts. * - * at the moment its easiest to allocate an entire array for every vertex, - * even though we only need edge verts - campbell - */ + * At the moment its easiest to allocate an entire array for every vertex, + * even though we only need edge verts. */ #define SOLIDIFY_SIDE_NORMALS @@ -1200,7 +1198,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex short *nor_short; int k; - /* note, only the first vertex (lower half of the index) is calculated */ + /* NOTE: only the first vertex (lower half of the index) is calculated. */ BLI_assert(ed->v1 < numVerts); normalize_v3_v3(nor_cpy, edge_vert_nos[ed_orig->v1]); diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 0f8503eddde..b872f04b60f 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -181,9 +181,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; - const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object, - smd->shell_defgrp_name); - const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name); + const int shell_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->shell_defgrp_name); + const int rim_defgrp_index = BKE_id_defgroup_name_index(&mesh->id, smd->rim_defgrp_name); MOD_get_vgroup(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index); @@ -913,7 +912,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, uint unassigned_edges_len = 0; for (uint j = 0; j < tot_adj_edges; j++) { NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]]; - /* TODO check where the null pointer come from, + /* TODO: check where the null pointer come from, * because there should not be any... */ if (new_edges) { /* count the number of new edges around the original vert */ @@ -1107,7 +1106,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(unassigned_edges); - /* TODO reshape the edge_groups array to its actual size + /* TODO: reshape the edge_groups array to its actual size * after writing is finished to save on memory. */ } @@ -1374,7 +1373,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(vert_adj_edges); } - /* TODO create_regions if fix_intersections. */ + /* TODO: create_regions if fix_intersections. */ /* General use pointer for #EdgeGroup iteration. */ EdgeGroup **gs_ptr; @@ -1854,7 +1853,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, MEM_freeN(null_faces); } - /* TODO create vertdata for intersection fixes (intersection fixing per topology region). */ + /* TODO: create vertdata for intersection fixes (intersection fixing per topology region). */ /* Correction for adjacent one sided groups around a vert to * prevent edge duplicates and null polys. */ @@ -2018,7 +2017,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, * - new_edge value should have no duplicates * - every old_edge value should appear twice * - every group should have at least two members (edges) - * Note: that there can be vertices that only have one group. They are called singularities. + * NOTE: that there can be vertices that only have one group. They are called singularities. * These vertices will only have one side (there is no way of telling apart front * from back like on a mobius strip) */ diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index dd011a293ee..ec6de8f8387 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -94,6 +94,11 @@ typedef struct SDefBindCalcData { float imat[4][4]; const float falloff; int success; + /** Vertex group lookup data. */ + const MDeformVert *const dvert; + int const defgrp_index; + bool const invert_vgroup; + bool const sparse_bind; } SDefBindCalcData; /** @@ -218,7 +223,7 @@ static void freeData(ModifierData *md) SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { if (smd->verts[i].binds) { for (int j = 0; j < smd->verts[i].numbinds; j++) { MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds); @@ -243,7 +248,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla if (smd->verts) { tsmd->verts = MEM_dupallocN(smd->verts); - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { if (smd->verts[i].binds) { tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds); @@ -963,12 +968,32 @@ static void bindVert(void *__restrict userdata, SDefBindPoly *bpoly; SDefBind *sdbind; + sdvert->vertex_idx = index; + if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) { sdvert->binds = NULL; sdvert->numbinds = 0; return; } + if (data->sparse_bind) { + float weight = 0.0f; + + if (data->dvert && data->defgrp_index != -1) { + weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index); + } + + if (data->invert_vgroup) { + weight = 1.0f - weight; + } + + if (weight <= 0) { + sdvert->binds = NULL; + sdvert->numbinds = 0; + return; + } + } + copy_v3_v3(point_co, data->vertexCos[index]); bwdata = computeBindWeights(data, point_co); @@ -1135,6 +1160,21 @@ static void bindVert(void *__restrict userdata, freeBindData(bwdata); } +/* Remove vertices without bind data from the bind array. */ +static void compactSparseBinds(SurfaceDeformModifierData *smd) +{ + smd->num_bind_verts = 0; + + for (uint i = 0; i < smd->num_mesh_verts; i++) { + if (smd->verts[i].numbinds > 0) { + smd->verts[smd->num_bind_verts++] = smd->verts[i]; + } + } + + smd->verts = MEM_reallocN_id( + smd->verts, sizeof(*smd->verts) * smd->num_bind_verts, "SDefBindVerts (sparse)"); +} + static bool surfacedeformBind(Object *ob, SurfaceDeformModifierData *smd_orig, SurfaceDeformModifierData *smd_eval, @@ -1142,7 +1182,8 @@ static bool surfacedeformBind(Object *ob, uint numverts, uint tnumpoly, uint tnumverts, - Mesh *target) + Mesh *target, + Mesh *mesh) { BVHTreeFromMesh treeData = {NULL}; const MVert *mvert = target->mvert; @@ -1205,9 +1246,15 @@ static bool surfacedeformBind(Object *ob, return false; } - smd_orig->numverts = numverts; + smd_orig->num_mesh_verts = numverts; smd_orig->numpoly = tnumpoly; + int defgrp_index; + MDeformVert *dvert; + MOD_get_vgroup(ob, mesh, smd_orig->defgrp_name, &dvert, &defgrp_index); + const bool invert_vgroup = (smd_orig->flags & MOD_SDEF_INVERT_VGROUP) != 0; + const bool sparse_bind = (smd_orig->flags & MOD_SDEF_SPARSE_BIND) != 0; + SDefBindCalcData data = { .treeData = &treeData, .vert_edges = vert_edges, @@ -1221,6 +1268,10 @@ static bool surfacedeformBind(Object *ob, .vertexCos = vertexCos, .falloff = smd_orig->falloff, .success = MOD_SDEF_BIND_RESULT_SUCCESS, + .dvert = dvert, + .defgrp_index = defgrp_index, + .invert_vgroup = invert_vgroup, + .sparse_bind = sparse_bind, }; if (data.targetCos == NULL) { @@ -1242,6 +1293,13 @@ static bool surfacedeformBind(Object *ob, MEM_freeN(data.targetCos); + if (sparse_bind) { + compactSparseBinds(smd_orig); + } + else { + smd_orig->num_bind_verts = numverts; + } + if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); @@ -1267,6 +1325,11 @@ static bool surfacedeformBind(Object *ob, BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } + else if (smd_orig->num_bind_verts == 0 || !smd_orig->verts) { + data.success = MOD_SDEF_BIND_RESULT_GENERIC_ERR; + BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "No vertices were bound"); + freeData((ModifierData *)smd_orig); + } freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); @@ -1281,14 +1344,15 @@ static void deformVert(void *__restrict userdata, const SDefDeformData *const data = (SDefDeformData *)userdata; const SDefBind *sdbind = data->bind_verts[index].binds; const int num_binds = data->bind_verts[index].numbinds; - float *const vertexCos = data->vertexCos[index]; + const unsigned int vertex_idx = data->bind_verts[index].vertex_idx; + float *const vertexCos = data->vertexCos[vertex_idx]; float norm[3], temp[3], offset[3]; /* Retrieve the value of the weight vertex group if specified. */ float weight = 1.0f; if (data->dvert && data->defgrp_index != -1) { - weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index); + weight = BKE_defvert_find_weight(&data->dvert[vertex_idx], data->defgrp_index); if (data->invert_vgroup) { weight = 1.0f - weight; @@ -1423,7 +1487,8 @@ static void surfacedeformModifier_do(ModifierData *md, /* Avoid converting edit-mesh data, binding is an exception. */ BKE_mesh_wrapper_ensure_mdata(target); - if (!surfacedeformBind(ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { + if (!surfacedeformBind( + ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target, mesh)) { smd->flags &= ~MOD_SDEF_BIND; } /* Early abort, this is binding 'call', no need to perform whole evaluation. */ @@ -1431,8 +1496,9 @@ static void surfacedeformModifier_do(ModifierData *md, } /* Poly count checks */ - if (smd->numverts != numverts) { - BKE_modifier_set_error(ob, md, "Vertices changed from %u to %u", smd->numverts, numverts); + if (smd->num_mesh_verts != numverts) { + BKE_modifier_set_error( + ob, md, "Vertices changed from %u to %u", smd->num_mesh_verts, numverts); return; } if (smd->numpoly != tnumpoly) { @@ -1468,8 +1534,8 @@ static void surfacedeformModifier_do(ModifierData *md, TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (numverts > 10000); - BLI_task_parallel_range(0, numverts, &data, deformVert, &settings); + settings.use_threading = (smd->num_bind_verts > 10000); + BLI_task_parallel_range(0, smd->num_bind_verts, &data, deformVert, &settings); MEM_freeN(data.targetCos); } @@ -1554,6 +1620,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); + col = uiLayoutColumn(layout, false); + uiLayoutSetEnabled(col, !is_bound); + uiLayoutSetActive(col, !is_bound && RNA_string_length(ptr, "vertex_group") != 0); + uiItemR(col, ptr, "use_sparse_bind", 0, NULL, ICON_NONE); + uiItemS(layout); col = uiLayoutColumn(layout, false); @@ -1576,10 +1647,10 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md) { const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md; - BLO_write_struct_array(writer, SDefVert, smd->numverts, smd->verts); + BLO_write_struct_array(writer, SDefVert, smd->num_bind_verts, smd->verts); if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { BLO_write_struct_array(writer, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds); if (smd->verts[i].binds) { @@ -1607,7 +1678,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) BLO_read_data_address(reader, &smd->verts); if (smd->verts) { - for (int i = 0; i < smd->numverts; i++) { + for (int i = 0; i < smd->num_bind_verts; i++) { BLO_read_data_address(reader, &smd->verts[i].binds); if (smd->verts[i].binds) { diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 55409cba114..5b97d0eb259 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -71,7 +71,7 @@ void MOD_init_texture(MappingInfoModifierData *dmd, const ModifierEvalContext *c } } -/* TODO to be renamed to get_texture_coords once we are done with moving modifiers to Mesh. */ +/* TODO: to be renamed to get_texture_coords once we are done with moving modifiers to Mesh. */ /** \param cos: may be NULL, in which case we use directly mesh vertices' coordinates. */ void MOD_get_texture_coords(MappingInfoModifierData *dmd, const ModifierEvalContext *UNUSED(ctx), @@ -254,15 +254,22 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, void MOD_get_vgroup( Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index) { - *defgrp_index = BKE_object_defgroup_name_index(ob, name); - *dvert = NULL; - - if (*defgrp_index != -1) { - if (ob->type == OB_LATTICE) { + if (mesh) { + *defgrp_index = BKE_id_defgroup_name_index(&mesh->id, name); + if (*defgrp_index != -1) { + *dvert = mesh->dvert; + } + else { + *dvert = NULL; + } + } + else { + *defgrp_index = BKE_object_defgroup_name_index(ob, name); + if (*defgrp_index != -1 && ob->type == OB_LATTICE) { *dvert = BKE_lattice_deform_verts_get(ob); } - else if (mesh) { - *dvert = mesh->dvert; + else { + *dvert = NULL; } } } diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 5742144b6dd..3f161d339c2 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -233,7 +233,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * settings.use_threading = (numPolys > 1000); BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings); - /* XXX TODO is this still needed? */ + /* XXX TODO: is this still needed? */ // me_eval->dirty |= DM_DIRTY_TESS_CDLAYERS; mesh->runtime.is_original = false; diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 2f2da7d6554..bbdd7d0e647 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -378,7 +378,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, * But this is not exactly trivial change, better to keep this optimization for later... */ if (!has_vgroup) { - /* Note: in theory, we could avoid this extra allocation & copying... + /* NOTE: in theory, we could avoid this extra allocation & copying... * But think we can live with it for now, * and it makes code simpler & cleaner. */ float(*vert_normals)[3] = MEM_calloc_arrayN( diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index c5e2ecb9660..696c4c855c7 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -230,7 +230,7 @@ void weightvg_do_mask(const ModifierEvalContext *ctx, MEM_freeN(tex_co); } - else if ((ref_didx = BKE_object_defgroup_name_index(ob, defgrp_name)) != -1) { + else if ((ref_didx = BKE_id_defgroup_name_index(&mesh->id, defgrp_name)) != -1) { MDeformVert *dvert = NULL; /* Check whether we want to set vgroup weights from a constant weight factor or a vertex diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index b5f72c88800..093fa118ee0 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -194,12 +194,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) { + if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } /* Get vgroup idx from its name. */ - const int defgrp_index = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); if (defgrp_index == -1) { return mesh; } diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index a71a2f3b480..7aae089fa18 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -245,19 +245,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) { + if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } /* Get vgroup idx from its name. */ - const int defgrp_index = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name_a); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_a); if (defgrp_index == -1) { return mesh; } /* Get second vgroup idx from its name, if given. */ int defgrp_index_other = -1; if (wmd->defgrp_name_b[0] != '\0') { - defgrp_index_other = BKE_object_defgroup_name_index(ctx->object, wmd->defgrp_name_b); + defgrp_index_other = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_b); if (defgrp_index_other == -1) { return mesh; } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index cd03175f16c..6e78774269a 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -174,7 +174,7 @@ static void get_vert2geom_distance(int numVerts, BVHTreeFromMesh treeData_f = {NULL}; if (dist_v) { - /* Create a bvh-tree of the given target's verts. */ + /* Create a BVH-tree of the given target's verts. */ BKE_bvhtree_from_mesh_get(&treeData_v, target, BVHTREE_FROM_VERTS, 2); if (treeData_v.tree == NULL) { OUT_OF_MEMORY(); @@ -182,7 +182,7 @@ static void get_vert2geom_distance(int numVerts, } } if (dist_e) { - /* Create a bvh-tree of the given target's edges. */ + /* Create a BVH-tree of the given target's edges. */ BKE_bvhtree_from_mesh_get(&treeData_e, target, BVHTREE_FROM_EDGES, 2); if (treeData_e.tree == NULL) { OUT_OF_MEMORY(); @@ -190,7 +190,7 @@ static void get_vert2geom_distance(int numVerts, } } if (dist_f) { - /* Create a bvh-tree of the given target's faces. */ + /* Create a BVH-tree of the given target's faces. */ BKE_bvhtree_from_mesh_get(&treeData_f, target, BVHTREE_FROM_LOOPTRI, 2); if (treeData_f.tree == NULL) { OUT_OF_MEMORY(); @@ -468,7 +468,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ - if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) { + if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { return mesh; } @@ -479,11 +479,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } /* Get vgroup idx from its name. */ - defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); + defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); if (defgrp_index == -1) { return mesh; } - const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT); /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ /* As this modifier never add vertices to vgroup, just return. */ diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index 1590f342666..fe2d699aea8 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -1573,11 +1573,12 @@ struct WeldVertexCluster { uint merged_verts; }; -static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *weldModifier_doWeld(WeldModifierData *wmd, + const ModifierEvalContext *UNUSED(ctx), + Mesh *mesh) { Mesh *result = mesh; - Object *ob = ctx->object; BLI_bitmap *v_mask = NULL; int v_mask_act = 0; @@ -1590,7 +1591,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex totvert = mesh->totvert; /* Vertex Group. */ - const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); if (defgrp_index != -1) { MDeformVert *dvert, *dv; dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT); diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 16bf1f7d763..e188a61e975 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -76,7 +76,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh * Mesh *result; BMesh *bm; - const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name); + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); bm = BKE_mesh_to_bmesh_ex(mesh, &(struct BMeshCreateParams){0}, |