Blender V4.3
extract_elements.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "BLI_index_mask.hh"
8
9#include "BKE_attribute.hh"
10#include "BKE_curves.hh"
11#include "BKE_geometry_set.hh"
12#include "BKE_grease_pencil.hh"
13#include "BKE_instances.hh"
14#include "BKE_mesh.hh"
15#include "BKE_pointcloud.hh"
16
17namespace blender::geometry {
18
19using bke::AttrDomain;
20
27
29 const IndexMask &mask,
30 const bke::AttributeFilter &attribute_filter)
31{
32 BLI_assert(mask.min_array_size() <= mesh.verts_num);
33 Array<Mesh *> elements(mask.size(), nullptr);
34
35 const bke::AttributeAccessor src_attributes = mesh.attributes();
36
37 Vector<PropagationAttribute> propagation_attributes;
38 src_attributes.foreach_attribute([&](const bke::AttributeIter &iter) {
39 if (iter.data_type == CD_PROP_STRING) {
40 return;
41 }
42 if (attribute_filter.allow_skip(iter.name)) {
43 return;
44 }
45 const bke::GAttributeReader src_attribute = iter.get(AttrDomain::Point);
46 if (!src_attribute) {
47 return;
48 }
49 propagation_attributes.append({iter.name, iter.data_type, AttrDomain::Point, *src_attribute});
50 });
51
52 mask.foreach_index(GrainSize(32), [&](const int vert_i, const int element_i) {
53 Mesh *element = BKE_mesh_new_nomain(1, 0, 0, 0);
55
56 bke::MutableAttributeAccessor element_attributes = element->attributes_for_write();
57
58 for (const PropagationAttribute &src_attribute : propagation_attributes) {
60 src_attribute.name, AttrDomain::Point, src_attribute.cd_type);
61 if (!dst) {
62 continue;
63 }
64 src_attribute.data.get(vert_i, dst.span[0]);
65 dst.finish();
66 }
67
68 elements[element_i] = element;
69 });
70
71 return elements;
72}
73
75 const IndexMask &mask,
76 const bke::AttributeFilter &attribute_filter)
77{
78 BLI_assert(mask.min_array_size() <= mesh.edges_num);
79 Array<Mesh *> elements(mask.size(), nullptr);
80
81 const Span<int2> src_edges = mesh.edges();
82 const bke::AttributeAccessor src_attributes = mesh.attributes();
83
84 Vector<PropagationAttribute> propagation_attributes;
85 src_attributes.foreach_attribute([&](const bke::AttributeIter &iter) {
86 if (iter.data_type == CD_PROP_STRING) {
87 return;
88 }
89 if (iter.name == ".edge_verts") {
90 return;
91 }
92 if (attribute_filter.allow_skip(iter.name)) {
93 return;
94 }
95 const bke::GAttributeReader src_attribute = iter.get();
96 if (ELEM(src_attribute.domain, AttrDomain::Point, AttrDomain::Edge)) {
97 propagation_attributes.append(
98 {iter.name, iter.data_type, src_attribute.domain, *src_attribute});
99 }
100 else if (src_attribute.domain == AttrDomain::Corner) {
101 if (GVArray adapted_attribute = src_attributes.adapt_domain(
102 *src_attribute, src_attribute.domain, AttrDomain::Point))
103 {
104 propagation_attributes.append(
105 {iter.name, iter.data_type, AttrDomain::Point, adapted_attribute});
106 }
107 }
108 else if (src_attribute.domain == AttrDomain::Face) {
109 if (GVArray adapted_attribute = src_attributes.adapt_domain(
110 *src_attribute, src_attribute.domain, AttrDomain::Edge))
111 {
112 propagation_attributes.append(
113 {iter.name, iter.data_type, AttrDomain::Edge, adapted_attribute});
114 }
115 }
116 });
117
118 mask.foreach_index(GrainSize(32), [&](const int edge_i, const int element_i) {
119 Mesh *element = BKE_mesh_new_nomain(2, 1, 0, 0);
120 BKE_mesh_copy_parameters_for_eval(element, &mesh);
121
122 MutableSpan<int2> element_edges = element->edges_for_write();
123 element_edges[0] = {0, 1};
124 const int2 &src_edge = src_edges[edge_i];
125
126 bke::MutableAttributeAccessor element_attributes = element->attributes_for_write();
127 for (const PropagationAttribute &src_attribute : propagation_attributes) {
129 src_attribute.name, src_attribute.domain, src_attribute.cd_type);
130 if (!dst) {
131 continue;
132 }
133 if (src_attribute.domain == AttrDomain::Point) {
134 src_attribute.data.get(src_edge[0], dst.span[0]);
135 src_attribute.data.get(src_edge[1], dst.span[1]);
136 }
137 else {
138 src_attribute.data.get(edge_i, dst.span[0]);
139 }
140 dst.finish();
141 }
142 elements[element_i] = element;
143 });
144
145 return elements;
146}
147
149 const IndexMask &mask,
150 const bke::AttributeFilter &attribute_filter)
151{
152 BLI_assert(mask.min_array_size() <= mesh.faces_num);
153 Array<Mesh *> elements(mask.size(), nullptr);
154
155 const Span<int> src_corner_verts = mesh.corner_verts();
156 const Span<int> src_corner_edges = mesh.corner_edges();
157 const OffsetIndices<int> src_faces = mesh.faces();
158
159 const bke::AttributeAccessor src_attributes = mesh.attributes();
160
161 Vector<PropagationAttribute> propagation_attributes;
162 src_attributes.foreach_attribute([&](const bke::AttributeIter &iter) {
163 if (iter.data_type == CD_PROP_STRING) {
164 return;
165 }
166 if (ELEM(iter.name, ".edge_verts", ".corner_edge", ".corner_vert")) {
167 return;
168 }
169 if (attribute_filter.allow_skip(iter.name)) {
170 return;
171 }
172 const bke::GAttributeReader src_attribute = iter.get();
173 if (!src_attribute) {
174 return;
175 }
176 propagation_attributes.append(
177 {iter.name, iter.data_type, src_attribute.domain, *src_attribute});
178 });
179
180 mask.foreach_index(GrainSize(32), [&](const int face_i, const int element_i) {
181 const IndexRange src_face = src_faces[face_i];
182 const int verts_num = src_face.size();
183
184 Mesh *element = BKE_mesh_new_nomain(verts_num, verts_num, 1, verts_num);
185 BKE_mesh_copy_parameters_for_eval(element, &mesh);
186
187 MutableSpan<int2> element_edges = element->edges_for_write();
188 MutableSpan<int> element_corner_verts = element->corner_verts_for_write();
189 MutableSpan<int> element_corner_edges = element->corner_edges_for_write();
190 MutableSpan<int> element_face_offsets = element->face_offsets_for_write();
191
192 for (const int i : IndexRange(verts_num)) {
193 element_edges[i] = {i, i + 1};
194 element_corner_verts[i] = i;
195 element_corner_edges[i] = i;
196 }
197 element_edges.last()[1] = 0;
198 element_face_offsets[0] = 0;
199 element_face_offsets[1] = verts_num;
200
201 bke::MutableAttributeAccessor element_attributes = element->attributes_for_write();
202 for (const PropagationAttribute &src_attribute : propagation_attributes) {
204 src_attribute.name, src_attribute.domain, src_attribute.cd_type);
205 if (!dst) {
206 continue;
207 }
208 switch (src_attribute.domain) {
209 case AttrDomain::Point: {
210 for (const int i : IndexRange(verts_num)) {
211 const int src_corner_i = src_face[i];
212 const int src_vert_i = src_corner_verts[src_corner_i];
213 src_attribute.data.get(src_vert_i, dst.span[i]);
214 }
215 break;
216 }
217 case AttrDomain::Edge: {
218 for (const int i : IndexRange(verts_num)) {
219 const int src_corner_i = src_face[i];
220 const int src_edge_i = src_corner_edges[src_corner_i];
221 src_attribute.data.get(src_edge_i, dst.span[i]);
222 }
223 break;
224 }
225 case AttrDomain::Corner: {
226 src_attribute.data.materialize_compressed(src_face, dst.span.data());
227 break;
228 }
229 case AttrDomain::Face: {
230 src_attribute.data.get(face_i, dst.span[0]);
231 break;
232 }
233 default:
235 break;
236 }
237 dst.finish();
238 }
239 elements[element_i] = element;
240 });
241
242 return elements;
243}
244
246 const IndexMask &mask,
247 const bke::AttributeFilter &attribute_filter)
248{
249 BLI_assert(mask.min_array_size() <= pointcloud.totpoint);
250 Array<PointCloud *> elements(mask.size(), nullptr);
251
252 const bke::AttributeAccessor src_attributes = pointcloud.attributes();
253
254 mask.foreach_index(GrainSize(32), [&](const int point_i, const int element_i) {
256 element->totcol = pointcloud.totcol;
257 element->mat = static_cast<Material **>(MEM_dupallocN(pointcloud.mat));
258
259 bke::gather_attributes(src_attributes,
260 AttrDomain::Point,
261 AttrDomain::Point,
262 attribute_filter,
263 Span<int>{point_i},
264 element->attributes_for_write());
265 elements[element_i] = element;
266 });
267
268 return elements;
269}
270
272 const IndexMask &mask,
273 const bke::AttributeFilter &attribute_filter)
274{
275 BLI_assert(mask.min_array_size() <= curves.geometry.point_num);
276 Array<Curves *> elements(mask.size(), nullptr);
277
278 const bke::CurvesGeometry &src_curves = curves.geometry.wrap();
279 const bke::AttributeAccessor src_attributes = src_curves.attributes();
280 const Array<int> point_to_curve_map = src_curves.point_to_curve_map();
281
282 mask.foreach_index(GrainSize(32), [&](const int point_i, const int element_i) {
283 const int curve_i = point_to_curve_map[point_i];
284
285 /* Actual curve type is propagated below. */
287 bke::curves_copy_parameters(curves, *element);
288
289 bke::MutableAttributeAccessor element_attributes =
290 element->geometry.wrap().attributes_for_write();
291 bke::gather_attributes(src_attributes,
292 AttrDomain::Point,
293 AttrDomain::Point,
294 attribute_filter,
295 Span<int>{point_i},
296 element_attributes);
297 bke::gather_attributes(src_attributes,
298 AttrDomain::Curve,
299 AttrDomain::Curve,
300 attribute_filter,
301 Span<int>{curve_i},
302 element_attributes);
303 elements[element_i] = element;
304 });
305
306 return elements;
307}
308
310 const IndexMask &mask,
311 const bke::AttributeFilter &attribute_filter)
312{
313 BLI_assert(mask.min_array_size() <= curves.geometry.curve_num);
314 Array<Curves *> elements(mask.size(), nullptr);
315
316 const bke::CurvesGeometry &src_curves = curves.geometry.wrap();
317 const bke::AttributeAccessor src_attributes = src_curves.attributes();
318 const OffsetIndices<int> src_points_by_curve = src_curves.points_by_curve();
319
320 mask.foreach_index(GrainSize(32), [&](const int curve_i, const int element_i) {
321 const IndexRange src_points = src_points_by_curve[curve_i];
322 const int points_num = src_points.size();
324 bke::MutableAttributeAccessor element_attributes =
325 element->geometry.wrap().attributes_for_write();
326 bke::curves_copy_parameters(curves, *element);
327 bke::gather_attributes(src_attributes,
328 AttrDomain::Point,
329 AttrDomain::Point,
330 attribute_filter,
331 src_points,
332 element_attributes);
333 bke::gather_attributes(src_attributes,
334 AttrDomain::Curve,
335 AttrDomain::Curve,
336 attribute_filter,
337 Span<int>{curve_i},
338 element_attributes);
339 element->geometry.wrap().update_curve_types();
340 elements[element_i] = element;
341 });
342
343 return elements;
344}
345
347 const IndexMask &mask,
348 const bke::AttributeFilter &attribute_filter)
349{
350 using bke::Instances;
351 BLI_assert(mask.min_array_size() <= instances.instances_num());
352 Array<Instances *> elements(mask.size(), nullptr);
353
354 const bke::AttributeAccessor src_attributes = instances.attributes();
355 const Span<bke::InstanceReference> src_references = instances.references();
356 const Span<int> src_reference_handles = instances.reference_handles();
357 const Span<float4x4> src_transforms = instances.transforms();
358
359 mask.foreach_index(GrainSize(32), [&](const int instance_i, const int element_i) {
360 const int old_handle = src_reference_handles[instance_i];
361 const bke::InstanceReference &old_reference = src_references[old_handle];
362 const float4x4 &old_transform = src_transforms[instance_i];
363
364 Instances *element = new Instances();
365 const int new_handle = element->add_new_reference(old_reference);
366 element->add_instance(new_handle, old_transform);
367
368 bke::gather_attributes(src_attributes,
369 AttrDomain::Instance,
370 AttrDomain::Instance,
372 attribute_filter, {".reference_index", "instance_transform"}),
373 Span<int>{instance_i},
374 element->attributes_for_write());
375
376 elements[element_i] = element;
377 });
378
379 return elements;
380}
381
383 const IndexMask &mask,
384 const bke::AttributeFilter &attribute_filter)
385{
386 using namespace bke::greasepencil;
387 BLI_assert(mask.min_array_size() <= grease_pencil.layers().size());
388
389 Array<GreasePencil *> elements(mask.size(), nullptr);
390 const bke::AttributeAccessor src_attributes = grease_pencil.attributes();
391 const Span<const Layer *> src_layers = grease_pencil.layers();
392
393 mask.foreach_index(GrainSize(32), [&](const int layer_i, const int element_i) {
395 element->material_array = static_cast<Material **>(
396 MEM_dupallocN(grease_pencil.material_array));
397 element->material_array_num = grease_pencil.material_array_num;
398
399 const Layer &src_layer = *src_layers[layer_i];
400 const Drawing *src_drawing = grease_pencil.get_eval_drawing(src_layer);
401
402 if (src_drawing) {
403 Layer &new_layer = element->add_layer(src_layer.name());
404 Drawing &drawing = *element->insert_frame(new_layer, element->runtime->eval_frame);
405 drawing.strokes_for_write() = src_drawing->strokes();
406
407 bke::gather_attributes(src_attributes,
408 AttrDomain::Layer,
409 AttrDomain::Layer,
410 attribute_filter,
411 Span<int>{layer_i},
412 element->attributes_for_write());
413 }
414
415 elements[element_i] = element;
416 });
417
418 return elements;
419}
420
422 const GreasePencil &grease_pencil,
423 int layer_i,
424 const IndexMask &mask,
425 const bke::AttributeFilter &attribute_filter)
426{
427 using namespace bke::greasepencil;
428 const Layer &src_layer = grease_pencil.layer(layer_i);
429 const Drawing &src_drawing = *grease_pencil.get_eval_drawing(src_layer);
430 const bke::CurvesGeometry &src_curves = src_drawing.strokes();
431 const bke::AttributeAccessor src_layer_attributes = grease_pencil.attributes();
432 const bke::AttributeAccessor src_curves_attributes = src_curves.attributes();
433 const Array<int> point_to_curve_map = src_curves.point_to_curve_map();
434
435 Array<GreasePencil *> elements(mask.size(), nullptr);
436 mask.foreach_index(GrainSize(32), [&](const int point_i, const int element_i) {
437 const int curve_i = point_to_curve_map[point_i];
438
440 element->material_array = static_cast<Material **>(
441 MEM_dupallocN(grease_pencil.material_array));
442 element->material_array_num = grease_pencil.material_array_num;
443
444 Layer &new_layer = element->add_layer(src_layer.name());
445 Drawing &drawing = *element->insert_frame(new_layer, element->runtime->eval_frame);
446 bke::CurvesGeometry &new_curves = drawing.strokes_for_write();
447 new_curves.resize(1, 1);
448 new_curves.offsets_for_write().last() = 1;
449
450 bke::gather_attributes(src_curves_attributes,
451 AttrDomain::Point,
452 AttrDomain::Point,
453 attribute_filter,
454 Span<int>{point_i},
455 new_curves.attributes_for_write());
456 bke::gather_attributes(src_curves_attributes,
457 AttrDomain::Curve,
458 AttrDomain::Curve,
459 attribute_filter,
460 Span<int>{curve_i},
461 new_curves.attributes_for_write());
462 bke::gather_attributes(src_layer_attributes,
463 AttrDomain::Layer,
464 AttrDomain::Layer,
465 attribute_filter,
466 Span<int>{layer_i},
467 element->attributes_for_write());
468
469 new_curves.update_curve_types();
470
471 elements[element_i] = element;
472 });
473
474 return elements;
475}
476
478 const GreasePencil &grease_pencil,
479 const int layer_i,
480 const IndexMask &mask,
481 const bke::AttributeFilter &attribute_filter)
482{
483 using namespace bke::greasepencil;
484 const Layer &src_layer = grease_pencil.layer(layer_i);
485 const Drawing &src_drawing = *grease_pencil.get_eval_drawing(src_layer);
486 const bke::CurvesGeometry &src_curves = src_drawing.strokes();
487 const bke::AttributeAccessor src_layer_attributes = grease_pencil.attributes();
488 const bke::AttributeAccessor src_curves_attributes = src_curves.attributes();
489 const OffsetIndices<int> src_points_by_curve = src_curves.points_by_curve();
490
491 Array<GreasePencil *> elements(mask.size(), nullptr);
492 mask.foreach_index(GrainSize(32), [&](const int curve_i, const int element_i) {
493 const IndexRange src_points = src_points_by_curve[curve_i];
494 const int points_num = src_points.size();
495
497 element->material_array = static_cast<Material **>(
498 MEM_dupallocN(grease_pencil.material_array));
499 element->material_array_num = grease_pencil.material_array_num;
500
501 Layer &new_layer = element->add_layer(src_layer.name());
502 Drawing &drawing = *element->insert_frame(new_layer, element->runtime->eval_frame);
503 bke::CurvesGeometry &new_curves = drawing.strokes_for_write();
504
505 new_curves.resize(points_num, 1);
506 bke::gather_attributes(src_curves_attributes,
507 AttrDomain::Point,
508 AttrDomain::Point,
509 attribute_filter,
510 src_points,
511 new_curves.attributes_for_write());
512 bke::gather_attributes(src_curves_attributes,
513 AttrDomain::Curve,
514 AttrDomain::Curve,
515 attribute_filter,
516 Span<int>{curve_i},
517 new_curves.attributes_for_write());
518 bke::gather_attributes(src_layer_attributes,
519 AttrDomain::Layer,
520 AttrDomain::Layer,
521 attribute_filter,
522 Span<int>{layer_i},
523 element->attributes_for_write());
524
525 new_curves.update_curve_types();
526 elements[element_i] = element;
527 });
528
529 return elements;
530}
531
532} // namespace blender::geometry
Low-level operations for curves.
Low-level operations for grease pencil.
GreasePencil * BKE_grease_pencil_new_nomain()
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
General operations for point clouds.
PointCloud * BKE_pointcloud_new_nomain(int totpoint)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
@ CURVE_TYPE_POLY
@ CD_PROP_STRING
ATTR_WARN_UNUSED_RESULT const void * element
AttributeSet attributes
constexpr int64_t size() const
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:690
constexpr const T * data() const
Definition BLI_span.hh:216
void append(const T &value)
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
GVArray adapt_domain(const GVArray &varray, const AttrDomain from_domain, const AttrDomain to_domain) const
GAttributeReader get() const
Array< int > point_to_curve_map() const
OffsetIndices< int > points_by_curve() const
MutableAttributeAccessor attributes_for_write()
void resize(int points_num, int curves_num)
MutableSpan< int > offsets_for_write()
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
void curves_copy_parameters(const Curves &src, Curves &dst)
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
auto attribute_filter_with_skip_ref(AttributeFilter filter, const Span< StringRef > skip)
Curves * curves_new_nomain_single(int points_num, CurveType type)
Array< bke::Instances * > extract_instances(const bke::Instances &instances, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< GreasePencil * > extract_greasepencil_layer_points(const GreasePencil &grease_pencil, int layer_i, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< Mesh * > extract_mesh_faces(const Mesh &mesh, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< Mesh * > extract_mesh_vertices(const Mesh &mesh, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< Curves * > extract_curves(const Curves &curves, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< Curves * > extract_curves_points(const Curves &curves, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< GreasePencil * > extract_greasepencil_layers(const GreasePencil &grease_pencil, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< GreasePencil * > extract_greasepencil_layer_curves(const GreasePencil &grease_pencil, int layer_i, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< PointCloud * > extract_pointcloud_points(const PointCloud &pointcloud, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
Array< Mesh * > extract_mesh_edges(const Mesh &mesh, const IndexMask &mask, const bke::AttributeFilter &attribute_filter)
GreasePencilLayerRuntimeHandle * runtime
struct Material ** material_array
struct Material ** mat
bool allow_skip(const StringRef name) const