Blender  V3.3
MOD_mask.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_utildefines.h"
11 
12 #include "BLI_ghash.h"
13 #include "BLI_listbase.h"
14 #include "BLI_math.h"
15 
16 #include "BLT_translation.h"
17 
18 #include "DNA_armature_types.h"
19 #include "DNA_defaults.h"
20 #include "DNA_mesh_types.h"
21 #include "DNA_meshdata_types.h"
22 #include "DNA_modifier_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_screen_types.h"
25 
26 #include "BKE_action.h" /* BKE_pose_channel_find_name */
27 #include "BKE_context.h"
28 #include "BKE_customdata.h"
29 #include "BKE_deform.h"
30 #include "BKE_lib_query.h"
31 #include "BKE_mesh.h"
32 #include "BKE_modifier.h"
33 #include "BKE_screen.h"
34 
35 #include "UI_interface.h"
36 #include "UI_resources.h"
37 
38 #include "RNA_access.h"
39 #include "RNA_prototypes.h"
40 
41 #include "DEG_depsgraph_build.h"
42 #include "DEG_depsgraph_query.h"
43 
44 #include "MOD_modifiertypes.h"
45 #include "MOD_ui_common.h"
46 
47 #include "BLI_array.hh"
48 #include "BLI_listbase_wrapper.hh"
49 #include "BLI_vector.hh"
50 
51 using blender::Array;
55 using blender::Span;
56 using blender::Vector;
57 
58 static void initData(ModifierData *md)
59 {
61 
63 
65 }
66 
67 static void requiredDataMask(Object *UNUSED(ob),
68  ModifierData *UNUSED(md),
69  CustomData_MeshMasks *r_cddata_masks)
70 {
71  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
72 }
73 
74 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
75 {
76  MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md);
77  walk(userData, ob, (ID **)&mmd->ob_arm, IDWALK_CB_NOP);
78 }
79 
81 {
82  MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md);
83  if (mmd->ob_arm) {
84  bArmature *arm = (bArmature *)mmd->ob_arm->data;
85  /* Tag relationship in depsgraph, but also on the armature. */
86  /* TODO(sergey): Is it a proper relation here? */
87  DEG_add_object_relation(ctx->node, mmd->ob_arm, DEG_OB_COMP_TRANSFORM, "Mask Modifier");
88  arm->flag |= ARM_HAS_VIZ_DEPS;
89  DEG_add_modifier_to_transform_relation(ctx->node, "Mask Modifier");
90  }
91 }
92 
93 /* A vertex will be in the mask if a selected bone influences it more than a certain threshold. */
95  Mesh *mesh,
96  Object *armature_ob,
97  float threshold,
98  MutableSpan<bool> r_vertex_mask)
99 {
100  /* Element i is true if there is a selected bone that uses vertex group i. */
101  Vector<bool> selected_bone_uses_group;
102 
104  bPoseChannel *pchan = BKE_pose_channel_find_name(armature_ob->pose, def->name);
105  bool bone_for_group_exists = pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED);
106  selected_bone_uses_group.append(bone_for_group_exists);
107  }
108 
109  Span<bool> use_vertex_group = selected_bone_uses_group;
110 
111  for (int i : r_vertex_mask.index_range()) {
112  Span<MDeformWeight> weights(dvert[i].dw, dvert[i].totweight);
113  r_vertex_mask[i] = false;
114 
115  /* check the groups that vertex is assigned to, and see if it was any use */
116  for (const MDeformWeight &dw : weights) {
117  if (use_vertex_group.get(dw.def_nr, false)) {
118  if (dw.weight > threshold) {
119  r_vertex_mask[i] = true;
120  break;
121  }
122  }
123  }
124  }
125 }
126 
127 /* A vertex will be in the mask if the vertex group influences it more than a certain threshold. */
129  int defgrp_index,
130  float threshold,
131  MutableSpan<bool> r_vertex_mask)
132 {
133  for (int i : r_vertex_mask.index_range()) {
134  const bool found = BKE_defvert_find_weight(&dvert[i], defgrp_index) > threshold;
135  r_vertex_mask[i] = found;
136  }
137 }
138 
140 {
141  for (bool &value : array) {
142  value = !value;
143  }
144 }
145 
146 static void compute_masked_vertices(Span<bool> vertex_mask,
147  MutableSpan<int> r_vertex_map,
148  uint *r_verts_masked_num)
149 {
150  BLI_assert(vertex_mask.size() == r_vertex_map.size());
151 
152  uint verts_masked_num = 0;
153  for (uint i_src : r_vertex_map.index_range()) {
154  if (vertex_mask[i_src]) {
155  r_vertex_map[i_src] = verts_masked_num;
156  verts_masked_num++;
157  }
158  else {
159  r_vertex_map[i_src] = -1;
160  }
161  }
162 
163  *r_verts_masked_num = verts_masked_num;
164 }
165 
166 static void computed_masked_edges(const Mesh *mesh,
167  Span<bool> vertex_mask,
168  MutableSpan<int> r_edge_map,
169  uint *r_edges_masked_num)
170 {
171  BLI_assert(mesh->totedge == r_edge_map.size());
172 
173  uint edges_masked_num = 0;
174  for (int i : IndexRange(mesh->totedge)) {
175  const MEdge &edge = mesh->medge[i];
176 
177  /* only add if both verts will be in new mesh */
178  if (vertex_mask[edge.v1] && vertex_mask[edge.v2]) {
179  r_edge_map[i] = edges_masked_num;
180  edges_masked_num++;
181  }
182  else {
183  r_edge_map[i] = -1;
184  }
185  }
186 
187  *r_edges_masked_num = edges_masked_num;
188 }
189 
191  Span<bool> vertex_mask,
192  MutableSpan<int> r_edge_map,
193  uint *r_edges_masked_num,
194  uint *r_verts_add_num)
195 {
196  BLI_assert(mesh->totedge == r_edge_map.size());
197 
198  uint edges_masked_num = 0;
199  uint verts_add_num = 0;
200  for (int i : IndexRange(mesh->totedge)) {
201  const MEdge &edge = mesh->medge[i];
202 
203  /* only add if both verts will be in new mesh */
204  bool v1 = vertex_mask[edge.v1];
205  bool v2 = vertex_mask[edge.v2];
206  if (v1 && v2) {
207  r_edge_map[i] = edges_masked_num;
208  edges_masked_num++;
209  }
210  else if (v1 != v2) {
211  r_edge_map[i] = -2;
212  verts_add_num++;
213  }
214  else {
215  r_edge_map[i] = -1;
216  }
217  }
218 
219  edges_masked_num += verts_add_num;
220  *r_edges_masked_num = edges_masked_num;
221  *r_verts_add_num = verts_add_num;
222 }
223 
224 static void computed_masked_polygons(const Mesh *mesh,
225  Span<bool> vertex_mask,
226  Vector<int> &r_masked_poly_indices,
227  Vector<int> &r_loop_starts,
228  uint *r_polys_masked_num,
229  uint *r_loops_masked_num)
230 {
231  BLI_assert(mesh->totvert == vertex_mask.size());
232 
233  r_masked_poly_indices.reserve(mesh->totpoly);
234  r_loop_starts.reserve(mesh->totpoly);
235 
236  uint loops_masked_num = 0;
237  for (int i : IndexRange(mesh->totpoly)) {
238  const MPoly &poly_src = mesh->mpoly[i];
239 
240  bool all_verts_in_mask = true;
241  Span<MLoop> loops_src(&mesh->mloop[poly_src.loopstart], poly_src.totloop);
242  for (const MLoop &loop : loops_src) {
243  if (!vertex_mask[loop.v]) {
244  all_verts_in_mask = false;
245  break;
246  }
247  }
248 
249  if (all_verts_in_mask) {
250  r_masked_poly_indices.append_unchecked(i);
251  r_loop_starts.append_unchecked(loops_masked_num);
252  loops_masked_num += poly_src.totloop;
253  }
254  }
255 
256  *r_polys_masked_num = r_masked_poly_indices.size();
257  *r_loops_masked_num = loops_masked_num;
258 }
259 
261  Span<bool> vertex_mask,
262  uint verts_add_num,
263  uint loops_masked_num,
264  Vector<int> &r_masked_poly_indices,
265  Vector<int> &r_loop_starts,
266  uint *r_edges_add_num,
267  uint *r_polys_add_num,
268  uint *r_loops_add_num)
269 {
270  BLI_assert(mesh->totvert == vertex_mask.size());
271 
272  /* Can't really know ahead of time how much space to use exactly. Estimate limit instead. */
273  /* NOTE: this reserve can only lift the capacity if there are ngons, which get split. */
274  r_masked_poly_indices.reserve(r_masked_poly_indices.size() + verts_add_num);
275  r_loop_starts.reserve(r_loop_starts.size() + verts_add_num);
276 
277  uint edges_add_num = 0;
278  uint polys_add_num = 0;
279  uint loops_add_num = 0;
280  for (int i : IndexRange(mesh->totpoly)) {
281  const MPoly &poly_src = mesh->mpoly[i];
282 
283  int in_count = 0;
284  int start = -1;
285  int dst_totloop = -1;
286  Span<MLoop> loops_src(&mesh->mloop[poly_src.loopstart], poly_src.totloop);
287  for (const int j : loops_src.index_range()) {
288  const MLoop &loop = loops_src[j];
289  if (vertex_mask[loop.v]) {
290  in_count++;
291  }
292  else if (start == -1) {
293  start = j;
294  }
295  }
296  if (0 < in_count && in_count < poly_src.totloop) {
297  /* Ring search starting at a vertex which is not included in the mask. */
298  const MLoop *last_loop = &loops_src[start];
299  bool v_loop_in_mask_last = vertex_mask[last_loop->v];
300  for (const int j : loops_src.index_range()) {
301  const MLoop &loop = loops_src[(start + 1 + j) % poly_src.totloop];
302  const bool v_loop_in_mask = vertex_mask[loop.v];
303  if (v_loop_in_mask && !v_loop_in_mask_last) {
304  dst_totloop = 3;
305  }
306  else if (!v_loop_in_mask && v_loop_in_mask_last) {
307  BLI_assert(dst_totloop > 2);
308  r_masked_poly_indices.append(i);
309  r_loop_starts.append(loops_masked_num + loops_add_num);
310  loops_add_num += dst_totloop;
311  polys_add_num++;
312  edges_add_num++;
313  dst_totloop = -1;
314  }
315  else if (v_loop_in_mask && v_loop_in_mask_last) {
316  BLI_assert(dst_totloop > 2);
317  dst_totloop++;
318  }
319  last_loop = &loop;
320  v_loop_in_mask_last = v_loop_in_mask;
321  }
322  }
323  }
324 
325  *r_edges_add_num = edges_add_num;
326  *r_polys_add_num = polys_add_num;
327  *r_loops_add_num = loops_add_num;
328 }
329 
330 static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh,
331  Mesh &dst_mesh,
332  Span<int> vertex_map)
333 {
334  BLI_assert(src_mesh.totvert == vertex_map.size());
335  for (const int i_src : vertex_map.index_range()) {
336  const int i_dst = vertex_map[i_src];
337  if (i_dst == -1) {
338  continue;
339  }
340 
341  const MVert &v_src = src_mesh.mvert[i_src];
342  MVert &v_dst = dst_mesh.mvert[i_dst];
343 
344  v_dst = v_src;
345  CustomData_copy_data(&src_mesh.vdata, &dst_mesh.vdata, i_src, i_dst, 1);
346  }
347 }
348 
350  const MDeformVert *dvert, int defgrp_index, float threshold, uint v1, uint v2)
351 {
352  /* NOTE: this calculation is done twice for every vertex,
353  * instead of storing it the first time and then reusing it. */
354  float value1 = BKE_defvert_find_weight(&dvert[v1], defgrp_index);
355  float value2 = BKE_defvert_find_weight(&dvert[v2], defgrp_index);
356  return (threshold - value1) / (value2 - value1);
357 }
358 
359 static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh,
360  Mesh &dst_mesh,
361  Span<bool> vertex_mask,
362  Span<int> vertex_map,
363  const MDeformVert *dvert,
364  int defgrp_index,
365  float threshold,
366  uint edges_masked_num,
367  uint verts_add_num,
368  MutableSpan<int> r_edge_map)
369 {
370  BLI_assert(src_mesh.totvert == vertex_mask.size());
371  BLI_assert(src_mesh.totedge == r_edge_map.size());
372 
373  uint vert_index = dst_mesh.totvert - verts_add_num;
374  uint edge_index = edges_masked_num - verts_add_num;
375  for (int i_src : IndexRange(src_mesh.totedge)) {
376  if (r_edge_map[i_src] != -1) {
377  int i_dst = r_edge_map[i_src];
378  if (i_dst == -2) {
379  i_dst = edge_index;
380  }
381  const MEdge &e_src = src_mesh.medge[i_src];
382  MEdge &e_dst = dst_mesh.medge[i_dst];
383 
384  CustomData_copy_data(&src_mesh.edata, &dst_mesh.edata, i_src, i_dst, 1);
385  e_dst = e_src;
386  e_dst.v1 = vertex_map[e_src.v1];
387  e_dst.v2 = vertex_map[e_src.v2];
388  }
389  if (r_edge_map[i_src] == -2) {
390  const int i_dst = edge_index++;
391  r_edge_map[i_src] = i_dst;
392  const MEdge &e_src = src_mesh.medge[i_src];
393  /* Cut destination edge and make v1 the new vertex. */
394  MEdge &e_dst = dst_mesh.medge[i_dst];
395  if (!vertex_mask[e_src.v1]) {
396  e_dst.v1 = vert_index;
397  }
398  else {
399  BLI_assert(!vertex_mask[e_src.v2]);
400  e_dst.v2 = e_dst.v1;
401  e_dst.v1 = vert_index;
402  }
403  /* Create the new vertex. */
404  float fac = get_interp_factor_from_vgroup(
405  dvert, defgrp_index, threshold, e_src.v1, e_src.v2);
406 
407  float weights[2] = {1.0f - fac, fac};
409  &src_mesh.vdata, &dst_mesh.vdata, (int *)&e_src.v1, weights, nullptr, 2, vert_index);
410  MVert &v = dst_mesh.mvert[vert_index];
411  MVert &v1 = src_mesh.mvert[e_src.v1];
412  MVert &v2 = src_mesh.mvert[e_src.v2];
413 
414  interp_v3_v3v3(v.co, v1.co, v2.co, fac);
415  vert_index++;
416  }
417  }
418  BLI_assert(vert_index == dst_mesh.totvert);
419  BLI_assert(edge_index == edges_masked_num);
420 }
421 
422 static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
423  Mesh &dst_mesh,
424  Span<int> vertex_map,
425  Span<int> edge_map)
426 {
427  BLI_assert(src_mesh.totvert == vertex_map.size());
428  BLI_assert(src_mesh.totedge == edge_map.size());
429  for (const int i_src : IndexRange(src_mesh.totedge)) {
430  const int i_dst = edge_map[i_src];
431  if (ELEM(i_dst, -1, -2)) {
432  continue;
433  }
434 
435  const MEdge &e_src = src_mesh.medge[i_src];
436  MEdge &e_dst = dst_mesh.medge[i_dst];
437 
438  CustomData_copy_data(&src_mesh.edata, &dst_mesh.edata, i_src, i_dst, 1);
439  e_dst = e_src;
440  e_dst.v1 = vertex_map[e_src.v1];
441  e_dst.v2 = vertex_map[e_src.v2];
442  }
443 }
444 
445 static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
446  Mesh &dst_mesh,
447  Span<int> vertex_map,
448  Span<int> edge_map,
449  Span<int> masked_poly_indices,
450  Span<int> new_loop_starts,
451  int polys_masked_num)
452 {
453  for (const int i_dst : IndexRange(polys_masked_num)) {
454  const int i_src = masked_poly_indices[i_dst];
455 
456  const MPoly &mp_src = src_mesh.mpoly[i_src];
457  MPoly &mp_dst = dst_mesh.mpoly[i_dst];
458  const int i_ml_src = mp_src.loopstart;
459  const int i_ml_dst = new_loop_starts[i_dst];
460 
461  CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1);
462  CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src, i_ml_dst, mp_src.totloop);
463 
464  const MLoop *ml_src = src_mesh.mloop + i_ml_src;
465  MLoop *ml_dst = dst_mesh.mloop + i_ml_dst;
466 
467  mp_dst = mp_src;
468  mp_dst.loopstart = i_ml_dst;
469  for (int i : IndexRange(mp_src.totloop)) {
470  ml_dst[i].v = vertex_map[ml_src[i].v];
471  ml_dst[i].e = edge_map[ml_src[i].e];
472  }
473  }
474 }
475 
476 static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh,
477  Mesh &dst_mesh,
478  Span<bool> vertex_mask,
479  Span<int> vertex_map,
480  Span<int> edge_map,
481  const MDeformVert *dvert,
482  int defgrp_index,
483  float threshold,
484  Span<int> masked_poly_indices,
485  Span<int> new_loop_starts,
486  int polys_masked_num,
487  int edges_add_num)
488 {
489  int edge_index = dst_mesh.totedge - edges_add_num;
490  int sub_poly_index = 0;
491  int last_i_src = -1;
492  for (const int i_dst :
493  IndexRange(polys_masked_num, masked_poly_indices.size() - polys_masked_num)) {
494  const int i_src = masked_poly_indices[i_dst];
495  if (i_src == last_i_src) {
496  sub_poly_index++;
497  }
498  else {
499  sub_poly_index = 0;
500  last_i_src = i_src;
501  }
502 
503  const MPoly &mp_src = src_mesh.mpoly[i_src];
504  MPoly &mp_dst = dst_mesh.mpoly[i_dst];
505  const int i_ml_src = mp_src.loopstart;
506  int i_ml_dst = new_loop_starts[i_dst];
507  const int mp_totloop = (i_dst + 1 < new_loop_starts.size() ? new_loop_starts[i_dst + 1] :
508  dst_mesh.totloop) -
509  i_ml_dst;
510 
511  CustomData_copy_data(&src_mesh.pdata, &dst_mesh.pdata, i_src, i_dst, 1);
512 
513  mp_dst = mp_src;
514  mp_dst.loopstart = i_ml_dst;
515  mp_dst.totloop = mp_totloop;
516 
517  /* Ring search starting at a vertex which is not included in the mask. */
518  int start = -sub_poly_index - 1;
519  bool skip = false;
520  Span<MLoop> loops_src(&src_mesh.mloop[i_ml_src], mp_src.totloop);
521  for (const int j : loops_src.index_range()) {
522  if (!vertex_mask[loops_src[j].v]) {
523  if (start == -1) {
524  start = j;
525  break;
526  }
527  if (!skip) {
528  skip = true;
529  }
530  }
531  else if (skip) {
532  skip = false;
533  start++;
534  }
535  }
536 
537  BLI_assert(start >= 0);
538  BLI_assert(edge_index < dst_mesh.totedge);
539 
540  const MLoop *last_loop = &loops_src[start];
541  bool v_loop_in_mask_last = vertex_mask[last_loop->v];
542  int last_index = start;
543  for (const int j : loops_src.index_range()) {
544  const int index = (start + 1 + j) % mp_src.totloop;
545  const MLoop &loop = loops_src[index];
546  const bool v_loop_in_mask = vertex_mask[loop.v];
547  if (v_loop_in_mask && !v_loop_in_mask_last) {
548  /* Start new cut. */
549  float fac = get_interp_factor_from_vgroup(
550  dvert, defgrp_index, threshold, last_loop->v, loop.v);
551  float weights[2] = {1.0f - fac, fac};
552  int indices[2] = {i_ml_src + last_index, i_ml_src + index};
554  &src_mesh.ldata, &dst_mesh.ldata, indices, weights, nullptr, 2, i_ml_dst);
555  MLoop &cut_dst_loop = dst_mesh.mloop[i_ml_dst];
556  cut_dst_loop.e = edge_map[last_loop->e];
557  cut_dst_loop.v = dst_mesh.medge[cut_dst_loop.e].v1;
558  i_ml_dst++;
559 
560  CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1);
561  MLoop &next_dst_loop = dst_mesh.mloop[i_ml_dst];
562  next_dst_loop.v = vertex_map[loop.v];
563  next_dst_loop.e = edge_map[loop.e];
564  i_ml_dst++;
565  }
566  else if (!v_loop_in_mask && v_loop_in_mask_last) {
567  BLI_assert(i_ml_dst != mp_dst.loopstart);
568  /* End active cut. */
569  float fac = get_interp_factor_from_vgroup(
570  dvert, defgrp_index, threshold, last_loop->v, loop.v);
571  float weights[2] = {1.0f - fac, fac};
572  int indices[2] = {i_ml_src + last_index, i_ml_src + index};
574  &src_mesh.ldata, &dst_mesh.ldata, indices, weights, nullptr, 2, i_ml_dst);
575  MLoop &cut_dst_loop = dst_mesh.mloop[i_ml_dst];
576  cut_dst_loop.e = edge_index;
577  cut_dst_loop.v = dst_mesh.medge[edge_map[last_loop->e]].v1;
578  i_ml_dst++;
579 
580  /* Create closing edge. */
581  MEdge &cut_edge = dst_mesh.medge[edge_index];
582  cut_edge.v1 = dst_mesh.mloop[mp_dst.loopstart].v;
583  cut_edge.v2 = cut_dst_loop.v;
584  BLI_assert(cut_edge.v1 != cut_edge.v2);
585  cut_edge.flag = ME_EDGEDRAW | ME_EDGERENDER;
586  edge_index++;
587 
588  /* Only handle one of the cuts per iteration. */
589  break;
590  }
591  else if (v_loop_in_mask && v_loop_in_mask_last) {
592  BLI_assert(i_ml_dst != mp_dst.loopstart);
593  /* Extend active poly. */
594  CustomData_copy_data(&src_mesh.ldata, &dst_mesh.ldata, i_ml_src + index, i_ml_dst, 1);
595  MLoop &dst_loop = dst_mesh.mloop[i_ml_dst];
596  dst_loop.v = vertex_map[loop.v];
597  dst_loop.e = edge_map[loop.e];
598  i_ml_dst++;
599  }
600  last_loop = &loop;
601  last_index = index;
602  v_loop_in_mask_last = v_loop_in_mask;
603  }
604  BLI_assert(mp_dst.loopstart + mp_dst.totloop == i_ml_dst);
605  }
606  BLI_assert(edge_index == dst_mesh.totedge);
607 }
608 
609 /* Components of the algorithm:
610  * 1. Figure out which vertices should be present in the output mesh.
611  * 2. Find edges and polygons only using those vertices.
612  * 3. Create a new mesh that only uses the found vertices, edges and polygons.
613  */
615 {
616  MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md);
617  const bool invert_mask = mmd->flag & MOD_MASK_INV;
618  const bool use_interpolation = mmd->mode == MOD_MASK_MODE_VGROUP &&
619  (mmd->flag & MOD_MASK_SMOOTH);
620 
621  /* Return empty or input mesh when there are no vertex groups. */
622  const MDeformVert *dvert = (const MDeformVert *)CustomData_get_layer(&mesh->vdata,
624  if (dvert == nullptr) {
625  return invert_mask ? mesh : BKE_mesh_new_nomain_from_template(mesh, 0, 0, 0, 0, 0);
626  }
627 
628  /* Quick test to see if we can return early. */
629  if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (mesh->totvert == 0) ||
631  return mesh;
632  }
633 
634  int defgrp_index = -1;
635 
636  Array<bool> vertex_mask;
637  if (mmd->mode == MOD_MASK_MODE_ARM) {
638  Object *armature_ob = mmd->ob_arm;
639 
640  /* Return input mesh if there is no armature with bones. */
641  if (ELEM(nullptr, armature_ob, armature_ob->pose)) {
642  return mesh;
643  }
644 
645  vertex_mask = Array<bool>(mesh->totvert);
646  compute_vertex_mask__armature_mode(dvert, mesh, armature_ob, mmd->threshold, vertex_mask);
647  }
648  else {
650  defgrp_index = BKE_id_defgroup_name_index(&mesh->id, mmd->vgroup);
651 
652  /* Return input mesh if the vertex group does not exist. */
653  if (defgrp_index == -1) {
654  return mesh;
655  }
656 
657  vertex_mask = Array<bool>(mesh->totvert);
658  compute_vertex_mask__vertex_group_mode(dvert, defgrp_index, mmd->threshold, vertex_mask);
659  }
660 
661  if (invert_mask) {
662  invert_boolean_array(vertex_mask);
663  }
664 
665  Array<int> vertex_map(mesh->totvert);
666  uint verts_masked_num;
667  compute_masked_vertices(vertex_mask, vertex_map, &verts_masked_num);
668 
669  Array<int> edge_map(mesh->totedge);
670  uint edges_masked_num;
671  uint verts_add_num;
672  if (use_interpolation) {
673  computed_masked_edges_smooth(mesh, vertex_mask, edge_map, &edges_masked_num, &verts_add_num);
674  }
675  else {
676  computed_masked_edges(mesh, vertex_mask, edge_map, &edges_masked_num);
677  verts_add_num = 0;
678  }
679 
680  Vector<int> masked_poly_indices;
681  Vector<int> new_loop_starts;
682  uint polys_masked_num;
683  uint loops_masked_num;
685  vertex_mask,
686  masked_poly_indices,
687  new_loop_starts,
688  &polys_masked_num,
689  &loops_masked_num);
690 
691  uint edges_add_num = 0;
692  uint polys_add_num = 0;
693  uint loops_add_num = 0;
694  if (use_interpolation) {
696  vertex_mask,
697  verts_add_num,
698  loops_masked_num,
699  masked_poly_indices,
700  new_loop_starts,
701  &edges_add_num,
702  &polys_add_num,
703  &loops_add_num);
704  }
705 
707  verts_masked_num + verts_add_num,
708  edges_masked_num + edges_add_num,
709  0,
710  loops_masked_num + loops_add_num,
711  polys_masked_num + polys_add_num);
712 
714  if (use_interpolation) {
716  *result,
717  vertex_mask,
718  vertex_map,
719  dvert,
720  defgrp_index,
721  mmd->threshold,
722  edges_masked_num,
723  verts_add_num,
724  edge_map);
725  }
726  else {
727  copy_masked_edges_to_new_mesh(*mesh, *result, vertex_map, edge_map);
728  }
730  *result,
731  vertex_map,
732  edge_map,
733  masked_poly_indices,
734  new_loop_starts,
735  polys_masked_num);
736  if (use_interpolation) {
738  *result,
739  vertex_mask,
740  vertex_map,
741  edge_map,
742  dvert,
743  defgrp_index,
744  mmd->threshold,
745  masked_poly_indices,
746  new_loop_starts,
747  polys_masked_num,
748  edges_add_num);
749  }
750 
752 
753  return result;
754 }
755 
756 static bool isDisabled(const struct Scene *UNUSED(scene),
757  ModifierData *md,
758  bool UNUSED(useRenderParams))
759 {
760  MaskModifierData *mmd = reinterpret_cast<MaskModifierData *>(md);
761 
762  /* The object type check is only needed here in case we have a placeholder
763  * object assigned (because the library containing the armature is missing).
764  *
765  * In other cases it should be impossible to have a type mismatch.
766  */
767  return mmd->ob_arm && mmd->ob_arm->type != OB_ARMATURE;
768 }
769 
770 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
771 {
772  uiLayout *sub, *row;
773  uiLayout *layout = panel->layout;
774 
775  PointerRNA ob_ptr;
777 
778  int mode = RNA_enum_get(ptr, "mode");
779 
780  uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
781 
782  uiLayoutSetPropSep(layout, true);
783 
784  if (mode == MOD_MASK_MODE_ARM) {
785  row = uiLayoutRow(layout, true);
786  uiItemR(row, ptr, "armature", 0, nullptr, ICON_NONE);
787  sub = uiLayoutRow(row, true);
788  uiLayoutSetPropDecorate(sub, false);
789  uiItemR(sub, ptr, "invert_vertex_group", 0, "", ICON_ARROW_LEFTRIGHT);
790  }
791  else if (mode == MOD_MASK_MODE_VGROUP) {
792  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
793  uiItemR(layout, ptr, "use_smooth", 0, nullptr, ICON_NONE);
794  }
795 
796  uiItemR(layout, ptr, "threshold", 0, nullptr, ICON_NONE);
797 
798  modifier_panel_end(layout, ptr);
799 }
800 
801 static void panelRegister(ARegionType *region_type)
802 {
804 }
805 
807  /* name */ N_("Mask"),
808  /* structName */ "MaskModifierData",
809  /* structSize */ sizeof(MaskModifierData),
810  /* srna */ &RNA_MaskModifier,
812  /* flags */
815  /* icon */ ICON_MOD_MASK,
816 
817  /* copyData */ BKE_modifier_copydata_generic,
818 
819  /* deformVerts */ nullptr,
820  /* deformMatrices */ nullptr,
821  /* deformVertsEM */ nullptr,
822  /* deformMatricesEM */ nullptr,
823  /* modifyMesh */ modifyMesh,
824  /* modifyGeometrySet */ nullptr,
825 
826  /* initData */ initData,
827  /* requiredDataMask */ requiredDataMask,
828  /* freeData */ nullptr,
829  /* isDisabled */ isDisabled,
830  /* updateDepsgraph */ updateDepsgraph,
831  /* dependsOnTime */ nullptr,
832  /* dependsOnNormals */ nullptr,
833  /* foreachIDLink */ foreachIDLink,
834  /* foreachTexLink */ nullptr,
835  /* freeRuntimeData */ nullptr,
836  /* panelRegister */ panelRegister,
837  /* blendWrite */ nullptr,
838  /* blendRead */ nullptr,
839 };
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
CustomData interface, see also DNA_customdata_types.h.
void CustomData_interp(const struct CustomData *source, struct CustomData *dest, const int *src_indices, const float *weights, const float *sub_weights, int count, int dest_index)
void * CustomData_get_layer(const struct CustomData *data, int type)
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
int BKE_id_defgroup_name_index(const struct ID *id, const char *name)
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
void BKE_mesh_calc_edges_loose(struct Mesh *mesh)
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
ModifierTypeFlag
Definition: BKE_modifier.h:65
@ eModifierTypeFlag_SupportsMapping
Definition: BKE_modifier.h:68
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_Nonconstructive
Definition: BKE_modifier.h:49
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
@ DEG_OB_COMP_TRANSFORM
@ BONE_SELECTED
@ ARM_HAS_VIZ_DEPS
#define CD_MASK_MDEFORMVERT
@ CD_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ ME_EDGEDRAW
@ ME_EDGERENDER
struct MaskModifierData MaskModifierData
@ MOD_MASK_SMOOTH
@ MOD_MASK_INV
@ eModifierType_Mask
@ MOD_MASK_MODE_ARM
@ MOD_MASK_MODE_VGROUP
Object is a sort of wrapper for general info.
@ OB_ARMATURE
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
static void computed_masked_polygons(const Mesh *mesh, Span< bool > vertex_mask, Vector< int > &r_masked_poly_indices, Vector< int > &r_loop_starts, uint *r_polys_masked_num, uint *r_loops_masked_num)
Definition: MOD_mask.cc:224
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
Definition: MOD_mask.cc:80
static float get_interp_factor_from_vgroup(const MDeformVert *dvert, int defgrp_index, float threshold, uint v1, uint v2)
Definition: MOD_mask.cc:349
static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< int > vertex_map, Span< int > edge_map, Span< int > masked_poly_indices, Span< int > new_loop_starts, int polys_masked_num)
Definition: MOD_mask.cc:445
static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< bool > vertex_mask, Span< int > vertex_map, const MDeformVert *dvert, int defgrp_index, float threshold, uint edges_masked_num, uint verts_add_num, MutableSpan< int > r_edge_map)
Definition: MOD_mask.cc:359
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
Definition: MOD_mask.cc:756
static void compute_interpolated_polygons(const Mesh *mesh, Span< bool > vertex_mask, uint verts_add_num, uint loops_masked_num, Vector< int > &r_masked_poly_indices, Vector< int > &r_loop_starts, uint *r_edges_add_num, uint *r_polys_add_num, uint *r_loops_add_num)
Definition: MOD_mask.cc:260
static void compute_masked_vertices(Span< bool > vertex_mask, MutableSpan< int > r_vertex_map, uint *r_verts_masked_num)
Definition: MOD_mask.cc:146
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh)
Definition: MOD_mask.cc:614
static void requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks)
Definition: MOD_mask.cc:67
static void computed_masked_edges(const Mesh *mesh, Span< bool > vertex_mask, MutableSpan< int > r_edge_map, uint *r_edges_masked_num)
Definition: MOD_mask.cc:166
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
Definition: MOD_mask.cc:74
static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< bool > vertex_mask, Span< int > vertex_map, Span< int > edge_map, const MDeformVert *dvert, int defgrp_index, float threshold, Span< int > masked_poly_indices, Span< int > new_loop_starts, int polys_masked_num, int edges_add_num)
Definition: MOD_mask.cc:476
static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< int > vertex_map, Span< int > edge_map)
Definition: MOD_mask.cc:422
static void compute_vertex_mask__armature_mode(const MDeformVert *dvert, Mesh *mesh, Object *armature_ob, float threshold, MutableSpan< bool > r_vertex_mask)
Definition: MOD_mask.cc:94
static void compute_vertex_mask__vertex_group_mode(const MDeformVert *dvert, int defgrp_index, float threshold, MutableSpan< bool > r_vertex_mask)
Definition: MOD_mask.cc:128
static void invert_boolean_array(MutableSpan< bool > array)
Definition: MOD_mask.cc:139
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_mask.cc:770
static void initData(ModifierData *md)
Definition: MOD_mask.cc:58
static void panelRegister(ARegionType *region_type)
Definition: MOD_mask.cc:801
ModifierTypeInfo modifierType_Mask
Definition: MOD_mask.cc:806
static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< int > vertex_map)
Definition: MOD_mask.cc:330
static void computed_masked_edges_smooth(const Mesh *mesh, Span< bool > vertex_mask, MutableSpan< int > r_edge_map, uint *r_edges_masked_num, uint *r_verts_add_num)
Definition: MOD_mask.cc:190
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
#define C
Definition: RandGen.cpp:25
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_ITEM_R_EXPAND
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr int64_t size() const
Definition: BLI_span.hh:511
constexpr IndexRange index_range() const
Definition: BLI_span.hh:661
constexpr T get(int64_t index, const T &fallback) const
Definition: BLI_span.hh:324
constexpr int64_t size() const
Definition: BLI_span.hh:240
constexpr IndexRange index_range() const
Definition: BLI_span.hh:401
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
void append_unchecked(const T &value)
Definition: BLI_vector.hh:484
void reserve(const int64_t min_capacity)
Definition: BLI_vector.hh:340
Scene scene
ccl_gpu_kernel_postfix ccl_global float int int int int float threshold
ccl_gpu_kernel_postfix int ccl_global int * indices
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
float co[3]
Definition: bmesh_class.h:87
Definition: DNA_ID.h:368
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
struct Object * ob_arm
struct MEdge * medge
CustomData vdata
struct MVert * mvert
int totedge
ListBase vertex_group_names
int totvert
struct MLoop * mloop
CustomData pdata
int totpoly
CustomData edata
int totloop
struct MPoly * mpoly
CustomData ldata
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
struct bPose * pose
void * data
struct uiLayout * layout
struct Bone * bone
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480