Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| if (!geometry_set.has_mesh()) { | if (!geometry_set.has_mesh()) { | ||||
| geometry_set.remove_geometry_during_modify(); | geometry_set.remove_geometry_during_modify(); | ||||
| return; | return; | ||||
| } | } | ||||
| geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_MESH}); | geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_MESH}); | ||||
| const Mesh &mesh = *geometry_set.get_mesh_for_read(); | const Mesh &mesh = *geometry_set.get_mesh_for_read(); | ||||
| const Span<MVert> verts = mesh.verts(); | |||||
| const Span<MEdge> edges = mesh.edges(); | const Span<MEdge> edges = mesh.edges(); | ||||
| const Span<MPoly> polys = mesh.polys(); | const Span<MPoly> polys = mesh.polys(); | ||||
| const Span<MLoop> loops = mesh.loops(); | const Span<MLoop> loops = mesh.loops(); | ||||
| bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE}; | bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE}; | ||||
| FieldEvaluator evaluator(field_context, polys.size()); | FieldEvaluator evaluator(field_context, polys.size()); | ||||
| evaluator.add(count_field); | evaluator.add(count_field); | ||||
| evaluator.set_selection(selection_field); | evaluator.set_selection(selection_field); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | ||||
| const VArray<int> counts = evaluator.get_evaluated<int>(0); | const VArray<int> counts = evaluator.get_evaluated<int>(0); | ||||
| int total_polys = 0; | int total_polys = 0; | ||||
| int total_loops = 0; | int total_loops = 0; | ||||
| Array<int> offsets(selection.size() + 1); | Array<int> offsets(selection.size() + 1); | ||||
| for (const int i_selection : selection.index_range()) { | for (const int i_selection : selection.index_range()) { | ||||
| const int count = std::max(counts[selection[i_selection]], 0); | const int count = std::max(counts[selection[i_selection]], 0); | ||||
| offsets[i_selection] = total_polys; | offsets[i_selection] = total_polys; | ||||
| total_polys += count; | total_polys += count; | ||||
| total_loops += count * polys[selection[i_selection]].totloop; | total_loops += count * polys[selection[i_selection]].totloop; | ||||
| } | } | ||||
| offsets[selection.size()] = total_polys; | offsets[selection.size()] = total_polys; | ||||
| Mesh *new_mesh = BKE_mesh_new_nomain(total_loops, total_loops, 0, total_loops, total_polys); | Mesh *new_mesh = BKE_mesh_new_nomain(total_loops, total_loops, 0, total_loops, total_polys); | ||||
| MutableSpan<MVert> new_verts = new_mesh->verts_for_write(); | |||||
| MutableSpan<MEdge> new_edges = new_mesh->edges_for_write(); | MutableSpan<MEdge> new_edges = new_mesh->edges_for_write(); | ||||
| MutableSpan<MPoly> new_polys = new_mesh->polys_for_write(); | MutableSpan<MPoly> new_polys = new_mesh->polys_for_write(); | ||||
| MutableSpan<MLoop> new_loops = new_mesh->loops_for_write(); | MutableSpan<MLoop> new_loops = new_mesh->loops_for_write(); | ||||
| Array<int> vert_mapping(new_verts.size()); | Array<int> vert_mapping(new_mesh->totvert); | ||||
| Array<int> edge_mapping(new_edges.size()); | Array<int> edge_mapping(new_edges.size()); | ||||
| Array<int> loop_mapping(new_loops.size()); | Array<int> loop_mapping(new_loops.size()); | ||||
| int poly_index = 0; | int poly_index = 0; | ||||
| int loop_index = 0; | int loop_index = 0; | ||||
| for (const int i_selection : selection.index_range()) { | for (const int i_selection : selection.index_range()) { | ||||
| const IndexRange poly_range = range_for_offsets_index(offsets, i_selection); | const IndexRange poly_range = range_for_offsets_index(offsets, i_selection); | ||||
| const MPoly &source = polys[selection[i_selection]]; | const MPoly &source = polys[selection[i_selection]]; | ||||
| for ([[maybe_unused]] const int i_duplicate : IndexRange(poly_range.size())) { | for ([[maybe_unused]] const int i_duplicate : IndexRange(poly_range.size())) { | ||||
| new_polys[poly_index] = source; | new_polys[poly_index] = source; | ||||
| new_polys[poly_index].loopstart = loop_index; | new_polys[poly_index].loopstart = loop_index; | ||||
| for (const int i_loops : IndexRange(source.totloop)) { | for (const int i_loops : IndexRange(source.totloop)) { | ||||
| const MLoop ¤t_loop = loops[source.loopstart + i_loops]; | const MLoop ¤t_loop = loops[source.loopstart + i_loops]; | ||||
| loop_mapping[loop_index] = source.loopstart + i_loops; | loop_mapping[loop_index] = source.loopstart + i_loops; | ||||
| new_verts[loop_index] = verts[current_loop.v]; | |||||
| vert_mapping[loop_index] = current_loop.v; | vert_mapping[loop_index] = current_loop.v; | ||||
| new_edges[loop_index] = edges[current_loop.e]; | new_edges[loop_index] = edges[current_loop.e]; | ||||
| edge_mapping[loop_index] = current_loop.e; | edge_mapping[loop_index] = current_loop.e; | ||||
| new_edges[loop_index].v1 = loop_index; | new_edges[loop_index].v1 = loop_index; | ||||
| if (i_loops + 1 != source.totloop) { | if (i_loops + 1 != source.totloop) { | ||||
| new_edges[loop_index].v2 = loop_index + 1; | new_edges[loop_index].v2 = loop_index + 1; | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| * \{ */ | * \{ */ | ||||
| static void duplicate_points_mesh(GeometrySet &geometry_set, | static void duplicate_points_mesh(GeometrySet &geometry_set, | ||||
| const Field<int> &count_field, | const Field<int> &count_field, | ||||
| const Field<bool> &selection_field, | const Field<bool> &selection_field, | ||||
| const IndexAttributes &attribute_outputs) | const IndexAttributes &attribute_outputs) | ||||
| { | { | ||||
| const Mesh &mesh = *geometry_set.get_mesh_for_read(); | const Mesh &mesh = *geometry_set.get_mesh_for_read(); | ||||
| const Span<MVert> src_verts = mesh.verts(); | |||||
| bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_POINT}; | bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_POINT}; | ||||
| FieldEvaluator evaluator{field_context, src_verts.size()}; | FieldEvaluator evaluator{field_context, mesh.totvert}; | ||||
| evaluator.add(count_field); | evaluator.add(count_field); | ||||
| evaluator.set_selection(selection_field); | evaluator.set_selection(selection_field); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const VArray<int> counts = evaluator.get_evaluated<int>(0); | const VArray<int> counts = evaluator.get_evaluated<int>(0); | ||||
| const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | ||||
| Array<int> offsets = accumulate_counts_to_offsets(selection, counts); | Array<int> offsets = accumulate_counts_to_offsets(selection, counts); | ||||
| Mesh *new_mesh = BKE_mesh_new_nomain(offsets.last(), 0, 0, 0, 0); | Mesh *new_mesh = BKE_mesh_new_nomain(offsets.last(), 0, 0, 0, 0); | ||||
| MutableSpan<MVert> dst_verts = new_mesh->verts_for_write(); | |||||
| threaded_slice_fill(offsets.as_span(), selection, src_verts, dst_verts); | |||||
| copy_attributes_without_id(geometry_set, | copy_attributes_without_id(geometry_set, | ||||
| GEO_COMPONENT_TYPE_MESH, | GEO_COMPONENT_TYPE_MESH, | ||||
| ATTR_DOMAIN_POINT, | ATTR_DOMAIN_POINT, | ||||
| offsets, | offsets, | ||||
| selection, | selection, | ||||
| mesh.attributes(), | mesh.attributes(), | ||||
| new_mesh->attributes_for_write()); | new_mesh->attributes_for_write()); | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||