diff options
Diffstat (limited to 'source/blender/modifiers/intern')
61 files changed, 331 insertions, 2005 deletions
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 828b8b79664..a86a667974e 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -296,7 +296,6 @@ ModifierTypeInfo modifierType_Armature = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ deformMatricesEM, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 56db68b163c..c2b1478c1b2 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -1037,7 +1037,6 @@ ModifierTypeInfo modifierType_Array = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index add95a0d248..984e85f58ef 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -446,7 +446,6 @@ ModifierTypeInfo modifierType_Bevel = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index bb05ae3e1b3..7b084d608fb 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -641,7 +641,6 @@ ModifierTypeInfo modifierType_Boolean = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ nullptr, /* modifyGeometrySet */ nullptr, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 86f0df1418b..867c1e9b5bb 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -345,7 +345,6 @@ ModifierTypeInfo modifierType_Build = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 715bc26e5d3..defc7df31dc 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -589,7 +589,6 @@ ModifierTypeInfo modifierType_Cast = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 8aff29dc17d..4b8928009fe 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -308,7 +308,6 @@ ModifierTypeInfo modifierType_Cloth = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 02e1f61b824..658a569627b 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -317,7 +317,6 @@ ModifierTypeInfo modifierType_Collision = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 49ff4acb31f..d75c2a13587 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -610,7 +610,7 @@ static void correctivesmooth_modifier_do(ModifierData *md, BLI_assert(csmd->bind_coords != NULL); /* Copy bound data to the original modifier. */ CorrectiveSmoothModifierData *csmd_orig = (CorrectiveSmoothModifierData *) - BKE_modifier_get_original(&csmd->modifier); + BKE_modifier_get_original(ob, &csmd->modifier); csmd_orig->bind_coords = MEM_dupallocN(csmd->bind_coords); csmd_orig->bind_coords_num = csmd->bind_coords_num; } @@ -850,7 +850,6 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 20dbb299767..b01b70000b8 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -234,7 +234,6 @@ ModifierTypeInfo modifierType_Curve = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 34bb93cbbbc..a289b9c918a 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -484,7 +484,6 @@ ModifierTypeInfo modifierType_DataTransfer = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 975f80a04f8..ad5391d2b6c 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -298,7 +298,6 @@ ModifierTypeInfo modifierType_Decimate = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 010292d2ebb..94cdcad3b6a 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -262,9 +262,9 @@ static void displaceModifier_do_task(void *__restrict userdata, } break; case MOD_DISP_DIR_RGB_XYZ: - local_vec[0] = texres.tr - dmd->midlevel; - local_vec[1] = texres.tg - dmd->midlevel; - local_vec[2] = texres.tb - dmd->midlevel; + local_vec[0] = texres.trgba[0] - dmd->midlevel; + local_vec[1] = texres.trgba[1] - dmd->midlevel; + local_vec[2] = texres.trgba[2] - dmd->midlevel; if (use_global_direction) { mul_transposed_mat3_m4_v3(data->local_mat, local_vec); } @@ -508,7 +508,6 @@ ModifierTypeInfo modifierType_Displace = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index a696ce216c7..676433b14b1 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -221,7 +221,6 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 1039bcb2b3b..55707435e52 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -185,7 +185,6 @@ ModifierTypeInfo modifierType_EdgeSplit = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 68d6b4a3626..c788633f978 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -1255,7 +1255,6 @@ ModifierTypeInfo modifierType_Explode = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index a21eb603300..748633b78b3 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -273,7 +273,6 @@ ModifierTypeInfo modifierType_Fluid = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 18ce37c5d85..b4c081906ba 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -572,7 +572,6 @@ ModifierTypeInfo modifierType_Hook = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index 6efeec1970f..090973f12c0 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -887,7 +887,6 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index a36a8c386b4..8cc34d43d82 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -633,7 +633,6 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ init_data, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 29d1ecf6050..709b617d3ec 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -191,7 +191,6 @@ ModifierTypeInfo modifierType_Lattice = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 0de8b26a1b7..097f7241205 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -837,7 +837,6 @@ ModifierTypeInfo modifierType_Mask = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ nullptr, /* modifyGeometrySet */ nullptr, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc index 910b52dea67..a8e1c91dd20 100644 --- a/source/blender/modifiers/intern/MOD_mesh_to_volume.cc +++ b/source/blender/modifiers/intern/MOD_mesh_to_volume.cc @@ -308,7 +308,6 @@ ModifierTypeInfo modifierType_MeshToVolume = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ nullptr, - /* modifyHair */ nullptr, /* modifyGeometrySet */ modifyGeometrySet, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index 74f9887a973..48ff4f7d6af 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -446,7 +446,6 @@ ModifierTypeInfo modifierType_MeshCache = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index cb043643dd9..5c6bcb4ba24 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -390,7 +390,7 @@ static void meshdeformModifier_do(ModifierData *md, } if (!recursive_bind_sentinel) { recursive_bind_sentinel = 1; - mmd->bindfunc(mmd, cagemesh, (float *)vertexCos, numVerts, cagemat); + mmd->bindfunc(ob, mmd, cagemesh, (float *)vertexCos, numVerts, cagemat); recursive_bind_sentinel = 0; } @@ -642,7 +642,6 @@ ModifierTypeInfo modifierType_MeshDeform = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index e1459ccba6d..8bde0cab3dc 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -404,6 +404,10 @@ static void override_layers_panel_draw(const bContext *C, Panel *panel) return; } + if (RNA_pointer_is_null(&fileptr)) { + return; + } + uiLayoutSetPropSep(layout, true); uiTemplateCacheFileLayers(layout, C, &fileptr); } @@ -452,7 +456,6 @@ ModifierTypeInfo modifierType_MeshSequenceCache = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index bbac6589577..721906a6a01 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -120,9 +120,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * result = mirrorModifier__doMirror(mmd, ctx->object, mesh); - if (result != mesh) { - BKE_mesh_normals_tag_dirty(result); - } return result; } @@ -241,7 +238,6 @@ ModifierTypeInfo modifierType_Mirror = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index c3b34f3cd23..205839774d8 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -518,7 +518,6 @@ ModifierTypeInfo modifierType_Multires = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 49528845197..ca4bfbed5f5 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -109,6 +109,8 @@ using blender::float3; using blender::FunctionRef; using blender::IndexRange; using blender::Map; +using blender::MultiValueMap; +using blender::MutableSpan; using blender::Set; using blender::Span; using blender::StringRef; @@ -119,7 +121,9 @@ using blender::fn::Field; using blender::fn::GField; using blender::fn::GMutablePointer; using blender::fn::GPointer; +using blender::fn::GVArray; using blender::fn::ValueOrField; +using blender::fn::ValueOrFieldCPPType; using blender::nodes::FieldInferencingInterface; using blender::nodes::GeoNodeExecParams; using blender::nodes::InputSocketFieldType; @@ -137,56 +141,85 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(nmd, DNA_struct_default_get(NodesModifierData), modifier); } -static void addIdsUsedBySocket(const ListBase *sockets, Set<ID *> &ids) +static void add_used_ids_from_sockets(const ListBase &sockets, Set<ID *> &ids) { - LISTBASE_FOREACH (const bNodeSocket *, socket, sockets) { - if (socket->type == SOCK_OBJECT) { - Object *object = ((bNodeSocketValueObject *)socket->default_value)->value; - if (object != nullptr) { - ids.add(&object->id); + LISTBASE_FOREACH (const bNodeSocket *, socket, &sockets) { + switch (socket->type) { + case SOCK_OBJECT: { + if (Object *object = ((bNodeSocketValueObject *)socket->default_value)->value) { + ids.add(&object->id); + } + break; } - } - else if (socket->type == SOCK_COLLECTION) { - Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value; - if (collection != nullptr) { - ids.add(&collection->id); + case SOCK_COLLECTION: { + if (Collection *collection = + ((bNodeSocketValueCollection *)socket->default_value)->value) { + ids.add(&collection->id); + } + break; } - } - else if (socket->type == SOCK_MATERIAL) { - Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value; - if (material != nullptr) { - ids.add(&material->id); + case SOCK_MATERIAL: { + if (Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value) { + ids.add(&material->id); + } + break; } - } - else if (socket->type == SOCK_TEXTURE) { - Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value; - if (texture != nullptr) { - ids.add(&texture->id); + case SOCK_TEXTURE: { + if (Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value) { + ids.add(&texture->id); + } + break; } - } - else if (socket->type == SOCK_IMAGE) { - Image *image = ((bNodeSocketValueImage *)socket->default_value)->value; - if (image != nullptr) { - ids.add(&image->id); + case SOCK_IMAGE: { + if (Image *image = ((bNodeSocketValueImage *)socket->default_value)->value) { + ids.add(&image->id); + } + break; } } } } -static void find_used_ids_from_nodes(const bNodeTree &tree, Set<ID *> &ids) +/** + * \note We can only check properties here that cause the dependency graph to update relations when + * they are changed, otherwise there may be a missing relation after editing. So this could check + * more properties like whether the node is muted, but we would have to accept the cost of updating + * relations when those properties are changed. + */ +static bool node_needs_own_transform_relation(const bNode &node) +{ + if (node.type == GEO_NODE_COLLECTION_INFO) { + const NodeGeometryCollectionInfo &storage = *static_cast<const NodeGeometryCollectionInfo *>( + node.storage); + return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE; + } + + if (node.type == GEO_NODE_OBJECT_INFO) { + const NodeGeometryObjectInfo &storage = *static_cast<const NodeGeometryObjectInfo *>( + node.storage); + return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE; + } + + return false; +} + +static void process_nodes_for_depsgraph(const bNodeTree &tree, + Set<ID *> &ids, + bool &needs_own_transform_relation) { Set<const bNodeTree *> handled_groups; LISTBASE_FOREACH (const bNode *, node, &tree.nodes) { - addIdsUsedBySocket(&node->inputs, ids); - addIdsUsedBySocket(&node->outputs, ids); + add_used_ids_from_sockets(node->inputs, ids); + add_used_ids_from_sockets(node->outputs, ids); if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) { const bNodeTree *group = (bNodeTree *)node->id; if (group != nullptr && handled_groups.add(group)) { - find_used_ids_from_nodes(*group, ids); + process_nodes_for_depsgraph(*group, ids, needs_own_transform_relation); } } + needs_own_transform_relation |= node_needs_own_transform_relation(*node); } } @@ -236,37 +269,43 @@ static void add_object_relation(const ModifierUpdateDepsgraphContext *ctx, Objec static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) { NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md); - DEG_add_modifier_to_transform_relation(ctx->node, "Nodes Modifier"); - if (nmd->node_group != nullptr) { - DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier"); - - Set<ID *> used_ids; - find_used_ids_from_settings(nmd->settings, used_ids); - find_used_ids_from_nodes(*nmd->node_group, used_ids); - for (ID *id : used_ids) { - switch ((ID_Type)GS(id->name)) { - case ID_OB: { - Object *object = reinterpret_cast<Object *>(id); - add_object_relation(ctx, *object); - break; - } - case ID_GR: { - Collection *collection = reinterpret_cast<Collection *>(id); - add_collection_relation(ctx, *collection); - break; - } - case ID_IM: - case ID_TE: { - DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier"); - } - default: { - /* Purposefully don't add relations for materials. While there are material sockets, - * the pointers are only passed around as handles rather than dereferenced. */ - break; - } + if (nmd->node_group == nullptr) { + return; + } + + DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier"); + + bool needs_own_transform_relation = false; + Set<ID *> used_ids; + find_used_ids_from_settings(nmd->settings, used_ids); + process_nodes_for_depsgraph(*nmd->node_group, used_ids, needs_own_transform_relation); + for (ID *id : used_ids) { + switch ((ID_Type)GS(id->name)) { + case ID_OB: { + Object *object = reinterpret_cast<Object *>(id); + add_object_relation(ctx, *object); + break; + } + case ID_GR: { + Collection *collection = reinterpret_cast<Collection *>(id); + add_collection_relation(ctx, *collection); + break; + } + case ID_IM: + case ID_TE: { + DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier"); + } + default: { + /* Purposefully don't add relations for materials. While there are material sockets, + * the pointers are only passed around as handles rather than dereferenced. */ + break; } } } + + if (needs_own_transform_relation) { + DEG_add_modifier_to_transform_relation(ctx->node, "Nodes Modifier"); + } } static bool check_tree_for_time_node(const bNodeTree &tree, @@ -892,80 +931,142 @@ static void clear_runtime_data(NodesModifierData *nmd) } } -static void store_field_on_geometry_component(GeometryComponent &component, - const StringRef attribute_name, - AttributeDomain domain, - const GField &field) +struct OutputAttributeInfo { + GField field; + StringRefNull name; +}; + +struct OutputAttributeToStore { + GeometryComponentType component_type; + AttributeDomain domain; + StringRefNull name; + GMutableSpan data; +}; + +/** + * The output attributes are organized based on their domain, because attributes on the same domain + * can be evaluated together. + */ +static MultiValueMap<AttributeDomain, OutputAttributeInfo> find_output_attributes_to_store( + const NodesModifierData &nmd, const NodeRef &output_node, Span<GMutablePointer> output_values) { - /* If the attribute name corresponds to a built-in attribute, use the domain of the built-in - * attribute instead. */ - if (component.attribute_is_builtin(attribute_name)) { - component.attribute_try_create_builtin(attribute_name, AttributeInitDefault()); - std::optional<AttributeMetaData> meta_data = component.attribute_get_meta_data(attribute_name); - if (meta_data.has_value()) { - domain = meta_data->domain; + MultiValueMap<AttributeDomain, OutputAttributeInfo> outputs_by_domain; + for (const InputSocketRef *socket : output_node.inputs().drop_front(1).drop_back(1)) { + if (!socket_type_has_attribute_toggle(*socket->bsocket())) { + continue; } - else { - return; + + const std::string prop_name = socket->identifier() + attribute_name_suffix; + const IDProperty *prop = IDP_GetPropertyFromGroup(nmd.settings.properties, prop_name.c_str()); + if (prop == nullptr) { + continue; } + const StringRefNull attribute_name = IDP_String(prop); + if (attribute_name.is_empty()) { + continue; + } + + const int index = socket->index(); + const GPointer value = output_values[index]; + const ValueOrFieldCPPType *cpp_type = dynamic_cast<const ValueOrFieldCPPType *>(value.type()); + BLI_assert(cpp_type != nullptr); + const GField field = cpp_type->as_field(value.get()); + + const bNodeSocket *interface_socket = (const bNodeSocket *)BLI_findlink( + &nmd.node_group->outputs, socket->index()); + const AttributeDomain domain = (AttributeDomain)interface_socket->attribute_domain; + OutputAttributeInfo output_info; + output_info.field = std::move(field); + output_info.name = attribute_name; + outputs_by_domain.add(domain, std::move(output_info)); } - const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(field.cpp_type()); - OutputAttribute attribute = component.attribute_try_get_for_output_only( - attribute_name, domain, data_type); - if (attribute) { - /* In the future we could also evaluate all output fields at once. */ - const int domain_size = component.attribute_domain_size(domain); - blender::bke::GeometryComponentFieldContext field_context{component, domain}; - blender::fn::FieldEvaluator field_evaluator{field_context, domain_size}; - field_evaluator.add_with_destination(field, attribute.varray()); - field_evaluator.evaluate(); - attribute.save(); - } + return outputs_by_domain; } -static void store_output_value_in_geometry(GeometrySet &geometry_set, - NodesModifierData *nmd, - const InputSocketRef &socket, - const GPointer value) +/** + * The computed values are stored in newly allocated arrays. They still have to be moved to the + * actual geometry. + */ +static Vector<OutputAttributeToStore> compute_attributes_to_store( + const GeometrySet &geometry, + const MultiValueMap<AttributeDomain, OutputAttributeInfo> &outputs_by_domain) { - if (!socket_type_has_attribute_toggle(*socket.bsocket())) { - return; - } - const std::string prop_name = socket.identifier() + attribute_name_suffix; - const IDProperty *prop = IDP_GetPropertyFromGroup(nmd->settings.properties, prop_name.c_str()); - if (prop == nullptr) { - return; - } - const StringRefNull attribute_name = IDP_String(prop); - if (attribute_name.is_empty()) { - return; + Vector<OutputAttributeToStore> attributes_to_store; + for (const GeometryComponentType component_type : {GEO_COMPONENT_TYPE_MESH, + GEO_COMPONENT_TYPE_POINT_CLOUD, + GEO_COMPONENT_TYPE_CURVE, + GEO_COMPONENT_TYPE_INSTANCES}) { + if (!geometry.has(component_type)) { + continue; + } + const GeometryComponent &component = *geometry.get_component_for_read(component_type); + for (const auto item : outputs_by_domain.items()) { + const AttributeDomain domain = item.key; + const Span<OutputAttributeInfo> outputs_info = item.value; + if (!component.attribute_domain_supported(domain)) { + continue; + } + const int domain_size = component.attribute_domain_size(domain); + blender::bke::GeometryComponentFieldContext field_context{component, domain}; + blender::fn::FieldEvaluator field_evaluator{field_context, domain_size}; + for (const OutputAttributeInfo &output_info : outputs_info) { + const CPPType &type = output_info.field.cpp_type(); + OutputAttributeToStore store{ + component_type, + domain, + output_info.name, + GMutableSpan{ + type, MEM_malloc_arrayN(domain_size, type.size(), __func__), domain_size}}; + field_evaluator.add_with_destination(output_info.field, store.data); + attributes_to_store.append(store); + } + field_evaluator.evaluate(); + } } - const blender::fn::ValueOrFieldCPPType *cpp_type = - dynamic_cast<const blender::fn::ValueOrFieldCPPType *>(value.type()); - BLI_assert(cpp_type != nullptr); + return attributes_to_store; +} - const GField field = cpp_type->as_field(value.get()); - const bNodeSocket *interface_socket = (bNodeSocket *)BLI_findlink(&nmd->node_group->outputs, - socket.index()); - const AttributeDomain domain = (AttributeDomain)interface_socket->attribute_domain; - if (geometry_set.has_mesh()) { - MeshComponent &component = geometry_set.get_component_for_write<MeshComponent>(); - store_field_on_geometry_component(component, attribute_name, domain, field); - } - if (geometry_set.has_pointcloud()) { - PointCloudComponent &component = geometry_set.get_component_for_write<PointCloudComponent>(); - store_field_on_geometry_component(component, attribute_name, domain, field); - } - if (geometry_set.has_curve()) { - CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>(); - store_field_on_geometry_component(component, attribute_name, domain, field); - } - if (geometry_set.has_instances()) { - InstancesComponent &component = geometry_set.get_component_for_write<InstancesComponent>(); - store_field_on_geometry_component(component, attribute_name, domain, field); +static void store_computed_output_attributes( + GeometrySet &geometry, const Span<OutputAttributeToStore> attributes_to_store) +{ + for (const OutputAttributeToStore &store : attributes_to_store) { + GeometryComponent &component = geometry.get_component_for_write(store.component_type); + if (component.attribute_exists(store.name)) { + /* Copy the data into an existing attribute. */ + blender::bke::WriteAttributeLookup write_attribute = component.attribute_try_get_for_write( + store.name); + if (write_attribute) { + write_attribute.varray.set_all(store.data.data()); + if (write_attribute.tag_modified_fn) { + write_attribute.tag_modified_fn(); + } + } + store.data.type().destruct_n(store.data.data(), store.data.size()); + MEM_freeN(store.data.data()); + } + else { + component.attribute_try_create(store.name, + store.domain, + blender::bke::cpp_type_to_custom_data_type(store.data.type()), + AttributeInitMove(store.data.data())); + } } } +static void store_output_attributes(GeometrySet &geometry, + const NodesModifierData &nmd, + const NodeRef &output_node, + Span<GMutablePointer> output_values) +{ + /* All new attribute values have to be computed before the geometry is actually changed. This is + * necessary because some fields might depend on attributes that are overwritten. */ + MultiValueMap<AttributeDomain, OutputAttributeInfo> outputs_by_domain = + find_output_attributes_to_store(nmd, output_node, output_values); + Vector<OutputAttributeToStore> attributes_to_store = compute_attributes_to_store( + geometry, outputs_by_domain); + store_computed_output_attributes(geometry, attributes_to_store); +} + /** * Evaluate a node group to compute the output geometry. */ @@ -1040,19 +1141,20 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree, eval_params.geo_logger = geo_logger.has_value() ? &*geo_logger : nullptr; blender::modifiers::geometry_nodes::evaluate_geometry_nodes(eval_params); - GeometrySet output_geometry_set = eval_params.r_output_values[0].relocate_out<GeometrySet>(); + GeometrySet output_geometry_set = std::move(*eval_params.r_output_values[0].get<GeometrySet>()); if (geo_logger.has_value()) { geo_logger->log_output_geometry(output_geometry_set); - NodesModifierData *nmd_orig = (NodesModifierData *)BKE_modifier_get_original(&nmd->modifier); + NodesModifierData *nmd_orig = (NodesModifierData *)BKE_modifier_get_original(ctx->object, + &nmd->modifier); clear_runtime_data(nmd_orig); nmd_orig->runtime_eval_log = new geo_log::ModifierLog(*geo_logger); } - for (const InputSocketRef *socket : output_node.inputs().drop_front(1).drop_back(1)) { - GMutablePointer socket_value = eval_params.r_output_values[socket->index()]; - store_output_value_in_geometry(output_geometry_set, nmd, *socket, socket_value); - socket_value.destruct(); + store_output_attributes(output_geometry_set, *nmd, output_node, eval_params.r_output_values); + + for (GMutablePointer value : eval_params.r_output_values) { + value.destruct(); } return output_geometry_set; @@ -1616,7 +1718,6 @@ ModifierTypeInfo modifierType_Nodes = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ nullptr, /* modifyGeometrySet */ modifyGeometrySet, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 5362d86a87f..f59af9074ce 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -1347,7 +1347,7 @@ class GeometryNodesEvaluator { } input_state.usage = ValueUsage::Unused; - /* If the input is unused, it's value can be destructed now. */ + /* If the input is unused, its value can be destructed now. */ this->destruct_input_value_if_exists(locked_node, socket); if (input_state.was_ready_for_execution) { diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index a01f63be791..cce3434f6e3 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -58,7 +58,6 @@ ModifierTypeInfo modifierType_None = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 61099fedf46..8b58b575d24 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -336,8 +336,6 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, if (do_polynors_fix && polygons_check_flip( mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) { - /* XXX TODO: is this still needed? */ - // mesh->dirty |= DM_DIRTY_TESS_CDLAYERS; /* We need to recompute vertex normals! */ BKE_mesh_normals_tag_dirty(mesh); } @@ -788,7 +786,6 @@ ModifierTypeInfo modifierType_NormalEdit = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index d821caf25a7..0c00f807df3 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -741,7 +741,6 @@ ModifierTypeInfo modifierType_Ocean = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 4fffa7c93f3..67a492d4154 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -677,7 +677,6 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 2a4cc1c2747..6fb60fffcf4 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -334,7 +334,6 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 937a73fddd9..67f83b17f3f 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -299,7 +299,6 @@ ModifierTypeInfo modifierType_Remesh = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index f5db3bced7a..33c62197dbd 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -27,6 +27,7 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLT_translation.h" @@ -134,6 +135,8 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result, const float axis_offset[3], const float merge_threshold) { + BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__); + const float merge_threshold_sq = square_f(merge_threshold); const bool use_offset = axis_offset != NULL; uint tot_doubles = 0; @@ -150,13 +153,10 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result, } const float dist_sq = len_squared_v3v3(axis_co, mvert_new[i].co); if (dist_sq <= merge_threshold_sq) { - mvert_new[i].flag |= ME_VERT_TMP_TAG; + BLI_BITMAP_ENABLE(vert_tag, i); tot_doubles += 1; copy_v3_v3(mvert_new[i].co, axis_co); } - else { - mvert_new[i].flag &= ~ME_VERT_TMP_TAG & 0xFF; - } } if (tot_doubles != 0) { @@ -166,7 +166,7 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result, uint tot_doubles_left = tot_doubles; for (uint i = 0; i < totvert; i += 1) { - if (mvert_new[i].flag & ME_VERT_TMP_TAG) { + if (BLI_BITMAP_TEST(vert_tag, i)) { int *doubles_map = &full_doubles_map[totvert + i]; for (uint step = 1; step < step_tot; step += 1) { *doubles_map = (int)i; @@ -184,6 +184,9 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result, MESH_MERGE_VERTS_DUMP_IF_MAPPED); MEM_freeN(full_doubles_map); } + + MEM_freeN(vert_tag); + return result; } @@ -439,6 +442,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * mv_new = mvert_new; mv_orig = mvert_orig; + BLI_bitmap *vert_tag = BLI_BITMAP_NEW(totvert, __func__); + /* Copy the first set of edges */ med_orig = medge_orig; med_new = medge_new; @@ -447,10 +452,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * med_new->v2 = med_orig->v2; med_new->crease = med_orig->crease; med_new->flag = med_orig->flag & ~ME_LOOSEEDGE; - /* Tag mvert as not loose. - * NOTE: ME_VERT_TMP_TAG is given to be cleared by BKE_mesh_new_nomain_from_template. */ - mvert_new[med_orig->v1].flag |= ME_VERT_TMP_TAG; - mvert_new[med_orig->v2].flag |= ME_VERT_TMP_TAG; + + /* Tag mvert as not loose. */ + BLI_BITMAP_ENABLE(vert_tag, med_orig->v1); + BLI_BITMAP_ENABLE(vert_tag, med_orig->v1); } /* build polygon -> edge map */ @@ -910,7 +915,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * med_new->v1 = varray_stride + j; med_new->v2 = med_new->v1 - totvert; med_new->flag = ME_EDGEDRAW | ME_EDGERENDER; - if ((mv_new_base->flag & ME_VERT_TMP_TAG) == 0) { + if (!BLI_BITMAP_TEST(vert_tag, j)) { med_new->flag |= ME_LOOSEEDGE; } med_new++; @@ -931,7 +936,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * med_new->v1 = i; med_new->v2 = varray_stride + i; med_new->flag = ME_EDGEDRAW | ME_EDGERENDER; - if ((mvert_new[i].flag & ME_VERT_TMP_TAG) == 0) { + if (!BLI_BITMAP_TEST(vert_tag, i)) { med_new->flag |= ME_LOOSEEDGE; } med_new++; @@ -1119,6 +1124,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } #endif + MEM_freeN(vert_tag); + if (edge_poly_map) { MEM_freeN(edge_poly_map); } @@ -1257,7 +1264,6 @@ ModifierTypeInfo modifierType_Screw = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index b517bc102f8..8c5299a965d 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -139,7 +139,6 @@ ModifierTypeInfo modifierType_ShapeKey = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ deformMatricesEM, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index a12724ec23c..4d10df91331 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -291,7 +291,6 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 39ebc415021..25c3acb0c4f 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -596,7 +596,6 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 07ce819e91c..d1cb120132d 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -2101,7 +2101,6 @@ ModifierTypeInfo modifierType_Skin = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 97027e2ecff..3228a72d958 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -284,7 +284,6 @@ ModifierTypeInfo modifierType_Smooth = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index 46e960e10d4..f0178a817dc 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -120,7 +120,6 @@ ModifierTypeInfo modifierType_Softbody = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 736dd08a713..09933fef7ff 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -274,7 +274,6 @@ ModifierTypeInfo modifierType_Solidify = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index b77f6b7e3e2..65ad298cff1 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -245,9 +245,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if ((ctx->flag & MOD_APPLY_TO_BASE_MESH) == 0) { Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); const bool is_render_mode = (ctx->flag & MOD_APPLY_RENDER) != 0; - /* Same check as in `DRW_mesh_batch_cache_create_requested` to keep both code coherent. */ - const bool is_editmode = (mesh->edit_mesh != NULL) && - (mesh->edit_mesh->mesh_eval_final != NULL); + /* Same check as in `DRW_mesh_batch_cache_create_requested` to keep both code coherent. The + * difference is that here we do not check for the final edit mesh pointer as it is not yet + * assigned at this stage of modifier stack evaluation. */ + const bool is_editmode = (mesh->edit_mesh != NULL); const int required_mode = BKE_subsurf_modifier_eval_required_mode(is_render_mode, is_editmode); if (BKE_subsurf_modifier_can_do_gpu_subdiv_ex(scene, ctx->object, smd, required_mode, false)) { subdiv_cache_cpu_evaluation_settings(ctx, mesh, smd); @@ -499,7 +500,6 @@ ModifierTypeInfo modifierType_Subsurf = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index c8be2bd2829..a54af766b2f 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -245,7 +245,6 @@ ModifierTypeInfo modifierType_Surface = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index ec6de8f8387..70a05002a4f 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1454,7 +1454,7 @@ static void surfacedeformModifier_do(ModifierData *md, BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph"); return; } - ModifierData *md_orig = BKE_modifier_get_original(md); + ModifierData *md_orig = BKE_modifier_get_original(ob, md); freeData(md_orig); } return; @@ -1478,7 +1478,7 @@ static void surfacedeformModifier_do(ModifierData *md, } SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)BKE_modifier_get_original( - md); + ob, md); float tmp_mat[4][4]; invert_m4_m4(tmp_mat, ob->obmat); @@ -1715,7 +1715,6 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index b713df05b80..d4fcebb3216 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -170,7 +170,6 @@ ModifierTypeInfo modifierType_Triangulate = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 238952fde00..5721834c032 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -383,7 +383,6 @@ ModifierTypeInfo modifierType_UVProject = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 3f161d339c2..552cf1d5d3b 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -233,9 +233,6 @@ 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? */ - // me_eval->dirty |= DM_DIRTY_TESS_CDLAYERS; - mesh->runtime.is_original = false; return mesh; @@ -340,7 +337,6 @@ ModifierTypeInfo modifierType_UVWarp = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index a1ca29f454c..2b9ee97ea09 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -183,7 +183,7 @@ template<typename GridType> struct DisplaceOp { TexResult texture_result = {0}; BKE_texture_get_value( nullptr, this->texture, const_cast<float *>(pos.asV()), &texture_result, false); - return {texture_result.tr, texture_result.tg, texture_result.tb}; + return {texture_result.trgba[0], texture_result.trgba[1], texture_result.trgba[2]}; } }; @@ -339,7 +339,6 @@ ModifierTypeInfo modifierType_VolumeDisplace = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ nullptr, - /* modifyHair */ nullptr, /* modifyGeometrySet */ modifyGeometrySet, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc index 72358844838..9557abf0a8a 100644 --- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -221,7 +221,6 @@ ModifierTypeInfo modifierType_VolumeToMesh = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ nullptr, /* modifyGeometrySet */ nullptr, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 25e33b22bde..777ae4d9b10 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -539,7 +539,6 @@ ModifierTypeInfo modifierType_Warp = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index b7ab5dac388..5a56ec1d9e5 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -494,7 +494,6 @@ ModifierTypeInfo modifierType_Wave = { /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* modifyMesh */ NULL, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index bfe389eb080..21e6ed46908 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -757,7 +757,6 @@ ModifierTypeInfo modifierType_WeightedNormal = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index cd9e5162527..eedaea9d403 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -186,28 +186,32 @@ void weightvg_do_mask(const ModifierEvalContext *ctx, org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); break; case MOD_WVG_MASK_TEX_USE_RED: - org_w[i] = (new_w[i] * texres.tr * fact) + (org_w[i] * (1.0f - (texres.tr * fact))); + org_w[i] = (new_w[i] * texres.trgba[0] * fact) + + (org_w[i] * (1.0f - (texres.trgba[0] * fact))); break; case MOD_WVG_MASK_TEX_USE_GREEN: - org_w[i] = (new_w[i] * texres.tg * fact) + (org_w[i] * (1.0f - (texres.tg * fact))); + org_w[i] = (new_w[i] * texres.trgba[1] * fact) + + (org_w[i] * (1.0f - (texres.trgba[1] * fact))); break; case MOD_WVG_MASK_TEX_USE_BLUE: - org_w[i] = (new_w[i] * texres.tb * fact) + (org_w[i] * (1.0f - (texres.tb * fact))); + org_w[i] = (new_w[i] * texres.trgba[2] * fact) + + (org_w[i] * (1.0f - (texres.trgba[2] * fact))); break; case MOD_WVG_MASK_TEX_USE_HUE: - rgb_to_hsv_v(&texres.tr, hsv); + rgb_to_hsv_v(texres.trgba, hsv); org_w[i] = (new_w[i] * hsv[0] * fact) + (org_w[i] * (1.0f - (hsv[0] * fact))); break; case MOD_WVG_MASK_TEX_USE_SAT: - rgb_to_hsv_v(&texres.tr, hsv); + rgb_to_hsv_v(texres.trgba, hsv); org_w[i] = (new_w[i] * hsv[1] * fact) + (org_w[i] * (1.0f - (hsv[1] * fact))); break; case MOD_WVG_MASK_TEX_USE_VAL: - rgb_to_hsv_v(&texres.tr, hsv); + rgb_to_hsv_v(texres.trgba, hsv); org_w[i] = (new_w[i] * hsv[2] * fact) + (org_w[i] * (1.0f - (hsv[2] * fact))); break; case MOD_WVG_MASK_TEX_USE_ALPHA: - org_w[i] = (new_w[i] * texres.ta * fact) + (org_w[i] * (1.0f - (texres.ta * fact))); + org_w[i] = (new_w[i] * texres.trgba[3] * fact) + + (org_w[i] * (1.0f - (texres.trgba[3] * fact))); break; default: org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin * fact))); diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index a9d01c64ff1..6e4f8be8c50 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -428,7 +428,6 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index b369b82ebb7..1b2608afa12 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -514,7 +514,6 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 7ee19e1c537..27242b32432 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -767,7 +767,6 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_weld.cc b/source/blender/modifiers/intern/MOD_weld.cc index 2d4710ca71a..e9d98429ff2 100644 --- a/source/blender/modifiers/intern/MOD_weld.cc +++ b/source/blender/modifiers/intern/MOD_weld.cc @@ -27,21 +27,12 @@ * - Review weight and vertex color interpolation.; */ -//#define USE_WELD_DEBUG -//#define USE_WELD_NORMALS -//#define USE_BVHTREEKDOP - -#include <algorithm> - #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLI_array.hh" -#include "BLI_bitmap.h" #include "BLI_index_range.hh" -#include "BLI_kdtree.h" -#include "BLI_math.h" #include "BLI_span.hh" #include "BLI_vector.hh" @@ -51,7 +42,6 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" -#include "DNA_object_types.h" #include "DNA_screen_types.h" #ifdef USE_BVHTREEKDOP @@ -60,7 +50,6 @@ #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_screen.h" @@ -74,1808 +63,94 @@ #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" +#include "GEO_mesh_merge_by_distance.hh" + using blender::Array; -using blender::IndexRange; -using blender::MutableSpan; +using blender::IndexMask; using blender::Span; using blender::Vector; -/* Indicates when the element was not computed. */ -#define OUT_OF_CONTEXT (int)(-1) -/* Indicates if the edge or face will be collapsed. */ -#define ELEM_COLLAPSED (int)(-2) -/* indicates whether an edge or vertex in groups_map will be merged. */ -#define ELEM_MERGED (int)(-2) - -/* Used to indicate a range in an array specifying a group. */ -struct WeldGroup { - int len; - int ofs; -}; - -/* Edge groups that will be merged. Final vertices are also indicated. */ -struct WeldGroupEdge { - struct WeldGroup group; - int v1; - int v2; -}; - -struct WeldVert { - /* Indexes relative to the original Mesh. */ - int vert_dest; - int vert_orig; -}; - -struct WeldEdge { - union { - int flag; - struct { - /* Indexes relative to the original Mesh. */ - int edge_dest; - int edge_orig; - int vert_a; - int vert_b; - }; - }; -}; - -struct WeldLoop { - union { - int flag; - struct { - /* Indexes relative to the original Mesh. */ - int vert; - int edge; - int loop_orig; - int loop_skip_to; - }; - }; -}; - -struct WeldPoly { - union { - int flag; - struct { - /* Indexes relative to the original Mesh. */ - int poly_dst; - int poly_orig; - int loop_start; - int loop_end; - /* Final Polygon Size. */ - int len; - /* Group of loops that will be affected. */ - struct WeldGroup loops; - }; - }; -}; - -struct WeldMesh { - /* Group of vertices to be merged. */ - Array<WeldGroup> vert_groups; - Array<int> vert_groups_buffer; - - /* Group of edges to be merged. */ - Array<WeldGroupEdge> edge_groups; - Array<int> edge_groups_buffer; - /* From the original index of the vertex, this indicates which group it is or is going to be - * merged. */ - Array<int> edge_groups_map; - - /* References all polygons and loops that will be affected. */ - Vector<WeldLoop> wloop; - Vector<WeldPoly> wpoly; - WeldPoly *wpoly_new; - int wloop_len; - int wpoly_len; - int wpoly_new_len; - - /* From the actual index of the element in the mesh, it indicates what is the index of the Weld - * element above. */ - Array<int> loop_map; - Array<int> poly_map; - - int vert_kill_len; - int edge_kill_len; - int loop_kill_len; - int poly_kill_len; /* Including the new polygons. */ - - /* Size of the affected polygon with more sides. */ - int max_poly_len; -}; - -struct WeldLoopOfPolyIter { - int loop_start; - int loop_end; - Span<WeldLoop> wloop; - Span<MLoop> mloop; - Span<int> loop_map; - /* Weld group. */ - int *group; - - int l_curr; - int l_next; - - /* Return */ - int group_len; - int v; - int e; - char type; -}; - -/* -------------------------------------------------------------------- */ -/** \name Debug Utils - * \{ */ - -#ifdef USE_WELD_DEBUG -static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter *iter, - const WeldPoly &wp, - Span<WeldLoop> wloop, - Span<MLoop> mloop, - Span<int> loop_map, - int *group_buffer); - -static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter *iter); - -static void weld_assert_edge_kill_len(Span<WeldEdge> wedge, const int supposed_kill_len) -{ - int kills = 0; - const WeldEdge *we = &wedge[0]; - for (int i = wedge.size(); i--; we++) { - int edge_dest = we->edge_dest; - /* Magically includes collapsed edges. */ - if (edge_dest != OUT_OF_CONTEXT) { - kills++; - } - } - BLI_assert(kills == supposed_kill_len); -} - -static void weld_assert_poly_and_loop_kill_len(Span<WeldPoly> wpoly, - Span<WeldPoly> wpoly_new, - Span<WeldLoop> wloop, - Span<MLoop> mloop, - Span<int> loop_map, - Span<int> poly_map, - Span<MPoly> mpoly, - const int supposed_poly_kill_len, - const int supposed_loop_kill_len) -{ - int poly_kills = 0; - int loop_kills = mloop.size(); - const MPoly *mp = &mpoly[0]; - for (int i = 0; i < mpoly.size(); i++, mp++) { - int poly_ctx = poly_map[i]; - if (poly_ctx != OUT_OF_CONTEXT) { - const WeldPoly *wp = &wpoly[poly_ctx]; - WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin(&iter, *wp, wloop, mloop, loop_map, nullptr)) { - poly_kills++; - continue; - } - else { - if (wp->poly_dst != OUT_OF_CONTEXT) { - poly_kills++; - continue; - } - int remain = wp->len; - int l = wp->loop_start; - while (remain) { - int l_next = l + 1; - int loop_ctx = loop_map[l]; - if (loop_ctx != OUT_OF_CONTEXT) { - const WeldLoop *wl = &wloop[loop_ctx]; - if (wl->loop_skip_to != OUT_OF_CONTEXT) { - l_next = wl->loop_skip_to; - } - if (wl->flag != ELEM_COLLAPSED) { - loop_kills--; - remain--; - } - } - else { - loop_kills--; - remain--; - } - l = l_next; - } - } - } - else { - loop_kills -= mp->totloop; - } - } - - const WeldPoly *wp = wpoly_new.data(); - for (int i = wpoly_new.size(); i--; wp++) { - if (wp->poly_dst != OUT_OF_CONTEXT) { - poly_kills++; - continue; - } - int remain = wp->len; - int l = wp->loop_start; - while (remain) { - int l_next = l + 1; - int loop_ctx = loop_map[l]; - if (loop_ctx != OUT_OF_CONTEXT) { - const WeldLoop *wl = &wloop[loop_ctx]; - if (wl->loop_skip_to != OUT_OF_CONTEXT) { - l_next = wl->loop_skip_to; - } - if (wl->flag != ELEM_COLLAPSED) { - loop_kills--; - remain--; - } - } - else { - loop_kills--; - remain--; - } - l = l_next; - } - } - - BLI_assert(poly_kills == supposed_poly_kill_len); - BLI_assert(loop_kills == supposed_loop_kill_len); -} - -static void weld_assert_poly_no_vert_repetition(const WeldPoly &wp, - Span<WeldLoop> wloop, - Span<MLoop> mloop, - Span<int> loop_map) -{ - const int len = wp.len; - Array<int, 64> verts(len); - WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, nullptr)) { - return; - } - else { - int i = 0; - while (weld_iter_loop_of_poly_next(iter)) { - verts[i++] = iter.v; - } - } - for (int i = 0; i < len; i++) { - int va = verts[i]; - for (int j = i + 1; j < len; j++) { - int vb = verts[j]; - BLI_assert(va != vb); - } - } -} - -static void weld_assert_poly_len(const WeldPoly *wp, const Span<WeldLoop> wloop) -{ - if (wp->flag == ELEM_COLLAPSED) { - return; - } - - int len = wp->len; - const WeldLoop *wl = &wloop[wp->loops.ofs]; - BLI_assert(wp->loop_start <= wl->loop_orig); - - int end_wloop = wp->loops.ofs + wp->loops.len; - const WeldLoop *wl_end = &wloop[end_wloop - 1]; - - int min_len = 0; - for (; wl <= wl_end; wl++) { - BLI_assert(wl->loop_skip_to == OUT_OF_CONTEXT); /* Not for this case. */ - if (wl->flag != ELEM_COLLAPSED) { - min_len++; - } - } - BLI_assert(len >= min_len); - - int max_len = wp->loop_end - wp->loop_start + 1; - BLI_assert(len <= max_len); -} - -#endif /* USE_WELD_DEBUG */ - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Weld Vert API - * \{ */ - -static Vector<WeldVert> weld_vert_ctx_alloc_and_setup(Span<int> vert_dest_map, - const int vert_kill_len) -{ - Vector<WeldVert> wvert; - wvert.reserve(std::min<int>(2 * vert_kill_len, vert_dest_map.size())); - - for (const int i : vert_dest_map.index_range()) { - if (vert_dest_map[i] != OUT_OF_CONTEXT) { - WeldVert wv{}; - wv.vert_dest = vert_dest_map[i]; - wv.vert_orig = i; - wvert.append(wv); - } - } - return wvert; -} - -static void weld_vert_groups_setup(Span<WeldVert> wvert, - Span<int> vert_dest_map, - MutableSpan<int> r_vert_groups_map, - Array<int> &r_vert_groups_buffer, - Array<WeldGroup> &r_vert_groups) -{ - /* Get weld vert groups. */ - - int wgroups_len = 0; - for (const int i : vert_dest_map.index_range()) { - const int vert_dest = vert_dest_map[i]; - if (vert_dest != OUT_OF_CONTEXT) { - if (vert_dest != i) { - r_vert_groups_map[i] = ELEM_MERGED; - } - else { - r_vert_groups_map[i] = wgroups_len; - wgroups_len++; - } - } - else { - r_vert_groups_map[i] = OUT_OF_CONTEXT; - } - } - - r_vert_groups.reinitialize(wgroups_len); - r_vert_groups.fill({0, 0}); - MutableSpan<WeldGroup> wgroups = r_vert_groups; - - for (const WeldVert &wv : wvert) { - int group_index = r_vert_groups_map[wv.vert_dest]; - wgroups[group_index].len++; - } - - int ofs = 0; - for (WeldGroup &wg : wgroups) { - wg.ofs = ofs; - ofs += wg.len; - } - - BLI_assert(ofs == wvert.size()); - - r_vert_groups_buffer.reinitialize(ofs); - for (const WeldVert &wv : wvert) { - int group_index = r_vert_groups_map[wv.vert_dest]; - r_vert_groups_buffer[wgroups[group_index].ofs++] = wv.vert_orig; - } - - for (WeldGroup &wg : wgroups) { - wg.ofs -= wg.len; - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Weld Edge API - * \{ */ - -static void weld_edge_ctx_setup(MutableSpan<WeldGroup> r_vlinks, - MutableSpan<int> r_edge_dest_map, - MutableSpan<WeldEdge> r_wedge, - int *r_edge_kiil_len) +static Span<MDeformVert> get_vertex_group(const Mesh &mesh, const int defgrp_index) { - /* Setup Edge Overlap. */ - int edge_kill_len = 0; - - MutableSpan<WeldGroup> v_links = r_vlinks; - - for (WeldEdge &we : r_wedge) { - int dst_vert_a = we.vert_a; - int dst_vert_b = we.vert_b; - - if (dst_vert_a == dst_vert_b) { - BLI_assert(we.edge_dest == OUT_OF_CONTEXT); - r_edge_dest_map[we.edge_orig] = ELEM_COLLAPSED; - we.flag = ELEM_COLLAPSED; - edge_kill_len++; - continue; - } - - v_links[dst_vert_a].len++; - v_links[dst_vert_b].len++; - } - - int link_len = 0; - for (WeldGroup &vl : r_vlinks) { - vl.ofs = link_len; - link_len += vl.len; + if (defgrp_index == -1) { + return {}; } - - if (link_len > 0) { - Array<int> link_edge_buffer(link_len); - - for (const int i : r_wedge.index_range()) { - const WeldEdge &we = r_wedge[i]; - if (we.flag == ELEM_COLLAPSED) { - continue; - } - - int dst_vert_a = we.vert_a; - int dst_vert_b = we.vert_b; - - link_edge_buffer[v_links[dst_vert_a].ofs++] = i; - link_edge_buffer[v_links[dst_vert_b].ofs++] = i; - } - - for (WeldGroup &vl : r_vlinks) { - /* Fix offset */ - vl.ofs -= vl.len; - } - - for (const int i : r_wedge.index_range()) { - const WeldEdge &we = r_wedge[i]; - if (we.edge_dest != OUT_OF_CONTEXT) { - /* No need to retest edges. - * (Already includes collapsed edges). */ - continue; - } - - int dst_vert_a = we.vert_a; - int dst_vert_b = we.vert_b; - - struct WeldGroup *link_a = &v_links[dst_vert_a]; - struct WeldGroup *link_b = &v_links[dst_vert_b]; - - int edges_len_a = link_a->len; - int edges_len_b = link_b->len; - - if (edges_len_a <= 1 || edges_len_b <= 1) { - continue; - } - - int *edges_ctx_a = &link_edge_buffer[link_a->ofs]; - int *edges_ctx_b = &link_edge_buffer[link_b->ofs]; - int edge_orig = we.edge_orig; - - for (; edges_len_a--; edges_ctx_a++) { - int e_ctx_a = *edges_ctx_a; - if (e_ctx_a == i) { - continue; - } - while (edges_len_b && *edges_ctx_b < e_ctx_a) { - edges_ctx_b++; - edges_len_b--; - } - if (edges_len_b == 0) { - break; - } - int e_ctx_b = *edges_ctx_b; - if (e_ctx_a == e_ctx_b) { - WeldEdge *we_b = &r_wedge[e_ctx_b]; - BLI_assert(ELEM(we_b->vert_a, dst_vert_a, dst_vert_b)); - BLI_assert(ELEM(we_b->vert_b, dst_vert_a, dst_vert_b)); - BLI_assert(we_b->edge_dest == OUT_OF_CONTEXT); - BLI_assert(we_b->edge_orig != edge_orig); - r_edge_dest_map[we_b->edge_orig] = edge_orig; - we_b->edge_dest = edge_orig; - edge_kill_len++; - } - } - } - -#ifdef USE_WELD_DEBUG - weld_assert_edge_kill_len(r_wedge, edge_kill_len); -#endif + const MDeformVert *vertex_group = static_cast<const MDeformVert *>( + CustomData_get_layer(&mesh.vdata, CD_MDEFORMVERT)); + if (!vertex_group) { + return {}; } - - *r_edge_kiil_len = edge_kill_len; + return {vertex_group, mesh.totvert}; } -static Vector<WeldEdge> weld_edge_ctx_alloc(Span<MEdge> medge, - Span<int> vert_dest_map, - MutableSpan<int> r_edge_dest_map, - MutableSpan<int> r_edge_ctx_map) +static Vector<int64_t> selected_indices_from_vertex_group(Span<MDeformVert> vertex_group, + const int index, + const bool invert) { - /* Edge Context. */ - int wedge_len = 0; - - Vector<WeldEdge> wedge; - wedge.reserve(medge.size()); - - for (const int i : medge.index_range()) { - int v1 = medge[i].v1; - int v2 = medge[i].v2; - int v_dest_1 = vert_dest_map[v1]; - int v_dest_2 = vert_dest_map[v2]; - if ((v_dest_1 != OUT_OF_CONTEXT) || (v_dest_2 != OUT_OF_CONTEXT)) { - WeldEdge we{}; - we.vert_a = (v_dest_1 != OUT_OF_CONTEXT) ? v_dest_1 : v1; - we.vert_b = (v_dest_2 != OUT_OF_CONTEXT) ? v_dest_2 : v2; - we.edge_dest = OUT_OF_CONTEXT; - we.edge_orig = i; - wedge.append(we); - r_edge_dest_map[i] = i; - r_edge_ctx_map[i] = wedge_len++; - } - else { - r_edge_dest_map[i] = OUT_OF_CONTEXT; - r_edge_ctx_map[i] = OUT_OF_CONTEXT; + Vector<int64_t> selected_indices; + for (const int i : vertex_group.index_range()) { + const bool found = BKE_defvert_find_weight(&vertex_group[i], index) > 0.0f; + if (found != invert) { + selected_indices.append(i); } } - - return wedge; + return selected_indices; } -static void weld_edge_groups_setup(const int medge_len, - const int edge_kill_len, - MutableSpan<WeldEdge> wedge, - Span<int> wedge_map, - MutableSpan<int> r_edge_groups_map, - Array<int> &r_edge_groups_buffer, - Array<WeldGroupEdge> &r_edge_groups) +static Array<bool> selection_array_from_vertex_group(Span<MDeformVert> vertex_group, + const int index, + const bool invert) { - /* Get weld edge groups. */ - - struct WeldGroupEdge *wegrp_iter; - - int wgroups_len = wedge.size() - edge_kill_len; - r_edge_groups.reinitialize(wgroups_len); - r_edge_groups.fill({{0}}); - MutableSpan<WeldGroupEdge> wegroups = r_edge_groups; - wegrp_iter = &r_edge_groups[0]; - - wgroups_len = 0; - for (const int i : IndexRange(medge_len)) { - int edge_ctx = wedge_map[i]; - if (edge_ctx != OUT_OF_CONTEXT) { - WeldEdge *we = &wedge[edge_ctx]; - int edge_dest = we->edge_dest; - if (edge_dest != OUT_OF_CONTEXT) { - BLI_assert(edge_dest != we->edge_orig); - r_edge_groups_map[i] = ELEM_MERGED; - } - else { - we->edge_dest = we->edge_orig; - wegrp_iter->v1 = we->vert_a; - wegrp_iter->v2 = we->vert_b; - r_edge_groups_map[i] = wgroups_len; - wgroups_len++; - wegrp_iter++; - } - } - else { - r_edge_groups_map[i] = OUT_OF_CONTEXT; - } - } - - BLI_assert(wgroups_len == wedge.size() - edge_kill_len); - - for (const WeldEdge &we : wedge) { - if (we.flag == ELEM_COLLAPSED) { - continue; - } - int group_index = r_edge_groups_map[we.edge_dest]; - wegroups[group_index].group.len++; - } - - int ofs = 0; - for (WeldGroupEdge &wegrp : wegroups) { - wegrp.group.ofs = ofs; - ofs += wegrp.group.len; - } - - r_edge_groups_buffer.reinitialize(ofs); - for (const WeldEdge &we : wedge) { - if (we.flag == ELEM_COLLAPSED) { - continue; - } - int group_index = r_edge_groups_map[we.edge_dest]; - r_edge_groups_buffer[wegroups[group_index].group.ofs++] = we.edge_orig; - } - - for (WeldGroupEdge &wegrp : wegroups) { - wegrp.group.ofs -= wegrp.group.len; + Array<bool> selection(vertex_group.size()); + for (const int i : vertex_group.index_range()) { + const bool found = BKE_defvert_find_weight(&vertex_group[i], index) > 0.0f; + selection[i] = (found != invert); } + return selection; } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Weld Poly and Loop API - * \{ */ - -static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter &iter, - const WeldPoly &wp, - Span<WeldLoop> wloop, - Span<MLoop> mloop, - Span<int> loop_map, - int *group_buffer) +static std::optional<Mesh *> calculate_weld(const Mesh &mesh, const WeldModifierData &wmd) { - if (wp.flag == ELEM_COLLAPSED) { - return false; - } - - iter.loop_start = wp.loop_start; - iter.loop_end = wp.loop_end; - iter.wloop = wloop; - iter.mloop = mloop; - iter.loop_map = loop_map; - iter.group = group_buffer; + const int defgrp_index = BKE_id_defgroup_name_index(&mesh.id, wmd.defgrp_name); + Span<MDeformVert> vertex_group = get_vertex_group(mesh, defgrp_index); + const bool invert = (wmd.flag & MOD_WELD_INVERT_VGROUP) != 0; - int group_len = 0; - if (group_buffer) { - /* First loop group needs more attention. */ - int loop_start, loop_end, l; - loop_start = iter.loop_start; - loop_end = l = iter.loop_end; - while (l >= loop_start) { - const int loop_ctx = loop_map[l]; - if (loop_ctx != OUT_OF_CONTEXT) { - const WeldLoop *wl = &wloop[loop_ctx]; - if (wl->flag == ELEM_COLLAPSED) { - l--; - continue; - } - } - break; - } - if (l != loop_end) { - group_len = loop_end - l; - int i = 0; - while (l < loop_end) { - iter.group[i++] = ++l; - } + if (wmd.mode == MOD_WELD_MODE_ALL) { + if (!vertex_group.is_empty()) { + Vector<int64_t> selected_indices = selected_indices_from_vertex_group( + vertex_group, defgrp_index, invert); + return blender::geometry::mesh_merge_by_distance_all( + mesh, IndexMask(selected_indices), wmd.merge_dist); } + return blender::geometry::mesh_merge_by_distance_all( + mesh, IndexMask(mesh.totvert), wmd.merge_dist); } - iter.group_len = group_len; - - iter.l_next = iter.loop_start; -#ifdef USE_WELD_DEBUG - iter.v = OUT_OF_CONTEXT; -#endif - return true; -} - -static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter &iter) -{ - const int loop_end = iter.loop_end; - Span<WeldLoop> wloop = iter.wloop; - Span<int> loop_map = iter.loop_map; - int l = iter.l_curr = iter.l_next; - if (l == iter.loop_start) { - /* `grupo_len` is already calculated in the first loop */ - } - else { - iter.group_len = 0; - } - while (l <= loop_end) { - int l_next = l + 1; - const int loop_ctx = loop_map[l]; - if (loop_ctx != OUT_OF_CONTEXT) { - const WeldLoop *wl = &wloop[loop_ctx]; - if (wl->loop_skip_to != OUT_OF_CONTEXT) { - l_next = wl->loop_skip_to; - } - if (wl->flag == ELEM_COLLAPSED) { - if (iter.group) { - iter.group[iter.group_len++] = l; - } - l = l_next; - continue; - } -#ifdef USE_WELD_DEBUG - BLI_assert(iter.v != wl->vert); -#endif - iter.v = wl->vert; - iter.e = wl->edge; - iter.type = 1; - } - else { - const MLoop &ml = iter.mloop[l]; -#ifdef USE_WELD_DEBUG - BLI_assert((uint)iter.v != ml.v); -#endif - iter.v = ml.v; - iter.e = ml.e; - iter.type = 0; - } - if (iter.group) { - iter.group[iter.group_len++] = l; - } - iter.l_next = l_next; - return true; - } - - return false; -} - -static void weld_poly_loop_ctx_alloc(Span<MPoly> mpoly, - Span<MLoop> mloop, - Span<int> vert_dest_map, - Span<int> edge_dest_map, - WeldMesh *r_weld_mesh) -{ - /* Loop/Poly Context. */ - Array<int> loop_map(mloop.size()); - Array<int> poly_map(mpoly.size()); - int wloop_len = 0; - int wpoly_len = 0; - int max_ctx_poly_len = 4; - - Vector<WeldLoop> wloop; - wloop.reserve(mloop.size()); - - Vector<WeldPoly> wpoly; - wpoly.reserve(mpoly.size()); - - int maybe_new_poly = 0; - - for (const int i : mpoly.index_range()) { - const MPoly &mp = mpoly[i]; - const int loopstart = mp.loopstart; - const int totloop = mp.totloop; - - int vert_ctx_len = 0; - - int prev_wloop_len = wloop_len; - for (const int i_loop : mloop.index_range().slice(loopstart, totloop)) { - int v = mloop[i_loop].v; - int e = mloop[i_loop].e; - int v_dest = vert_dest_map[v]; - int e_dest = edge_dest_map[e]; - bool is_vert_ctx = v_dest != OUT_OF_CONTEXT; - bool is_edge_ctx = e_dest != OUT_OF_CONTEXT; - if (is_vert_ctx) { - vert_ctx_len++; - } - if (is_vert_ctx || is_edge_ctx) { - WeldLoop wl{}; - wl.vert = is_vert_ctx ? v_dest : v; - wl.edge = is_edge_ctx ? e_dest : e; - wl.loop_orig = i_loop; - wl.loop_skip_to = OUT_OF_CONTEXT; - wloop.append(wl); - - loop_map[i_loop] = wloop_len++; - } - else { - loop_map[i_loop] = OUT_OF_CONTEXT; - } - } - if (wloop_len != prev_wloop_len) { - int loops_len = wloop_len - prev_wloop_len; - WeldPoly wp{}; - wp.poly_dst = OUT_OF_CONTEXT; - wp.poly_orig = i; - wp.loops.len = loops_len; - wp.loops.ofs = prev_wloop_len; - wp.loop_start = loopstart; - wp.loop_end = loopstart + totloop - 1; - wp.len = totloop; - wpoly.append(wp); - - poly_map[i] = wpoly_len++; - if (totloop > 5 && vert_ctx_len > 1) { - int max_new = (totloop / 3) - 1; - vert_ctx_len /= 2; - maybe_new_poly += MIN2(max_new, vert_ctx_len); - CLAMP_MIN(max_ctx_poly_len, totloop); - } - } - else { - poly_map[i] = OUT_OF_CONTEXT; + if (wmd.mode == MOD_WELD_MODE_CONNECTED) { + const bool only_loose_edges = (wmd.flag & MOD_WELD_LOOSE_EDGES) != 0; + if (!vertex_group.is_empty()) { + Array<bool> selection = selection_array_from_vertex_group( + vertex_group, defgrp_index, invert); + return blender::geometry::mesh_merge_by_distance_connected( + mesh, selection, wmd.merge_dist, only_loose_edges); } + Array<bool> selection(mesh.totvert, true); + return blender::geometry::mesh_merge_by_distance_connected( + mesh, selection, wmd.merge_dist, only_loose_edges); } - if (mpoly.size() < (wpoly_len + maybe_new_poly)) { - wpoly.resize(wpoly_len + maybe_new_poly); - } - - WeldPoly *poly_new = wpoly.data() + wpoly_len; - - r_weld_mesh->wloop = std::move(wloop); - r_weld_mesh->wpoly = std::move(wpoly); - r_weld_mesh->wpoly_new = poly_new; - r_weld_mesh->wloop_len = wloop_len; - r_weld_mesh->wpoly_len = wpoly_len; - r_weld_mesh->wpoly_new_len = 0; - r_weld_mesh->loop_map = std::move(loop_map); - r_weld_mesh->poly_map = std::move(poly_map); - r_weld_mesh->max_poly_len = max_ctx_poly_len; + BLI_assert_unreachable(); + return nullptr; } -static void weld_poly_split_recursive(Span<int> vert_dest_map, -#ifdef USE_WELD_DEBUG - const Span<MLoop> mloop, -#endif - int ctx_verts_len, - WeldPoly *r_wp, - WeldMesh *r_weld_mesh, - int *r_poly_kill, - int *r_loop_kill) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { - int poly_len = r_wp->len; - if (poly_len > 3 && ctx_verts_len > 1) { - const int ctx_loops_len = r_wp->loops.len; - const int ctx_loops_ofs = r_wp->loops.ofs; - MutableSpan<WeldLoop> wloop = r_weld_mesh->wloop; - WeldPoly *wpoly_new = r_weld_mesh->wpoly_new; - - int loop_kill = 0; - - WeldLoop *poly_loops = &wloop[ctx_loops_ofs]; - WeldLoop *wla = &poly_loops[0]; - WeldLoop *wla_prev = &poly_loops[ctx_loops_len - 1]; - while (wla_prev->flag == ELEM_COLLAPSED) { - wla_prev--; - } - const int la_len = ctx_loops_len - 1; - for (int la = 0; la < la_len; la++, wla++) { - wa_continue: - if (wla->flag == ELEM_COLLAPSED) { - continue; - } - int vert_a = wla->vert; - /* Only test vertices that will be merged. */ - if (vert_dest_map[vert_a] != OUT_OF_CONTEXT) { - int lb = la + 1; - WeldLoop *wlb = wla + 1; - WeldLoop *wlb_prev = wla; - int killed_ab = 0; - ctx_verts_len = 1; - for (; lb < ctx_loops_len; lb++, wlb++) { - BLI_assert(wlb->loop_skip_to == OUT_OF_CONTEXT); - if (wlb->flag == ELEM_COLLAPSED) { - killed_ab++; - continue; - } - int vert_b = wlb->vert; - if (vert_dest_map[vert_b] != OUT_OF_CONTEXT) { - ctx_verts_len++; - } - if (vert_a == vert_b) { - const int dist_a = wlb->loop_orig - wla->loop_orig - killed_ab; - const int dist_b = poly_len - dist_a; + const WeldModifierData &wmd = reinterpret_cast<WeldModifierData &>(*md); - BLI_assert(dist_a != 0 && dist_b != 0); - if (dist_a == 1 || dist_b == 1) { - BLI_assert(dist_a != dist_b); - BLI_assert((wla->flag == ELEM_COLLAPSED) || (wlb->flag == ELEM_COLLAPSED)); - } - else { - WeldLoop *wl_tmp = nullptr; - if (dist_a == 2) { - wl_tmp = wlb_prev; - BLI_assert(wla->flag != ELEM_COLLAPSED); - BLI_assert(wl_tmp->flag != ELEM_COLLAPSED); - wla->flag = ELEM_COLLAPSED; - wl_tmp->flag = ELEM_COLLAPSED; - loop_kill += 2; - poly_len -= 2; - } - if (dist_b == 2) { - if (wl_tmp != nullptr) { - r_wp->flag = ELEM_COLLAPSED; - *r_poly_kill += 1; - } - else { - wl_tmp = wla_prev; - BLI_assert(wlb->flag != ELEM_COLLAPSED); - BLI_assert(wl_tmp->flag != ELEM_COLLAPSED); - wlb->flag = ELEM_COLLAPSED; - wl_tmp->flag = ELEM_COLLAPSED; - } - loop_kill += 2; - poly_len -= 2; - } - if (wl_tmp == nullptr) { - const int new_loops_len = lb - la; - const int new_loops_ofs = ctx_loops_ofs + la; - - WeldPoly *new_wp = &wpoly_new[r_weld_mesh->wpoly_new_len++]; - new_wp->poly_dst = OUT_OF_CONTEXT; - new_wp->poly_orig = r_wp->poly_orig; - new_wp->loops.len = new_loops_len; - new_wp->loops.ofs = new_loops_ofs; - new_wp->loop_start = wla->loop_orig; - new_wp->loop_end = wlb_prev->loop_orig; - new_wp->len = dist_a; - weld_poly_split_recursive(vert_dest_map, -#ifdef USE_WELD_DEBUG - mloop, -#endif - ctx_verts_len, - new_wp, - r_weld_mesh, - r_poly_kill, - r_loop_kill); - BLI_assert(dist_b == poly_len - dist_a); - poly_len = dist_b; - if (wla_prev->loop_orig > wla->loop_orig) { - /* New start. */ - r_wp->loop_start = wlb->loop_orig; - } - else { - /* The `loop_start` doesn't change but some loops must be skipped. */ - wla_prev->loop_skip_to = wlb->loop_orig; - } - wla = wlb; - la = lb; - goto wa_continue; - } - break; - } - } - if (wlb->flag != ELEM_COLLAPSED) { - wlb_prev = wlb; - } - } - } - if (wla->flag != ELEM_COLLAPSED) { - wla_prev = wla; - } - } - r_wp->len = poly_len; - *r_loop_kill += loop_kill; - -#ifdef USE_WELD_DEBUG - weld_assert_poly_no_vert_repetition(*r_wp, wloop, mloop, r_weld_mesh->loop_map); -#endif - } -} - -static void weld_poly_loop_ctx_setup(Span<MLoop> mloop, -#ifdef USE_WELD_DEBUG - Span<MPoly> mpoly, -#endif - const int mvert_len, - Span<int> vert_dest_map, - const int remain_edge_ctx_len, - MutableSpan<WeldGroup> r_vlinks, - WeldMesh *r_weld_mesh) -{ - MutableSpan<WeldPoly> wpoly = r_weld_mesh->wpoly; - MutableSpan<WeldLoop> wloop = r_weld_mesh->wloop; - WeldPoly *wpoly_new = r_weld_mesh->wpoly_new; - int wpoly_len = r_weld_mesh->wpoly_len; - int wpoly_new_len = 0; - int poly_kill_len = 0; - int loop_kill_len = 0; - - Span<int> loop_map = r_weld_mesh->loop_map; - - if (remain_edge_ctx_len) { - - /* Setup Poly/Loop. Note that `wpoly_len` may be different than `wpoly.size()` here. */ - for (const int i : IndexRange(wpoly_len)) { - WeldPoly &wp = wpoly[i]; - const int ctx_loops_len = wp.loops.len; - const int ctx_loops_ofs = wp.loops.ofs; - - int poly_len = wp.len; - int ctx_verts_len = 0; - WeldLoop *wl = &wloop[ctx_loops_ofs]; - for (int l = ctx_loops_len; l--; wl++) { - const int edge_dest = wl->edge; - if (edge_dest == ELEM_COLLAPSED) { - wl->flag = ELEM_COLLAPSED; - if (poly_len == 3) { - wp.flag = ELEM_COLLAPSED; - poly_kill_len++; - loop_kill_len += 3; - poly_len = 0; - break; - } - loop_kill_len++; - poly_len--; - } - else { - const int vert_dst = wl->vert; - if (vert_dest_map[vert_dst] != OUT_OF_CONTEXT) { - ctx_verts_len++; - } - } - } - - if (poly_len) { - wp.len = poly_len; -#ifdef USE_WELD_DEBUG - weld_assert_poly_len(wp, wloop); -#endif - - weld_poly_split_recursive(vert_dest_map, -#ifdef USE_WELD_DEBUG - mloop, -#endif - ctx_verts_len, - &wp, - r_weld_mesh, - &poly_kill_len, - &loop_kill_len); - - wpoly_new_len = r_weld_mesh->wpoly_new_len; - } - } - -#ifdef USE_WELD_DEBUG - weld_assert_poly_and_loop_kill_len(wpoly, - {wpoly_new, wpoly_new_len}, - wloop, - mloop, - loop_map, - r_weld_mesh->poly_map, - mpoly, - poly_kill_len, - loop_kill_len); -#endif - - /* Setup Polygon Overlap. */ - - const int wpoly_and_new_len = wpoly_len + wpoly_new_len; - - r_vlinks.fill({0, 0}); - MutableSpan<WeldGroup> v_links = r_vlinks; - - for (const int i : IndexRange(wpoly_and_new_len)) { - const WeldPoly &wp = wpoly[i]; - WeldLoopOfPolyIter iter; - if (weld_iter_loop_of_poly_begin(iter, wp, wloop, mloop, loop_map, nullptr)) { - while (weld_iter_loop_of_poly_next(iter)) { - v_links[iter.v].len++; - } - } - } - - int link_len = 0; - for (const int i : IndexRange(mvert_len)) { - v_links[i].ofs = link_len; - link_len += v_links[i].len; - } - - if (link_len) { - Array<int> link_poly_buffer(link_len); - - for (const int i : IndexRange(wpoly_and_new_len)) { - const WeldPoly &wp = wpoly[i]; - WeldLoopOfPolyIter iter; - if (weld_iter_loop_of_poly_begin(iter, wp, wloop, mloop, loop_map, nullptr)) { - while (weld_iter_loop_of_poly_next(iter)) { - link_poly_buffer[v_links[iter.v].ofs++] = i; - } - } - } - - for (WeldGroup &vl : r_vlinks) { - /* Fix offset */ - vl.ofs -= vl.len; - } - - int polys_len_a, polys_len_b, *polys_ctx_a, *polys_ctx_b, p_ctx_a, p_ctx_b; - polys_len_b = p_ctx_b = 0; /* silence warnings */ - - for (const int i : IndexRange(wpoly_and_new_len)) { - const WeldPoly &wp = wpoly[i]; - if (wp.poly_dst != OUT_OF_CONTEXT) { - /* No need to retest poly. - * (Already includes collapsed polygons). */ - continue; - } - - WeldLoopOfPolyIter iter; - weld_iter_loop_of_poly_begin(iter, wp, wloop, mloop, loop_map, nullptr); - weld_iter_loop_of_poly_next(iter); - struct WeldGroup *link_a = &v_links[iter.v]; - polys_len_a = link_a->len; - if (polys_len_a == 1) { - BLI_assert(link_poly_buffer[link_a->ofs] == i); - continue; - } - int wp_len = wp.len; - polys_ctx_a = &link_poly_buffer[link_a->ofs]; - for (; polys_len_a--; polys_ctx_a++) { - p_ctx_a = *polys_ctx_a; - if (p_ctx_a == i) { - continue; - } - - WeldPoly *wp_tmp = &wpoly[p_ctx_a]; - if (wp_tmp->len != wp_len) { - continue; - } - - WeldLoopOfPolyIter iter_b = iter; - while (weld_iter_loop_of_poly_next(iter_b)) { - struct WeldGroup *link_b = &v_links[iter_b.v]; - polys_len_b = link_b->len; - if (polys_len_b == 1) { - BLI_assert(link_poly_buffer[link_b->ofs] == i); - polys_len_b = 0; - break; - } - - polys_ctx_b = &link_poly_buffer[link_b->ofs]; - for (; polys_len_b; polys_len_b--, polys_ctx_b++) { - p_ctx_b = *polys_ctx_b; - if (p_ctx_b < p_ctx_a) { - continue; - } - if (p_ctx_b >= p_ctx_a) { - if (p_ctx_b > p_ctx_a) { - polys_len_b = 0; - } - break; - } - } - if (polys_len_b == 0) { - break; - } - } - if (polys_len_b == 0) { - continue; - } - BLI_assert(p_ctx_a > i); - BLI_assert(p_ctx_a == p_ctx_b); - BLI_assert(wp_tmp->poly_dst == OUT_OF_CONTEXT); - BLI_assert(wp_tmp != &wp); - wp_tmp->poly_dst = wp.poly_orig; - loop_kill_len += wp_tmp->len; - poly_kill_len++; - } - } - } - } - else { - poly_kill_len = r_weld_mesh->wpoly_len; - loop_kill_len = r_weld_mesh->wloop_len; - - for (WeldPoly &wp : wpoly) { - wp.flag = ELEM_COLLAPSED; - } - } - -#ifdef USE_WELD_DEBUG - weld_assert_poly_and_loop_kill_len(wpoly, - {wpoly_new, wpoly_new_len}, - wloop, - mloop, - loop_map, - r_weld_mesh->poly_map, - mpoly, - poly_kill_len, - loop_kill_len); -#endif - - r_weld_mesh->wpoly_new = wpoly_new; - r_weld_mesh->poly_kill_len = poly_kill_len; - r_weld_mesh->loop_kill_len = loop_kill_len; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Weld Mesh API - * \{ */ - -static void weld_mesh_context_create(const Mesh &mesh, - MutableSpan<int> vert_dest_map, - const int vert_kill_len, - WeldMesh *r_weld_mesh) -{ - Span<MEdge> medge{mesh.medge, mesh.totedge}; - Span<MPoly> mpoly{mesh.mpoly, mesh.totpoly}; - Span<MLoop> mloop{mesh.mloop, mesh.totloop}; - const int mvert_len = mesh.totvert; - - Vector<WeldVert> wvert = weld_vert_ctx_alloc_and_setup(vert_dest_map, vert_kill_len); - r_weld_mesh->vert_kill_len = vert_kill_len; - - Array<int> edge_dest_map(medge.size()); - Array<int> edge_ctx_map(medge.size()); - Vector<WeldEdge> wedge = weld_edge_ctx_alloc(medge, vert_dest_map, edge_dest_map, edge_ctx_map); - - Array<WeldGroup> v_links(mvert_len, {0, 0}); - weld_edge_ctx_setup(v_links, edge_dest_map, wedge, &r_weld_mesh->edge_kill_len); - - weld_poly_loop_ctx_alloc(mpoly, mloop, vert_dest_map, edge_dest_map, r_weld_mesh); - - weld_poly_loop_ctx_setup(mloop, -#ifdef USE_WELD_DEBUG - mpoly, - -#endif - mvert_len, - vert_dest_map, - wedge.size() - r_weld_mesh->edge_kill_len, - v_links, - r_weld_mesh); - - weld_vert_groups_setup(wvert, - vert_dest_map, - vert_dest_map, - r_weld_mesh->vert_groups_buffer, - r_weld_mesh->vert_groups); - - weld_edge_groups_setup(medge.size(), - r_weld_mesh->edge_kill_len, - wedge, - edge_ctx_map, - edge_dest_map, - r_weld_mesh->edge_groups_buffer, - r_weld_mesh->edge_groups); - - r_weld_mesh->edge_groups_map = std::move(edge_dest_map); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Weld CustomData - * \{ */ - -static void customdata_weld( - const CustomData *source, CustomData *dest, const int *src_indices, int count, int dest_index) -{ - if (count == 1) { - CustomData_copy_data(source, dest, src_indices[0], dest_index, 1); - return; - } - - CustomData_interp(source, dest, (const int *)src_indices, nullptr, nullptr, count, dest_index); - - int src_i, dest_i; - int j; - - float co[3] = {0.0f, 0.0f, 0.0f}; -#ifdef USE_WELD_NORMALS - float no[3] = {0.0f, 0.0f, 0.0f}; -#endif - int crease = 0; - int bweight = 0; - short flag = 0; - - /* interpolates a layer at a time */ - dest_i = 0; - for (src_i = 0; src_i < source->totlayer; src_i++) { - const int type = source->layers[src_i].type; - - /* find the first dest layer with type >= the source type - * (this should work because layers are ordered by type) - */ - while (dest_i < dest->totlayer && dest->layers[dest_i].type < type) { - dest_i++; - } - - /* if there are no more dest layers, we're done */ - if (dest_i == dest->totlayer) { - break; - } - - /* if we found a matching layer, add the data */ - if (dest->layers[dest_i].type == type) { - void *src_data = source->layers[src_i].data; - - if (type == CD_MVERT) { - for (j = 0; j < count; j++) { - MVert *mv_src = &((MVert *)src_data)[src_indices[j]]; - add_v3_v3(co, mv_src->co); -#ifdef USE_WELD_NORMALS - short *mv_src_no = mv_src->no; - no[0] += mv_src_no[0]; - no[1] += mv_src_no[1]; - no[2] += mv_src_no[2]; -#endif - bweight += mv_src->bweight; - flag |= mv_src->flag; - } - } - else if (type == CD_MEDGE) { - for (j = 0; j < count; j++) { - MEdge *me_src = &((MEdge *)src_data)[src_indices[j]]; - crease += me_src->crease; - bweight += me_src->bweight; - flag |= me_src->flag; - } - } - else if (CustomData_layer_has_interp(dest, dest_i)) { - /* Already calculated. - * TODO: Optimize by exposing `typeInfo->interp`. */ - } - else if (CustomData_layer_has_math(dest, dest_i)) { - const int size = CustomData_sizeof(type); - void *dst_data = dest->layers[dest_i].data; - void *v_dst = POINTER_OFFSET(dst_data, (size_t)dest_index * size); - for (j = 0; j < count; j++) { - CustomData_data_add( - type, v_dst, POINTER_OFFSET(src_data, (size_t)src_indices[j] * size)); - } - } - else { - CustomData_copy_layer_type_data(source, dest, type, src_indices[0], dest_index, 1); - } - - /* if there are multiple source & dest layers of the same type, - * we don't want to copy all source layers to the same dest, so - * increment dest_i - */ - dest_i++; - } - } - - float fac = 1.0f / count; - - for (dest_i = 0; dest_i < dest->totlayer; dest_i++) { - CustomDataLayer *layer_dst = &dest->layers[dest_i]; - const int type = layer_dst->type; - if (type == CD_MVERT) { - MVert *mv = &((MVert *)layer_dst->data)[dest_index]; - mul_v3_fl(co, fac); - bweight *= fac; - CLAMP_MAX(bweight, 255); - - copy_v3_v3(mv->co, co); -#ifdef USE_WELD_NORMALS - mul_v3_fl(no, fac); - short *mv_no = mv->no; - mv_no[0] = (short)no[0]; - mv_no[1] = (short)no[1]; - mv_no[2] = (short)no[2]; -#endif - - mv->flag = (char)flag; - mv->bweight = (char)bweight; - } - else if (type == CD_MEDGE) { - MEdge *me = &((MEdge *)layer_dst->data)[dest_index]; - crease *= fac; - bweight *= fac; - CLAMP_MAX(crease, 255); - CLAMP_MAX(bweight, 255); - - me->crease = (char)crease; - me->bweight = (char)bweight; - me->flag = flag; - } - else if (CustomData_layer_has_interp(dest, dest_i)) { - /* Already calculated. */ - } - else if (CustomData_layer_has_math(dest, dest_i)) { - const int size = CustomData_sizeof(type); - void *dst_data = layer_dst->data; - void *v_dst = POINTER_OFFSET(dst_data, (size_t)dest_index * size); - CustomData_data_multiply(type, v_dst, fac); - } - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Weld Modifier Main - * \{ */ - -#ifdef USE_BVHTREEKDOP -struct WeldOverlapData { - const MVert *mvert; - float merge_dist_sq; -}; -static bool bvhtree_weld_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread)) -{ - if (index_a < index_b) { - struct WeldOverlapData *data = userdata; - const MVert *mvert = data->mvert; - const float dist_sq = len_squared_v3v3(mvert[index_a].co, mvert[index_b].co); - BLI_assert(dist_sq <= ((data->merge_dist_sq + FLT_EPSILON) * 3)); - return dist_sq <= data->merge_dist_sq; - } - return false; -} -#endif - -/** Use for #MOD_WELD_MODE_CONNECTED calculation. */ -struct WeldVertexCluster { - float co[3]; - int merged_verts; -}; - -static Mesh *weldModifier_doWeld(WeldModifierData *wmd, - const ModifierEvalContext *UNUSED(ctx), - Mesh *mesh) -{ - BLI_bitmap *v_mask = nullptr; - int v_mask_act = 0; - - Span<MVert> mvert{mesh->mvert, mesh->totvert}; - Span<MEdge> medge{mesh->medge, mesh->totedge}; - Span<MPoly> mpoly{mesh->mpoly, mesh->totpoly}; - Span<MLoop> mloop{mesh->mloop, mesh->totloop}; - const int totvert = mesh->totvert; - const int totedge = mesh->totedge; - const int totloop = mesh->totloop; - const int totpoly = mesh->totpoly; - - /* Vertex Group. */ - const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); - if (defgrp_index != -1) { - MDeformVert *dvert; - dvert = static_cast<MDeformVert *>(CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT)); - if (dvert) { - const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0; - v_mask = BLI_BITMAP_NEW(totvert, __func__); - for (const int i : IndexRange(totvert)) { - const bool found = BKE_defvert_find_weight(&dvert[i], defgrp_index) > 0.0f; - if (found != invert_vgroup) { - BLI_BITMAP_ENABLE(v_mask, i); - v_mask_act++; - } - } - } - } - - /* From the original index of the vertex. - * This indicates which vert it is or is going to be merged. */ - Array<int> vert_dest_map(totvert); - int vert_kill_len = 0; - if (wmd->mode == MOD_WELD_MODE_ALL) -#ifdef USE_BVHTREEKDOP - { - /* Get overlap map. */ - struct BVHTreeFromMesh treedata; - BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata, - mvert.data(), - totvert, - false, - v_mask, - v_mask_act, - wmd->merge_dist / 2, - 2, - 6, - 0, - nullptr, - nullptr); - - if (bvhtree) { - struct WeldOverlapData data; - data.mvert = mvert; - data.merge_dist_sq = square_f(wmd->merge_dist); - - uint overlap_len; - BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree, - bvhtree, - &overlap_len, - bvhtree_weld_overlap_cb, - &data, - 1, - BVH_OVERLAP_RETURN_PAIRS); - - free_bvhtree_from_mesh(&treedata); - if (overlap) { - range_vn_i(vert_dest_map.data(), totvert, 0); - - const BVHTreeOverlap *overlap_iter = &overlap[0]; - for (int i = 0; i < overlap_len; i++, overlap_iter++) { - int indexA = overlap_iter->indexA; - int indexB = overlap_iter->indexB; - - BLI_assert(indexA < indexB); - - int va_dst = vert_dest_map[indexA]; - while (va_dst != vert_dest_map[va_dst]) { - va_dst = vert_dest_map[va_dst]; - } - int vb_dst = vert_dest_map[indexB]; - while (vb_dst != vert_dest_map[vb_dst]) { - vb_dst = vert_dest_map[vb_dst]; - } - if (va_dst == vb_dst) { - continue; - } - if (va_dst > vb_dst) { - SWAP(int, va_dst, vb_dst); - } - vert_kill_len++; - vert_dest_map[vb_dst] = va_dst; - } - - /* Fix #r_vert_dest_map for next step. */ - for (int i = 0; i < totvert; i++) { - if (i == vert_dest_map[i]) { - vert_dest_map[i] = OUT_OF_CONTEXT; - } - else { - int v = i; - while (v != vert_dest_map[v] && vert_dest_map[v] != OUT_OF_CONTEXT) { - v = vert_dest_map[v]; - } - vert_dest_map[v] = v; - vert_dest_map[i] = v; - } - } - - MEM_freeN(overlap); - } - } - } -#else - { - KDTree_3d *tree = BLI_kdtree_3d_new(v_mask ? v_mask_act : totvert); - for (const int i : IndexRange(totvert)) { - if (!v_mask || BLI_BITMAP_TEST(v_mask, i)) { - BLI_kdtree_3d_insert(tree, i, mvert[i].co); - } - vert_dest_map[i] = OUT_OF_CONTEXT; - } - - BLI_kdtree_3d_balance(tree); - vert_kill_len = BLI_kdtree_3d_calc_duplicates_fast( - tree, wmd->merge_dist, false, vert_dest_map.data()); - BLI_kdtree_3d_free(tree); - } -#endif - else { - BLI_assert(wmd->mode == MOD_WELD_MODE_CONNECTED); - - Array<WeldVertexCluster> vert_clusters(totvert); - - for (const int i : mvert.index_range()) { - WeldVertexCluster &vc = vert_clusters[i]; - copy_v3_v3(vc.co, mvert[i].co); - vc.merged_verts = 0; - } - const float merge_dist_sq = square_f(wmd->merge_dist); - - range_vn_i(vert_dest_map.data(), totvert, 0); - - /* Collapse Edges that are shorter than the threshold. */ - for (const int i : medge.index_range()) { - int v1 = medge[i].v1; - int v2 = medge[i].v2; - - if (wmd->flag & MOD_WELD_LOOSE_EDGES && (medge[i].flag & ME_LOOSEEDGE) == 0) { - continue; - } - while (v1 != vert_dest_map[v1]) { - v1 = vert_dest_map[v1]; - } - while (v2 != vert_dest_map[v2]) { - v2 = vert_dest_map[v2]; - } - if (v1 == v2) { - continue; - } - if (v_mask && (!BLI_BITMAP_TEST(v_mask, v1) || !BLI_BITMAP_TEST(v_mask, v2))) { - continue; - } - if (v1 > v2) { - SWAP(int, v1, v2); - } - WeldVertexCluster *v1_cluster = &vert_clusters[v1]; - WeldVertexCluster *v2_cluster = &vert_clusters[v2]; - - float edgedir[3]; - sub_v3_v3v3(edgedir, v2_cluster->co, v1_cluster->co); - const float dist_sq = len_squared_v3(edgedir); - if (dist_sq <= merge_dist_sq) { - float influence = (v2_cluster->merged_verts + 1) / - (float)(v1_cluster->merged_verts + v2_cluster->merged_verts + 2); - madd_v3_v3fl(v1_cluster->co, edgedir, influence); - - v1_cluster->merged_verts += v2_cluster->merged_verts + 1; - vert_dest_map[v2] = v1; - vert_kill_len++; - } - } - - for (const int i : IndexRange(totvert)) { - if (i == vert_dest_map[i]) { - vert_dest_map[i] = OUT_OF_CONTEXT; - } - else { - int v = i; - while ((v != vert_dest_map[v]) && (vert_dest_map[v] != OUT_OF_CONTEXT)) { - v = vert_dest_map[v]; - } - vert_dest_map[v] = v; - vert_dest_map[i] = v; - } - } - } - - if (v_mask) { - MEM_freeN(v_mask); - } - - if (vert_kill_len == 0) { + std::optional<Mesh *> result = calculate_weld(*mesh, wmd); + if (!result) { return mesh; } - - WeldMesh weld_mesh; - weld_mesh_context_create(*mesh, vert_dest_map, vert_kill_len, &weld_mesh); - - const int result_nverts = totvert - weld_mesh.vert_kill_len; - const int result_nedges = totedge - weld_mesh.edge_kill_len; - const int result_nloops = totloop - weld_mesh.loop_kill_len; - const int result_npolys = totpoly - weld_mesh.poly_kill_len + weld_mesh.wpoly_new_len; - - Mesh *result = BKE_mesh_new_nomain_from_template( - mesh, result_nverts, result_nedges, 0, result_nloops, result_npolys); - - /* Vertices. */ - - /* Be careful when editing this array, to avoid new allocations it uses the same buffer as - * #vert_dest_map. This map will be used to adjust the edges, polys and loops. */ - MutableSpan<int> vert_final = vert_dest_map; - - int dest_index = 0; - for (int i = 0; i < totvert; i++) { - int source_index = i; - int count = 0; - while (i < totvert && vert_dest_map[i] == OUT_OF_CONTEXT) { - vert_final[i] = dest_index + count; - count++; - i++; - } - if (count) { - CustomData_copy_data(&mesh->vdata, &result->vdata, source_index, dest_index, count); - dest_index += count; - } - if (i == totvert) { - break; - } - if (vert_dest_map[i] != ELEM_MERGED) { - struct WeldGroup *wgroup = &weld_mesh.vert_groups[vert_dest_map[i]]; - customdata_weld(&mesh->vdata, - &result->vdata, - &weld_mesh.vert_groups_buffer[wgroup->ofs], - wgroup->len, - dest_index); - vert_final[i] = dest_index; - dest_index++; - } - } - - BLI_assert(dest_index == result_nverts); - - /* Edges. */ - - /* Be careful when editing this array, to avoid new allocations it uses the same buffer as - * #edge_groups_map. This map will be used to adjust the polys and loops. */ - MutableSpan<int> edge_final = weld_mesh.edge_groups_map; - - dest_index = 0; - for (int i = 0; i < totedge; i++) { - const int source_index = i; - int count = 0; - while (i < totedge && weld_mesh.edge_groups_map[i] == OUT_OF_CONTEXT) { - edge_final[i] = dest_index + count; - count++; - i++; - } - if (count) { - CustomData_copy_data(&mesh->edata, &result->edata, source_index, dest_index, count); - MEdge *me = &result->medge[dest_index]; - dest_index += count; - for (; count--; me++) { - me->v1 = vert_final[me->v1]; - me->v2 = vert_final[me->v2]; - } - } - if (i == totedge) { - break; - } - if (weld_mesh.edge_groups_map[i] != ELEM_MERGED) { - struct WeldGroupEdge *wegrp = &weld_mesh.edge_groups[weld_mesh.edge_groups_map[i]]; - customdata_weld(&mesh->edata, - &result->edata, - &weld_mesh.edge_groups_buffer[wegrp->group.ofs], - wegrp->group.len, - dest_index); - MEdge *me = &result->medge[dest_index]; - me->v1 = vert_final[wegrp->v1]; - me->v2 = vert_final[wegrp->v2]; - me->flag |= ME_LOOSEEDGE; - - edge_final[i] = dest_index; - dest_index++; - } - } - - BLI_assert(dest_index == result_nedges); - - /* Polys/Loops. */ - - MPoly *r_mp = &result->mpoly[0]; - MLoop *r_ml = &result->mloop[0]; - int r_i = 0; - int loop_cur = 0; - Array<int, 64> group_buffer(weld_mesh.max_poly_len); - for (const int i : mpoly.index_range()) { - const MPoly &mp = mpoly[i]; - const int loop_start = loop_cur; - const int poly_ctx = weld_mesh.poly_map[i]; - if (poly_ctx == OUT_OF_CONTEXT) { - int mp_loop_len = mp.totloop; - CustomData_copy_data(&mesh->ldata, &result->ldata, mp.loopstart, loop_cur, mp_loop_len); - loop_cur += mp_loop_len; - for (; mp_loop_len--; r_ml++) { - r_ml->v = vert_final[r_ml->v]; - r_ml->e = edge_final[r_ml->e]; - } - } - else { - const WeldPoly &wp = weld_mesh.wpoly[poly_ctx]; - WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin( - iter, wp, weld_mesh.wloop, mloop, weld_mesh.loop_map, group_buffer.data())) { - continue; - } - - if (wp.poly_dst != OUT_OF_CONTEXT) { - continue; - } - while (weld_iter_loop_of_poly_next(iter)) { - customdata_weld( - &mesh->ldata, &result->ldata, group_buffer.data(), iter.group_len, loop_cur); - int v = vert_final[iter.v]; - int e = edge_final[iter.e]; - r_ml->v = v; - r_ml->e = e; - r_ml++; - loop_cur++; - if (iter.type) { - result->medge[e].flag &= ~ME_LOOSEEDGE; - } - BLI_assert((result->medge[e].flag & ME_LOOSEEDGE) == 0); - } - } - - CustomData_copy_data(&mesh->pdata, &result->pdata, i, r_i, 1); - r_mp->loopstart = loop_start; - r_mp->totloop = loop_cur - loop_start; - r_mp++; - r_i++; - } - - for (const int i : IndexRange(weld_mesh.wpoly_new_len)) { - const WeldPoly &wp = weld_mesh.wpoly_new[i]; - const int loop_start = loop_cur; - WeldLoopOfPolyIter iter; - if (!weld_iter_loop_of_poly_begin( - iter, wp, weld_mesh.wloop, mloop, weld_mesh.loop_map, group_buffer.data())) { - continue; - } - - if (wp.poly_dst != OUT_OF_CONTEXT) { - continue; - } - while (weld_iter_loop_of_poly_next(iter)) { - customdata_weld(&mesh->ldata, &result->ldata, group_buffer.data(), iter.group_len, loop_cur); - int v = vert_final[iter.v]; - int e = edge_final[iter.e]; - r_ml->v = v; - r_ml->e = e; - r_ml++; - loop_cur++; - if (iter.type) { - result->medge[e].flag &= ~ME_LOOSEEDGE; - } - BLI_assert((result->medge[e].flag & ME_LOOSEEDGE) == 0); - } - - r_mp->loopstart = loop_start; - r_mp->totloop = loop_cur - loop_start; - r_mp++; - r_i++; - } - - BLI_assert((int)r_i == result_npolys); - BLI_assert(loop_cur == result_nloops); - - /* We could only update the normals of the elements in context, but the next modifier can make it - * dirty anyway which would make the work useless. */ - BKE_mesh_normals_tag_dirty(result); - - return result; -} - -static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) -{ - WeldModifierData *wmd = (WeldModifierData *)md; - return weldModifier_doWeld(wmd, ctx, mesh); + return *result; } static void initData(ModifierData *md) @@ -1943,7 +218,6 @@ ModifierTypeInfo modifierType_Weld = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ nullptr, /* modifyGeometrySet */ nullptr, /* initData */ initData, diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 706960182cf..72bc4336eff 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -194,7 +194,6 @@ ModifierTypeInfo modifierType_Wireframe = { /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, /* modifyGeometrySet */ NULL, /* initData */ initData, |