Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern')
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c1
-rw-r--r--source/blender/modifiers/intern/MOD_array.c1
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c1
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_build.c1
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c1
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c1
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c3
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c1
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c1
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c7
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c1
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c1
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c1
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c1
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c1
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c1
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_mesh_to_volume.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c1
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c3
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c5
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c4
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c1
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc355
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc2
-rw-r--r--source/blender/modifiers/intern/MOD_none.c1
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c3
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c1
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c1
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c1
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c1
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c30
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c1
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c1
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c1
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c1
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c1
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c1
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c8
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c1
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c5
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c1
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c4
-rw-r--r--source/blender/modifiers/intern/MOD_volume_displace.cc3
-rw-r--r--source/blender/modifiers/intern/MOD_volume_to_mesh.cc1
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c1
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c18
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c1
-rw-r--r--source/blender/modifiers/intern/MOD_weld.cc1840
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c1
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,