Blender  V3.3
node_geo_delete_geometry.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "UI_interface.h"
4 #include "UI_resources.h"
5 
6 #include "BLI_array.hh"
7 
8 #include "DNA_mesh_types.h"
9 #include "DNA_meshdata_types.h"
10 
11 #include "BKE_attribute_math.hh"
12 #include "BKE_curves.hh"
13 #include "BKE_customdata.h"
14 #include "BKE_mesh.h"
15 #include "BKE_pointcloud.h"
16 
17 #include "node_geometry_util.hh"
18 
20 
22 
23 template<typename T>
25 {
26  for (const int i_out : mask.index_range()) {
27  r_data[i_out] = data[mask[i_out]];
28  }
29 }
30 
31 template<typename T>
33 {
34  for (const int i_src : index_map.index_range()) {
35  const int i_dst = index_map[i_src];
36  if (i_dst != -1) {
37  dst[i_dst] = src[i_src];
38  }
39  }
40 }
41 
46  const bke::AttributeAccessor src_attributes,
47  bke::MutableAttributeAccessor dst_attributes,
48  const Span<eAttrDomain> domains)
49 {
50  for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
51  const AttributeIDRef attribute_id = entry.key;
52  GAttributeReader attribute = src_attributes.lookup(attribute_id);
53  if (!attribute) {
54  continue;
55  }
56 
57  /* Only copy if it is on a domain we want. */
58  if (!domains.contains(attribute.domain)) {
59  continue;
60  }
61  const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
62 
63  GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
64  attribute_id, attribute.domain, data_type);
65 
66  if (!result_attribute) {
67  continue;
68  }
69 
70  attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
71  using T = decltype(dummy);
72  VArraySpan<T> span{attribute.varray.typed<T>()};
73  MutableSpan<T> out_span = result_attribute.span.typed<T>();
74  out_span.copy_from(span);
75  });
76  result_attribute.finish();
77  }
78 }
79 
85  const bke::AttributeAccessor src_attributes,
86  bke::MutableAttributeAccessor dst_attributes,
87  const eAttrDomain domain,
88  const IndexMask mask)
89 {
90  for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
91  const AttributeIDRef attribute_id = entry.key;
92  GAttributeReader attribute = src_attributes.lookup(attribute_id);
93  if (!attribute) {
94  continue;
95  }
96 
97  /* Only copy if it is on a domain we want. */
98  if (domain != attribute.domain) {
99  continue;
100  }
101  const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
102 
103  GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
104  attribute_id, attribute.domain, data_type);
105 
106  if (!result_attribute) {
107  continue;
108  }
109 
110  attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
111  using T = decltype(dummy);
112  VArraySpan<T> span{attribute.varray.typed<T>()};
113  MutableSpan<T> out_span = result_attribute.span.typed<T>();
114  copy_data_based_on_mask(span, out_span, mask);
115  });
116  result_attribute.finish();
117  }
118 }
119 
121  const bke::AttributeAccessor src_attributes,
122  bke::MutableAttributeAccessor dst_attributes,
123  const eAttrDomain domain,
124  const Span<int> index_map)
125 {
126  for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
127  const AttributeIDRef attribute_id = entry.key;
128  GAttributeReader attribute = src_attributes.lookup(attribute_id);
129  if (!attribute) {
130  continue;
131  }
132 
133  /* Only copy if it is on a domain we want. */
134  if (domain != attribute.domain) {
135  continue;
136  }
137  const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
138 
139  GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
140  attribute_id, attribute.domain, data_type);
141 
142  if (!result_attribute) {
143  continue;
144  }
145 
146  attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
147  using T = decltype(dummy);
148  VArraySpan<T> span{attribute.varray.typed<T>()};
149  MutableSpan<T> out_span = result_attribute.span.typed<T>();
150  copy_data_based_on_map(span, out_span, index_map);
151  });
152  result_attribute.finish();
153  }
154 }
155 
157  const bke::AttributeAccessor src_attributes,
158  bke::MutableAttributeAccessor dst_attributes,
159  const int selected_loops_num,
160  const Span<int> selected_poly_indices,
161  const Mesh &mesh_in)
162 {
164  indices.reserve(selected_loops_num);
165  for (const int src_poly_index : selected_poly_indices) {
166  const MPoly &src_poly = mesh_in.mpoly[src_poly_index];
167  const int src_loop_start = src_poly.loopstart;
168  const int tot_loop = src_poly.totloop;
169  for (const int i : IndexRange(tot_loop)) {
170  indices.append_unchecked(src_loop_start + i);
171  }
172  }
174  attributes, src_attributes, dst_attributes, ATTR_DOMAIN_CORNER, IndexMask(indices));
175 }
176 
177 static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh,
178  Mesh &dst_mesh,
179  Span<int> vertex_map)
180 {
181  BLI_assert(src_mesh.totvert == vertex_map.size());
182  for (const int i_src : vertex_map.index_range()) {
183  const int i_dst = vertex_map[i_src];
184  if (i_dst == -1) {
185  continue;
186  }
187 
188  const MVert &v_src = src_mesh.mvert[i_src];
189  MVert &v_dst = dst_mesh.mvert[i_dst];
190 
191  v_dst = v_src;
192  }
193 }
194 
195 static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span<int> edge_map)
196 {
197  BLI_assert(src_mesh.totedge == edge_map.size());
198  for (const int i_src : IndexRange(src_mesh.totedge)) {
199  const int i_dst = edge_map[i_src];
200  if (ELEM(i_dst, -1, -2)) {
201  continue;
202  }
203 
204  const MEdge &e_src = src_mesh.medge[i_src];
205  MEdge &e_dst = dst_mesh.medge[i_dst];
206 
207  e_dst = e_src;
208  e_dst.v1 = e_src.v1;
209  e_dst.v2 = e_src.v2;
210  }
211 }
212 
213 static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
214  Mesh &dst_mesh,
215  Span<int> vertex_map,
216  Span<int> edge_map)
217 {
218  BLI_assert(src_mesh.totvert == vertex_map.size());
219  BLI_assert(src_mesh.totedge == edge_map.size());
220  for (const int i_src : IndexRange(src_mesh.totedge)) {
221  const int i_dst = edge_map[i_src];
222  if (i_dst == -1) {
223  continue;
224  }
225 
226  const MEdge &e_src = src_mesh.medge[i_src];
227  MEdge &e_dst = dst_mesh.medge[i_dst];
228 
229  e_dst = e_src;
230  e_dst.v1 = vertex_map[e_src.v1];
231  e_dst.v2 = vertex_map[e_src.v2];
232  }
233 }
234 
235 /* Faces and edges changed but vertices are the same. */
236 static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
237  Mesh &dst_mesh,
238  Span<int> edge_map,
239  Span<int> masked_poly_indices,
240  Span<int> new_loop_starts)
241 {
242  for (const int i_dst : masked_poly_indices.index_range()) {
243  const int i_src = masked_poly_indices[i_dst];
244 
245  const MPoly &mp_src = src_mesh.mpoly[i_src];
246  MPoly &mp_dst = dst_mesh.mpoly[i_dst];
247  const int i_ml_src = mp_src.loopstart;
248  const int i_ml_dst = new_loop_starts[i_dst];
249 
250  const MLoop *ml_src = src_mesh.mloop + i_ml_src;
251  MLoop *ml_dst = dst_mesh.mloop + i_ml_dst;
252 
253  mp_dst = mp_src;
254  mp_dst.loopstart = i_ml_dst;
255  for (int i : IndexRange(mp_src.totloop)) {
256  ml_dst[i].v = ml_src[i].v;
257  ml_dst[i].e = edge_map[ml_src[i].e];
258  }
259  }
260 }
261 
262 /* Only faces changed. */
263 static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
264  Mesh &dst_mesh,
265  Span<int> masked_poly_indices,
266  Span<int> new_loop_starts)
267 {
268  for (const int i_dst : masked_poly_indices.index_range()) {
269  const int i_src = masked_poly_indices[i_dst];
270 
271  const MPoly &mp_src = src_mesh.mpoly[i_src];
272  MPoly &mp_dst = dst_mesh.mpoly[i_dst];
273  const int i_ml_src = mp_src.loopstart;
274  const int i_ml_dst = new_loop_starts[i_dst];
275 
276  const MLoop *ml_src = src_mesh.mloop + i_ml_src;
277  MLoop *ml_dst = dst_mesh.mloop + i_ml_dst;
278 
279  mp_dst = mp_src;
280  mp_dst.loopstart = i_ml_dst;
281  for (int i : IndexRange(mp_src.totloop)) {
282  ml_dst[i].v = ml_src[i].v;
283  ml_dst[i].e = ml_src[i].e;
284  }
285  }
286 }
287 
288 static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
289  Mesh &dst_mesh,
290  Span<int> vertex_map,
291  Span<int> edge_map,
292  Span<int> masked_poly_indices,
293  Span<int> new_loop_starts)
294 {
295  for (const int i_dst : masked_poly_indices.index_range()) {
296  const int i_src = masked_poly_indices[i_dst];
297 
298  const MPoly &mp_src = src_mesh.mpoly[i_src];
299  MPoly &mp_dst = dst_mesh.mpoly[i_dst];
300  const int i_ml_src = mp_src.loopstart;
301  const int i_ml_dst = new_loop_starts[i_dst];
302 
303  const MLoop *ml_src = src_mesh.mloop + i_ml_src;
304  MLoop *ml_dst = dst_mesh.mloop + i_ml_dst;
305 
306  mp_dst = mp_src;
307  mp_dst.loopstart = i_ml_dst;
308  for (int i : IndexRange(mp_src.totloop)) {
309  ml_dst[i].v = vertex_map[ml_src[i].v];
310  ml_dst[i].e = edge_map[ml_src[i].e];
311  }
312  }
313 }
314 
315 static void delete_curves_selection(GeometrySet &geometry_set,
316  const Field<bool> &selection_field,
317  const eAttrDomain selection_domain)
318 {
319  const CurveComponent &src_component = *geometry_set.get_component_for_read<CurveComponent>();
320  GeometryComponentFieldContext field_context{src_component, selection_domain};
321 
322  const int domain_num = src_component.attribute_domain_size(selection_domain);
323  fn::FieldEvaluator evaluator{field_context, domain_num};
324  evaluator.set_selection(selection_field);
325  evaluator.evaluate();
326  const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
327  if (selection.is_empty()) {
328  return;
329  }
330  if (selection.size() == domain_num) {
331  geometry_set.remove<CurveComponent>();
332  return;
333  }
334 
336  Curves &curves_id = *component.get_for_write();
338 
339  if (selection_domain == ATTR_DOMAIN_POINT) {
340  curves.remove_points(selection);
341  }
342  else if (selection_domain == ATTR_DOMAIN_CURVE) {
343  curves.remove_curves(selection);
344  }
345 }
346 
347 static void separate_point_cloud_selection(GeometrySet &geometry_set,
348  const Field<bool> &selection_field)
349 {
350  const PointCloudComponent &src_points =
352  GeometryComponentFieldContext field_context{src_points, ATTR_DOMAIN_POINT};
353 
354  fn::FieldEvaluator evaluator{field_context, src_points.attribute_domain_size(ATTR_DOMAIN_POINT)};
355  evaluator.set_selection(selection_field);
356  evaluator.evaluate();
357  const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
358  if (selection.is_empty()) {
359  geometry_set.replace_pointcloud(nullptr);
360  return;
361  }
362 
363  PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
364 
368 
373  selection);
374  geometry_set.replace_pointcloud(pointcloud);
375 }
376 
377 static void delete_selected_instances(GeometrySet &geometry_set,
378  const Field<bool> &selection_field)
379 {
381  GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE};
382 
383  fn::FieldEvaluator evaluator{field_context, instances.instances_num()};
384  evaluator.set_selection(selection_field);
385  evaluator.evaluate();
386  const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
387  if (selection.is_empty()) {
388  geometry_set.remove<InstancesComponent>();
389  return;
390  }
391 
392  instances.remove_instances(selection);
393 }
394 
396  MutableSpan<int> r_vertex_map,
397  int *r_selected_vertices_num)
398 {
399  BLI_assert(vertex_selection.size() == r_vertex_map.size());
400 
401  int selected_verts_num = 0;
402  for (const int i : r_vertex_map.index_range()) {
403  if (vertex_selection[i]) {
404  r_vertex_map[i] = selected_verts_num;
405  selected_verts_num++;
406  }
407  else {
408  r_vertex_map[i] = -1;
409  }
410  }
411 
412  *r_selected_vertices_num = selected_verts_num;
413 }
414 
416  const Span<bool> vertex_selection,
417  MutableSpan<int> r_edge_map,
418  int *r_selected_edges_num)
419 {
420  BLI_assert(mesh.totedge == r_edge_map.size());
421 
422  int selected_edges_num = 0;
423  for (const int i : IndexRange(mesh.totedge)) {
424  const MEdge &edge = mesh.medge[i];
425 
426  /* Only add the edge if both vertices will be in the new mesh. */
427  if (vertex_selection[edge.v1] && vertex_selection[edge.v2]) {
428  r_edge_map[i] = selected_edges_num;
429  selected_edges_num++;
430  }
431  else {
432  r_edge_map[i] = -1;
433  }
434  }
435 
436  *r_selected_edges_num = selected_edges_num;
437 }
438 
440  const Span<bool> vertex_selection,
441  Vector<int> &r_selected_poly_indices,
442  Vector<int> &r_loop_starts,
443  int *r_selected_polys_num,
444  int *r_selected_loops_num)
445 {
446  BLI_assert(mesh.totvert == vertex_selection.size());
447 
448  r_selected_poly_indices.reserve(mesh.totpoly);
449  r_loop_starts.reserve(mesh.totloop);
450 
451  int selected_loops_num = 0;
452  for (const int i : IndexRange(mesh.totpoly)) {
453  const MPoly &poly_src = mesh.mpoly[i];
454 
455  bool all_verts_in_selection = true;
456  Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop);
457  for (const MLoop &loop : loops_src) {
458  if (!vertex_selection[loop.v]) {
459  all_verts_in_selection = false;
460  break;
461  }
462  }
463 
464  if (all_verts_in_selection) {
465  r_selected_poly_indices.append_unchecked(i);
466  r_loop_starts.append_unchecked(selected_loops_num);
467  selected_loops_num += poly_src.totloop;
468  }
469  }
470 
471  *r_selected_polys_num = r_selected_poly_indices.size();
472  *r_selected_loops_num = selected_loops_num;
473 }
474 
480  const Mesh &mesh,
481  const Span<bool> edge_selection,
482  MutableSpan<int> r_vertex_map,
483  MutableSpan<int> r_edge_map,
484  int *r_selected_vertices_num,
485  int *r_selected_edges_num)
486 {
487  BLI_assert(mesh.totedge == edge_selection.size());
488 
489  int selected_edges_num = 0;
490  int selected_verts_num = 0;
491  for (const int i : IndexRange(mesh.totedge)) {
492  const MEdge &edge = mesh.medge[i];
493  if (edge_selection[i]) {
494  r_edge_map[i] = selected_edges_num;
495  selected_edges_num++;
496  if (r_vertex_map[edge.v1] == -1) {
497  r_vertex_map[edge.v1] = selected_verts_num;
498  selected_verts_num++;
499  }
500  if (r_vertex_map[edge.v2] == -1) {
501  r_vertex_map[edge.v2] = selected_verts_num;
502  selected_verts_num++;
503  }
504  }
505  else {
506  r_edge_map[i] = -1;
507  }
508  }
509 
510  *r_selected_vertices_num = selected_verts_num;
511  *r_selected_edges_num = selected_edges_num;
512 }
513 
518  const Span<bool> edge_selection,
519  MutableSpan<int> r_edge_map,
520  int *r_selected_edges_num)
521 {
522  BLI_assert(mesh.totedge == edge_selection.size());
523 
524  int selected_edges_num = 0;
525  for (const int i : IndexRange(mesh.totedge)) {
526  if (edge_selection[i]) {
527  r_edge_map[i] = selected_edges_num;
528  selected_edges_num++;
529  }
530  else {
531  r_edge_map[i] = -1;
532  }
533  }
534 
535  *r_selected_edges_num = selected_edges_num;
536 }
537 
543  const Span<bool> edge_selection,
544  Vector<int> &r_selected_poly_indices,
545  Vector<int> &r_loop_starts,
546  int *r_selected_polys_num,
547  int *r_selected_loops_num)
548 {
549  r_selected_poly_indices.reserve(mesh.totpoly);
550  r_loop_starts.reserve(mesh.totloop);
551 
552  int selected_loops_num = 0;
553  for (const int i : IndexRange(mesh.totpoly)) {
554  const MPoly &poly_src = mesh.mpoly[i];
555 
556  bool all_edges_in_selection = true;
557  Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop);
558  for (const MLoop &loop : loops_src) {
559  if (!edge_selection[loop.e]) {
560  all_edges_in_selection = false;
561  break;
562  }
563  }
564 
565  if (all_edges_in_selection) {
566  r_selected_poly_indices.append_unchecked(i);
567  r_loop_starts.append_unchecked(selected_loops_num);
568  selected_loops_num += poly_src.totloop;
569  }
570  }
571 
572  *r_selected_polys_num = r_selected_poly_indices.size();
573  *r_selected_loops_num = selected_loops_num;
574 }
575 
580  const Mesh &mesh,
581  const Span<bool> vertex_selection,
582  MutableSpan<int> r_edge_map,
583  Vector<int> &r_selected_poly_indices,
584  Vector<int> &r_loop_starts,
585  int *r_selected_edges_num,
586  int *r_selected_polys_num,
587  int *r_selected_loops_num)
588 {
589 
591  mesh, vertex_selection, r_edge_map, r_selected_edges_num);
592 
594  vertex_selection,
595  r_selected_poly_indices,
596  r_loop_starts,
597  r_selected_polys_num,
598  r_selected_loops_num);
599 }
600 
606  const Span<bool> vertex_selection,
607  MutableSpan<int> r_vertex_map,
608  MutableSpan<int> r_edge_map,
609  Vector<int> &r_selected_poly_indices,
610  Vector<int> &r_loop_starts,
611  int *r_selected_vertices_num,
612  int *r_selected_edges_num,
613  int *r_selected_polys_num,
614  int *r_selected_loops_num)
615 {
617  vertex_selection, r_vertex_map, r_selected_vertices_num);
618 
620  mesh, vertex_selection, r_edge_map, r_selected_edges_num);
621 
623  vertex_selection,
624  r_selected_poly_indices,
625  r_loop_starts,
626  r_selected_polys_num,
627  r_selected_loops_num);
628 }
629 
635  const Mesh &mesh,
636  const Span<bool> edge_selection,
637  MutableSpan<int> r_edge_map,
638  Vector<int> &r_selected_poly_indices,
639  Vector<int> &r_loop_starts,
640  int *r_selected_edges_num,
641  int *r_selected_polys_num,
642  int *r_selected_loops_num)
643 {
645  mesh, edge_selection, r_edge_map, r_selected_edges_num);
647  edge_selection,
648  r_selected_poly_indices,
649  r_loop_starts,
650  r_selected_polys_num,
651  r_selected_loops_num);
652 }
653 
659  const Span<bool> edge_selection,
660  MutableSpan<int> r_vertex_map,
661  MutableSpan<int> r_edge_map,
662  Vector<int> &r_selected_poly_indices,
663  Vector<int> &r_loop_starts,
664  int *r_selected_vertices_num,
665  int *r_selected_edges_num,
666  int *r_selected_polys_num,
667  int *r_selected_loops_num)
668 {
669  r_vertex_map.fill(-1);
671  edge_selection,
672  r_vertex_map,
673  r_edge_map,
674  r_selected_vertices_num,
675  r_selected_edges_num);
677  edge_selection,
678  r_selected_poly_indices,
679  r_loop_starts,
680  r_selected_polys_num,
681  r_selected_loops_num);
682 }
683 
688  const Span<bool> poly_selection,
689  Vector<int> &r_selected_poly_indices,
690  Vector<int> &r_loop_starts,
691  int *r_selected_polys_num,
692  int *r_selected_loops_num)
693 {
694  BLI_assert(mesh.totpoly == poly_selection.size());
695 
696  r_selected_poly_indices.reserve(mesh.totpoly);
697  r_loop_starts.reserve(mesh.totloop);
698 
699  int selected_loops_num = 0;
700  for (const int i : IndexRange(mesh.totpoly)) {
701  const MPoly &poly_src = mesh.mpoly[i];
702  /* We keep this one. */
703  if (poly_selection[i]) {
704  r_selected_poly_indices.append_unchecked(i);
705  r_loop_starts.append_unchecked(selected_loops_num);
706  selected_loops_num += poly_src.totloop;
707  }
708  }
709  *r_selected_polys_num = r_selected_poly_indices.size();
710  *r_selected_loops_num = selected_loops_num;
711 }
717  const Mesh &mesh,
718  const Span<bool> poly_selection,
719  MutableSpan<int> r_edge_map,
720  Vector<int> &r_selected_poly_indices,
721  Vector<int> &r_loop_starts,
722  int *r_selected_edges_num,
723  int *r_selected_polys_num,
724  int *r_selected_loops_num)
725 {
726  BLI_assert(mesh.totpoly == poly_selection.size());
727  BLI_assert(mesh.totedge == r_edge_map.size());
728  r_edge_map.fill(-1);
729 
730  r_selected_poly_indices.reserve(mesh.totpoly);
731  r_loop_starts.reserve(mesh.totloop);
732 
733  int selected_loops_num = 0;
734  int selected_edges_num = 0;
735  for (const int i : IndexRange(mesh.totpoly)) {
736  const MPoly &poly_src = mesh.mpoly[i];
737  /* We keep this one. */
738  if (poly_selection[i]) {
739  r_selected_poly_indices.append_unchecked(i);
740  r_loop_starts.append_unchecked(selected_loops_num);
741  selected_loops_num += poly_src.totloop;
742 
743  /* Add the vertices and the edges. */
744  Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop);
745  for (const MLoop &loop : loops_src) {
746  /* Check first if it has not yet been added. */
747  if (r_edge_map[loop.e] == -1) {
748  r_edge_map[loop.e] = selected_edges_num;
749  selected_edges_num++;
750  }
751  }
752  }
753  }
754  *r_selected_edges_num = selected_edges_num;
755  *r_selected_polys_num = r_selected_poly_indices.size();
756  *r_selected_loops_num = selected_loops_num;
757 }
758 
764  const Span<bool> poly_selection,
765  MutableSpan<int> r_vertex_map,
766  MutableSpan<int> r_edge_map,
767  Vector<int> &r_selected_poly_indices,
768  Vector<int> &r_loop_starts,
769  int *r_selected_vertices_num,
770  int *r_selected_edges_num,
771  int *r_selected_polys_num,
772  int *r_selected_loops_num)
773 {
774  BLI_assert(mesh.totpoly == poly_selection.size());
775  BLI_assert(mesh.totedge == r_edge_map.size());
776  r_vertex_map.fill(-1);
777  r_edge_map.fill(-1);
778 
779  r_selected_poly_indices.reserve(mesh.totpoly);
780  r_loop_starts.reserve(mesh.totloop);
781 
782  int selected_loops_num = 0;
783  int selected_verts_num = 0;
784  int selected_edges_num = 0;
785  for (const int i : IndexRange(mesh.totpoly)) {
786  const MPoly &poly_src = mesh.mpoly[i];
787  /* We keep this one. */
788  if (poly_selection[i]) {
789  r_selected_poly_indices.append_unchecked(i);
790  r_loop_starts.append_unchecked(selected_loops_num);
791  selected_loops_num += poly_src.totloop;
792 
793  /* Add the vertices and the edges. */
794  Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop);
795  for (const MLoop &loop : loops_src) {
796  /* Check first if it has not yet been added. */
797  if (r_vertex_map[loop.v] == -1) {
798  r_vertex_map[loop.v] = selected_verts_num;
799  selected_verts_num++;
800  }
801  if (r_edge_map[loop.e] == -1) {
802  r_edge_map[loop.e] = selected_edges_num;
803  selected_edges_num++;
804  }
805  }
806  }
807  }
808  *r_selected_vertices_num = selected_verts_num;
809  *r_selected_edges_num = selected_edges_num;
810  *r_selected_polys_num = r_selected_poly_indices.size();
811  *r_selected_loops_num = selected_loops_num;
812 }
813 
817 static void do_mesh_separation(GeometrySet &geometry_set,
818  const Mesh &mesh_in,
819  const Span<bool> selection,
820  const eAttrDomain domain,
822 {
823  /* Needed in all cases. */
824  Vector<int> selected_poly_indices;
825  Vector<int> new_loop_starts;
826  int selected_polys_num = 0;
827  int selected_loops_num = 0;
828 
829  Mesh *mesh_out;
830 
833  {GEO_COMPONENT_TYPE_MESH}, GEO_COMPONENT_TYPE_MESH, false, attributes);
834 
835  switch (mode) {
837  Array<int> vertex_map(mesh_in.totvert);
838  int selected_verts_num = 0;
839 
840  Array<int> edge_map(mesh_in.totedge);
841  int selected_edges_num = 0;
842 
843  /* Fill all the maps based on the selection. */
844  switch (domain) {
845  case ATTR_DOMAIN_POINT:
847  selection,
848  vertex_map,
849  edge_map,
850  selected_poly_indices,
851  new_loop_starts,
852  &selected_verts_num,
853  &selected_edges_num,
854  &selected_polys_num,
855  &selected_loops_num);
856  break;
857  case ATTR_DOMAIN_EDGE:
859  selection,
860  vertex_map,
861  edge_map,
862  selected_poly_indices,
863  new_loop_starts,
864  &selected_verts_num,
865  &selected_edges_num,
866  &selected_polys_num,
867  &selected_loops_num);
868  break;
869  case ATTR_DOMAIN_FACE:
871  selection,
872  vertex_map,
873  edge_map,
874  selected_poly_indices,
875  new_loop_starts,
876  &selected_verts_num,
877  &selected_edges_num,
878  &selected_polys_num,
879  &selected_loops_num);
880  break;
881  default:
883  break;
884  }
885  mesh_out = BKE_mesh_new_nomain_from_template(&mesh_in,
886  selected_verts_num,
887  selected_edges_num,
888  0,
889  selected_loops_num,
890  selected_polys_num);
891 
892  /* Copy the selected parts of the mesh over to the new mesh. */
893  copy_masked_vertices_to_new_mesh(mesh_in, *mesh_out, vertex_map);
894  copy_masked_edges_to_new_mesh(mesh_in, *mesh_out, vertex_map, edge_map);
896  mesh_in, *mesh_out, vertex_map, edge_map, selected_poly_indices, new_loop_starts);
897 
898  /* Copy attributes. */
899  copy_attributes_based_on_map(attributes,
900  bke::mesh_attributes(mesh_in),
903  vertex_map);
904  copy_attributes_based_on_map(attributes,
905  bke::mesh_attributes(mesh_in),
908  edge_map);
910  bke::mesh_attributes(mesh_in),
913  IndexMask(Vector<int64_t>(selected_poly_indices.as_span())));
914  copy_face_corner_attributes(attributes,
915  bke::mesh_attributes(mesh_in),
917  selected_loops_num,
918  selected_poly_indices,
919  mesh_in);
920  break;
921  }
923  Array<int> edge_map(mesh_in.totedge);
924  int selected_edges_num = 0;
925 
926  /* Fill all the maps based on the selection. */
927  switch (domain) {
928  case ATTR_DOMAIN_POINT:
930  selection,
931  edge_map,
932  selected_poly_indices,
933  new_loop_starts,
934  &selected_edges_num,
935  &selected_polys_num,
936  &selected_loops_num);
937  break;
938  case ATTR_DOMAIN_EDGE:
940  selection,
941  edge_map,
942  selected_poly_indices,
943  new_loop_starts,
944  &selected_edges_num,
945  &selected_polys_num,
946  &selected_loops_num);
947  break;
948  case ATTR_DOMAIN_FACE:
950  selection,
951  edge_map,
952  selected_poly_indices,
953  new_loop_starts,
954  &selected_edges_num,
955  &selected_polys_num,
956  &selected_loops_num);
957  break;
958  default:
960  break;
961  }
962  mesh_out = BKE_mesh_new_nomain_from_template(&mesh_in,
963  mesh_in.totvert,
964  selected_edges_num,
965  0,
966  selected_loops_num,
967  selected_polys_num);
968 
969  /* Copy the selected parts of the mesh over to the new mesh. */
970  memcpy(mesh_out->mvert, mesh_in.mvert, mesh_in.totvert * sizeof(MVert));
971  copy_masked_edges_to_new_mesh(mesh_in, *mesh_out, edge_map);
973  mesh_in, *mesh_out, edge_map, selected_poly_indices, new_loop_starts);
974 
975  /* Copy attributes. */
976  copy_attributes(attributes,
977  bke::mesh_attributes(mesh_in),
980  copy_attributes_based_on_map(attributes,
981  bke::mesh_attributes(mesh_in),
984  edge_map);
986  bke::mesh_attributes(mesh_in),
989  IndexMask(Vector<int64_t>(selected_poly_indices.as_span())));
990  copy_face_corner_attributes(attributes,
991  bke::mesh_attributes(mesh_in),
993  selected_loops_num,
994  selected_poly_indices,
995  mesh_in);
996  break;
997  }
999  /* Fill all the maps based on the selection. */
1000  switch (domain) {
1001  case ATTR_DOMAIN_POINT:
1003  selection,
1004  selected_poly_indices,
1005  new_loop_starts,
1006  &selected_polys_num,
1007  &selected_loops_num);
1008  break;
1009  case ATTR_DOMAIN_EDGE:
1011  selection,
1012  selected_poly_indices,
1013  new_loop_starts,
1014  &selected_polys_num,
1015  &selected_loops_num);
1016  break;
1017  case ATTR_DOMAIN_FACE:
1019  selection,
1020  selected_poly_indices,
1021  new_loop_starts,
1022  &selected_polys_num,
1023  &selected_loops_num);
1024  break;
1025  default:
1027  break;
1028  }
1030  &mesh_in, mesh_in.totvert, mesh_in.totedge, 0, selected_loops_num, selected_polys_num);
1031 
1032  /* Copy the selected parts of the mesh over to the new mesh. */
1033  memcpy(mesh_out->mvert, mesh_in.mvert, mesh_in.totvert * sizeof(MVert));
1034  memcpy(mesh_out->medge, mesh_in.medge, mesh_in.totedge * sizeof(MEdge));
1035  copy_masked_polys_to_new_mesh(mesh_in, *mesh_out, selected_poly_indices, new_loop_starts);
1036 
1037  /* Copy attributes. */
1038  copy_attributes(attributes,
1039  bke::mesh_attributes(mesh_in),
1040  bke::mesh_attributes_for_write(*mesh_out),
1042  copy_attributes_based_on_mask(attributes,
1043  bke::mesh_attributes(mesh_in),
1044  bke::mesh_attributes_for_write(*mesh_out),
1046  IndexMask(Vector<int64_t>(selected_poly_indices.as_span())));
1047  copy_face_corner_attributes(attributes,
1048  bke::mesh_attributes(mesh_in),
1049  bke::mesh_attributes_for_write(*mesh_out),
1050  selected_loops_num,
1051  selected_poly_indices,
1052  mesh_in);
1053  break;
1054  }
1055  }
1056 
1057  BKE_mesh_calc_edges_loose(mesh_out);
1058  geometry_set.replace_mesh(mesh_out);
1059 }
1060 
1061 static void separate_mesh_selection(GeometrySet &geometry_set,
1062  const Field<bool> &selection_field,
1063  const eAttrDomain selection_domain,
1064  const GeometryNodeDeleteGeometryMode mode)
1065 {
1066  const MeshComponent &src_component = *geometry_set.get_component_for_read<MeshComponent>();
1067  GeometryComponentFieldContext field_context{src_component, selection_domain};
1068 
1069  fn::FieldEvaluator evaluator{field_context,
1070  src_component.attribute_domain_size(selection_domain)};
1071  evaluator.add(selection_field);
1072  evaluator.evaluate();
1073  const VArray<bool> selection = evaluator.get_evaluated<bool>(0);
1074  /* Check if there is anything to delete. */
1075  if (selection.is_empty() || (selection.is_single() && selection.get_internal_single())) {
1076  return;
1077  }
1078 
1079  const VArraySpan<bool> selection_span{selection};
1080 
1082  geometry_set, *src_component.get_for_read(), selection_span, selection_domain, mode);
1083 }
1084 
1085 } // namespace blender::nodes::node_geo_delete_geometry_cc
1086 
1087 namespace blender::nodes {
1088 
1089 void separate_geometry(GeometrySet &geometry_set,
1090  const eAttrDomain domain,
1091  const GeometryNodeDeleteGeometryMode mode,
1092  const Field<bool> &selection_field,
1093  bool &r_is_error)
1094 {
1095  namespace file_ns = blender::nodes::node_geo_delete_geometry_cc;
1096 
1097  bool some_valid_domain = false;
1098  if (geometry_set.has_pointcloud()) {
1099  if (domain == ATTR_DOMAIN_POINT) {
1100  file_ns::separate_point_cloud_selection(geometry_set, selection_field);
1101  some_valid_domain = true;
1102  }
1103  }
1104  if (geometry_set.has_mesh()) {
1106  file_ns::separate_mesh_selection(geometry_set, selection_field, domain, mode);
1107  some_valid_domain = true;
1108  }
1109  }
1110  if (geometry_set.has_curves()) {
1111  if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE)) {
1113  geometry_set, fn::invert_boolean_field(selection_field), domain);
1114  some_valid_domain = true;
1115  }
1116  }
1117  if (geometry_set.has_instances()) {
1118  if (domain == ATTR_DOMAIN_INSTANCE) {
1119  file_ns::delete_selected_instances(geometry_set, selection_field);
1120  some_valid_domain = true;
1121  }
1122  }
1123  r_is_error = !some_valid_domain && geometry_set.has_realized_data();
1124 }
1125 
1126 } // namespace blender::nodes
1127 
1129 
1131 
1133 {
1134  b.add_input<decl::Geometry>(N_("Geometry"));
1135  b.add_input<decl::Bool>(N_("Selection"))
1136  .default_value(true)
1137  .hide_value()
1138  .supports_field()
1139  .description(N_("The parts of the geometry to be deleted"));
1140  b.add_output<decl::Geometry>(N_("Geometry"));
1141 }
1142 
1143 static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1144 {
1145  const bNode *node = static_cast<bNode *>(ptr->data);
1146  const NodeGeometryDeleteGeometry &storage = node_storage(*node);
1147  const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain);
1148 
1149  uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
1150  /* Only show the mode when it is relevant. */
1152  uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
1153  }
1154 }
1155 
1157 {
1158  NodeGeometryDeleteGeometry *data = MEM_cnew<NodeGeometryDeleteGeometry>(__func__);
1159  data->domain = ATTR_DOMAIN_POINT;
1161 
1162  node->storage = data;
1163 }
1164 
1166 {
1167  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
1168 
1169  /* The node's input is a selection of elements that should be deleted, but the code is
1170  * implemented as a separation operation that copies the selected elements to a new geometry.
1171  * Invert the selection to avoid the need to keep track of both cases in the code. */
1172  const Field<bool> selection = fn::invert_boolean_field(
1173  params.extract_input<Field<bool>>("Selection"));
1174 
1175  const NodeGeometryDeleteGeometry &storage = node_storage(params.node());
1176  const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain);
1178 
1179  if (domain == ATTR_DOMAIN_INSTANCE) {
1180  bool is_error;
1181  separate_geometry(geometry_set, domain, mode, selection, is_error);
1182  }
1183  else {
1184  geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
1185  bool is_error;
1186  /* Invert here because we want to keep the things not in the selection. */
1187  separate_geometry(geometry_set, domain, mode, selection, is_error);
1188  });
1189  }
1190 
1191  params.set_output("Geometry", std::move(geometry_set));
1192 }
1193 
1194 } // namespace blender::nodes::node_geo_delete_geometry_cc
1195 
1197 {
1198  namespace file_ns = blender::nodes::node_geo_delete_geometry_cc;
1199 
1200  static bNodeType ntype;
1201 
1203 
1204  node_type_storage(&ntype,
1205  "NodeGeometryDeleteGeometry",
1208 
1210 
1214  nodeRegisterType(&ntype);
1215 }
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_CURVE
Definition: BKE_attribute.h:31
@ ATTR_DOMAIN_INSTANCE
Definition: BKE_attribute.h:32
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
@ ATTR_DOMAIN_FACE
Definition: BKE_attribute.h:29
@ ATTR_DOMAIN_CORNER
Definition: BKE_attribute.h:30
@ ATTR_DOMAIN_EDGE
Definition: BKE_attribute.h:28
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
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)
#define GEO_NODE_DELETE_GEOMETRY
Definition: BKE_node.h:1445
#define NODE_STORAGE_FUNCS(StorageT)
Definition: BKE_node.h:1563
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4390
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4426
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
General operations for point clouds.
struct PointCloud * BKE_pointcloud_new_nomain(int totpoint)
Definition: pointcloud.cc:243
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define UNUSED(x)
#define ELEM(...)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
eCustomDataType
GeometryNodeDeleteGeometryMode
@ GEO_NODE_DELETE_GEOMETRY_MODE_EDGE_FACE
@ GEO_NODE_DELETE_GEOMETRY_MODE_ONLY_FACE
@ GEO_NODE_DELETE_GEOMETRY_MODE_ALL
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
int attribute_domain_size(eAttrDomain domain) const
Definition: geometry_set.cc:63
void remove_instances(const blender::IndexMask mask)
const Mesh * get_for_read() const
const PointCloud * get_for_read() const
MutableSpan< T > typed() const
int64_t size() const
bool is_empty() const
ItemIterator items() const
Definition: BLI_map.hh:859
constexpr int64_t size() const
Definition: BLI_span.hh:511
constexpr void fill(const T &value)
Definition: BLI_span.hh:527
constexpr void copy_from(Span< T > values)
Definition: BLI_span.hh:707
constexpr IndexRange index_range() const
Definition: BLI_span.hh:661
constexpr int64_t size() const
Definition: BLI_span.hh:240
constexpr IndexRange index_range() const
Definition: BLI_span.hh:401
constexpr bool contains(const T &value) const
Definition: BLI_span.hh:265
int64_t size() const
Definition: BLI_vector.hh:694
Span< T > as_span() const
Definition: BLI_vector.hh:325
void append_unchecked(const T &value)
Definition: BLI_vector.hh:484
void reserve(const int64_t min_capacity)
Definition: BLI_vector.hh:340
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
GSpanAttributeWriter lookup_or_add_for_write_only_span(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type)
OperationNode * node
SyclQueue void void * src
void * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_gpu_kernel_postfix int ccl_global int * indices
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
#define T
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
AttributeAccessor pointcloud_attributes(const PointCloud &pointcloud)
MutableAttributeAccessor pointcloud_attributes_for_write(PointCloud &pointcloud)
AttributeAccessor mesh_attributes(const Mesh &mesh)
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
Definition: customdata.cc:5337
MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh)
Field< bool > invert_boolean_field(const Field< bool > &field)
Definition: field.cc:521
static void compute_selected_mesh_data_from_edge_selection_edge_face(const Mesh &mesh, const Span< bool > edge_selection, MutableSpan< int > r_edge_map, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_edges_num, int *r_selected_polys_num, int *r_selected_loops_num)
static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, const Span< bool > vertex_selection, MutableSpan< int > r_vertex_map, MutableSpan< int > r_edge_map, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_vertices_num, int *r_selected_edges_num, int *r_selected_polys_num, int *r_selected_loops_num)
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, const Span< bool > edge_selection, MutableSpan< int > r_vertex_map, MutableSpan< int > r_edge_map, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_vertices_num, int *r_selected_edges_num, int *r_selected_polys_num, int *r_selected_loops_num)
static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< int > vertex_map)
static void compute_selected_vertices_from_vertex_selection(const Span< bool > vertex_selection, MutableSpan< int > r_vertex_map, int *r_selected_vertices_num)
static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, const Span< bool > edge_selection, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_polys_num, int *r_selected_loops_num)
static void separate_point_cloud_selection(GeometrySet &geometry_set, const Field< bool > &selection_field)
static void separate_mesh_selection(GeometrySet &geometry_set, const Field< bool > &selection_field, const eAttrDomain selection_domain, const GeometryNodeDeleteGeometryMode mode)
static void compute_selected_edges_from_vertex_selection(const Mesh &mesh, const Span< bool > vertex_selection, MutableSpan< int > r_edge_map, int *r_selected_edges_num)
static void compute_selected_mesh_data_from_poly_selection_edge_face(const Mesh &mesh, const Span< bool > poly_selection, MutableSpan< int > r_edge_map, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_edges_num, int *r_selected_polys_num, int *r_selected_loops_num)
static void delete_curves_selection(GeometrySet &geometry_set, const Field< bool > &selection_field, const eAttrDomain selection_domain)
static void copy_face_corner_attributes(const Map< AttributeIDRef, AttributeKind > &attributes, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes, const int selected_loops_num, const Span< int > selected_poly_indices, const Mesh &mesh_in)
static void delete_selected_instances(GeometrySet &geometry_set, const Field< bool > &selection_field)
static void node_declare(NodeDeclarationBuilder &b)
static void copy_data_based_on_map(Span< T > src, MutableSpan< T > dst, Span< int > index_map)
static void do_mesh_separation(GeometrySet &geometry_set, const Mesh &mesh_in, const Span< bool > selection, const eAttrDomain domain, const GeometryNodeDeleteGeometryMode mode)
static void copy_attributes_based_on_map(const Map< AttributeIDRef, AttributeKind > &attributes, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes, const eAttrDomain domain, const Span< int > index_map)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void compute_selected_mesh_data_from_vertex_selection_edge_face(const Mesh &mesh, const Span< bool > vertex_selection, MutableSpan< int > r_edge_map, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_edges_num, int *r_selected_polys_num, int *r_selected_loops_num)
static void copy_attributes_based_on_mask(const Map< AttributeIDRef, AttributeKind > &attributes, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes, const eAttrDomain domain, const IndexMask mask)
static void compute_selected_polygons_from_poly_selection(const Mesh &mesh, const Span< bool > poly_selection, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_polys_num, int *r_selected_loops_num)
static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, const Span< bool > vertex_selection, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_polys_num, int *r_selected_loops_num)
static void node_geo_exec(GeoNodeExecParams params)
static void copy_attributes(const Map< AttributeIDRef, AttributeKind > &attributes, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes, const Span< eAttrDomain > domains)
static void compute_selected_vertices_and_edges_from_edge_selection(const Mesh &mesh, const Span< bool > edge_selection, MutableSpan< int > r_vertex_map, MutableSpan< int > r_edge_map, int *r_selected_vertices_num, int *r_selected_edges_num)
static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< int > edge_map, Span< int > masked_poly_indices, Span< int > new_loop_starts)
static void copy_data_based_on_mask(Span< T > data, MutableSpan< T > r_data, IndexMask mask)
static void compute_selected_edges_from_edge_selection(const Mesh &mesh, const Span< bool > edge_selection, MutableSpan< int > r_edge_map, int *r_selected_edges_num)
static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span< int > edge_map)
static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, const Span< bool > poly_selection, MutableSpan< int > r_vertex_map, MutableSpan< int > r_edge_map, Vector< int > &r_selected_poly_indices, Vector< int > &r_loop_starts, int *r_selected_vertices_num, int *r_selected_edges_num, int *r_selected_polys_num, int *r_selected_loops_num)
void separate_geometry(GeometrySet &geometry_set, eAttrDomain domain, GeometryNodeDeleteGeometryMode mode, const Field< bool > &selection_field, bool &r_is_error)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
Definition: node.cc:1082
void register_node_type_geo_delete_geometry()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:55
void node_free_standard_storage(bNode *node)
Definition: node_util.c:43
void remove(const GeometryComponentType component_type)
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
bool has_realized_data() const
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
void gather_attributes_for_propagation(blender::Span< GeometryComponentType > component_types, GeometryComponentType dst_component_type, bool include_instances, blender::Map< blender::bke::AttributeIDRef, blender::bke::AttributeKind > &r_attributes) const
bool has_instances() const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
bool has_mesh() const
bool has_curves() const
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
bool has_pointcloud() const
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
struct MEdge * medge
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
void * data
Definition: RNA_types.h:38
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:244
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480