Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| /* This allows parallelizing attribute mixing for new edges. */ | /* This allows parallelizing attribute mixing for new edges. */ | ||||
| Array<Vector<int>> vert_to_edge_map = create_vert_to_edge_map(orig_vert_size, mesh.edges()); | Array<Vector<int>> vert_to_edge_map = create_vert_to_edge_map(orig_vert_size, mesh.edges()); | ||||
| expand_mesh(mesh, selection.size(), selection.size(), 0, 0); | expand_mesh(mesh, selection.size(), selection.size(), 0, 0); | ||||
| const IndexRange new_vert_range{orig_vert_size, selection.size()}; | const IndexRange new_vert_range{orig_vert_size, selection.size()}; | ||||
| const IndexRange new_edge_range{orig_edge_size, selection.size()}; | const IndexRange new_edge_range{orig_edge_size, selection.size()}; | ||||
| MutableSpan<MVert> new_verts = mesh.verts_for_write().slice(new_vert_range); | MutableSpan<float3> new_positions = mesh.positions_for_write().slice(new_vert_range); | ||||
| MutableSpan<MEdge> new_edges = mesh.edges_for_write().slice(new_edge_range); | MutableSpan<MEdge> new_edges = mesh.edges_for_write().slice(new_edge_range); | ||||
| for (const int i_selection : selection.index_range()) { | for (const int i_selection : selection.index_range()) { | ||||
| new_edges[i_selection] = new_loose_edge(selection[i_selection], new_vert_range[i_selection]); | new_edges[i_selection] = new_loose_edge(selection[i_selection], new_vert_range[i_selection]); | ||||
| } | } | ||||
| MutableAttributeAccessor attributes = mesh.attributes_for_write(); | MutableAttributeAccessor attributes = mesh.attributes_for_write(); | ||||
| Show All 27 Lines | |||||
| attribute.finish(); | attribute.finish(); | ||||
| return true; | return true; | ||||
| }); | }); | ||||
| devirtualize_varray(offsets, [&](const auto offsets) { | devirtualize_varray(offsets, [&](const auto offsets) { | ||||
| threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) { | threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) { | ||||
| for (const int i : range) { | for (const int i : range) { | ||||
| const float3 offset = offsets[selection[i]]; | new_positions[i] += offsets[selection[i]]; | ||||
| add_v3_v3(new_verts[i].co, offset); | |||||
| } | } | ||||
| }); | }); | ||||
| }); | }); | ||||
| MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | ||||
| vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | ||||
| MutableSpan<int> new_edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | MutableSpan<int> new_edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| BLI_assert_unreachable(); | BLI_assert_unreachable(); | ||||
| } | } | ||||
| }); | }); | ||||
| attribute.finish(); | attribute.finish(); | ||||
| return true; | return true; | ||||
| }); | }); | ||||
| MutableSpan<MVert> new_verts = mesh.verts_for_write().slice(new_vert_range); | MutableSpan<float3> new_positions = mesh.positions_for_write().slice(new_vert_range); | ||||
| if (edge_offsets.is_single()) { | if (edge_offsets.is_single()) { | ||||
| const float3 offset = edge_offsets.get_internal_single(); | const float3 offset = edge_offsets.get_internal_single(); | ||||
| threading::parallel_for(new_verts.index_range(), 1024, [&](const IndexRange range) { | threading::parallel_for(new_positions.index_range(), 1024, [&](const IndexRange range) { | ||||
| for (const int i : range) { | for (const int i : range) { | ||||
| add_v3_v3(new_verts[i].co, offset); | new_positions[i] += offset; | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| else { | else { | ||||
| threading::parallel_for(new_verts.index_range(), 1024, [&](const IndexRange range) { | threading::parallel_for(new_positions.index_range(), 1024, [&](const IndexRange range) { | ||||
| for (const int i : range) { | for (const int i : range) { | ||||
| add_v3_v3(new_verts[i].co, vert_offsets[new_vert_indices[i]]); | new_positions[i] += vert_offsets[new_vert_indices[i]]; | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | ||||
| vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | ||||
| MutableSpan<int> edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | MutableSpan<int> edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| attribute.finish(); | attribute.finish(); | ||||
| return true; | return true; | ||||
| }); | }); | ||||
| /* Translate vertices based on the offset. If the vertex is used by a selected edge, it will | /* Translate vertices based on the offset. If the vertex is used by a selected edge, it will | ||||
| * have been duplicated and only the new vertex should use the offset. Otherwise the vertex might | * have been duplicated and only the new vertex should use the offset. Otherwise the vertex might | ||||
| * still need an offset, but it was reused on the inside of a region of extruded faces. */ | * still need an offset, but it was reused on the inside of a region of extruded faces. */ | ||||
| MutableSpan<MVert> verts = mesh.verts_for_write(); | MutableSpan<float3> positions = mesh.positions_for_write(); | ||||
| if (poly_offsets.is_single()) { | if (poly_offsets.is_single()) { | ||||
| const float3 offset = poly_offsets.get_internal_single(); | const float3 offset = poly_offsets.get_internal_single(); | ||||
| threading::parallel_for( | threading::parallel_for( | ||||
| IndexRange(all_selected_verts.size()), 1024, [&](const IndexRange range) { | IndexRange(all_selected_verts.size()), 1024, [&](const IndexRange range) { | ||||
| for (const int i_orig : all_selected_verts.as_span().slice(range)) { | for (const int i_orig : all_selected_verts.as_span().slice(range)) { | ||||
| const int i_new = new_vert_indices.index_of_try(i_orig); | const int i_new = new_vert_indices.index_of_try(i_orig); | ||||
| MVert &vert = verts[(i_new == -1) ? i_orig : new_vert_range[i_new]]; | if (i_new == -1) { | ||||
| add_v3_v3(vert.co, offset); | positions[i_orig] += offset; | ||||
| } | |||||
| else { | |||||
| positions[new_vert_range[i_new]] += offset; | |||||
| } | |||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| else { | else { | ||||
| threading::parallel_for( | threading::parallel_for( | ||||
| IndexRange(all_selected_verts.size()), 1024, [&](const IndexRange range) { | IndexRange(all_selected_verts.size()), 1024, [&](const IndexRange range) { | ||||
| for (const int i_orig : all_selected_verts.as_span().slice(range)) { | for (const int i_orig : all_selected_verts.as_span().slice(range)) { | ||||
| const int i_new = new_vert_indices.index_of_try(i_orig); | const int i_new = new_vert_indices.index_of_try(i_orig); | ||||
| const float3 offset = vert_offsets[i_orig]; | const float3 offset = vert_offsets[i_orig]; | ||||
| MVert &vert = verts[(i_new == -1) ? i_orig : new_vert_range[i_new]]; | if (i_new == -1) { | ||||
| add_v3_v3(vert.co, offset); | positions[i_orig] += offset; | ||||
| } | |||||
| else { | |||||
| positions[new_vert_range[i_new]] += offset; | |||||
| } | |||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | ||||
| vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | ||||
| MutableSpan<int> edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | MutableSpan<int> edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | ||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
| const IndexRange side_loop_range{orig_loops.size(), side_poly_range.size() * 4}; | const IndexRange side_loop_range{orig_loops.size(), side_poly_range.size() * 4}; | ||||
| expand_mesh(mesh, | expand_mesh(mesh, | ||||
| new_vert_range.size(), | new_vert_range.size(), | ||||
| connect_edge_range.size() + duplicate_edge_range.size(), | connect_edge_range.size() + duplicate_edge_range.size(), | ||||
| side_poly_range.size(), | side_poly_range.size(), | ||||
| side_loop_range.size()); | side_loop_range.size()); | ||||
| MutableSpan<MVert> new_verts = mesh.verts_for_write().slice(new_vert_range); | MutableSpan<float3> new_positions = mesh.positions_for_write().slice(new_vert_range); | ||||
| MutableSpan<MEdge> edges = mesh.edges_for_write(); | MutableSpan<MEdge> edges = mesh.edges_for_write(); | ||||
| MutableSpan<MEdge> connect_edges = edges.slice(connect_edge_range); | MutableSpan<MEdge> connect_edges = edges.slice(connect_edge_range); | ||||
| MutableSpan<MEdge> duplicate_edges = edges.slice(duplicate_edge_range); | MutableSpan<MEdge> duplicate_edges = edges.slice(duplicate_edge_range); | ||||
| MutableSpan<MPoly> polys = mesh.polys_for_write(); | MutableSpan<MPoly> polys = mesh.polys_for_write(); | ||||
| MutableSpan<MPoly> new_polys = polys.slice(side_poly_range); | MutableSpan<MPoly> new_polys = polys.slice(side_poly_range); | ||||
| MutableSpan<MLoop> loops = mesh.loops_for_write(); | MutableSpan<MLoop> loops = mesh.loops_for_write(); | ||||
| /* For every selected polygon, build the faces that form the sides of the extrusion. Filling some | /* For every selected polygon, build the faces that form the sides of the extrusion. Filling some | ||||
| ▲ Show 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | |||||
| attribute.finish(); | attribute.finish(); | ||||
| return true; | return true; | ||||
| }); | }); | ||||
| /* Offset the new vertices. */ | /* Offset the new vertices. */ | ||||
| threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) { | threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) { | ||||
| for (const int i_selection : range) { | for (const int i_selection : range) { | ||||
| const IndexRange poly_corner_range = selected_corner_range(index_offsets, i_selection); | const IndexRange poly_corner_range = selected_corner_range(index_offsets, i_selection); | ||||
| for (MVert &vert : new_verts.slice(poly_corner_range)) { | for (float3 &position : new_positions.slice(poly_corner_range)) { | ||||
| add_v3_v3(vert.co, poly_offset[poly_selection[i_selection]]); | position += poly_offset[poly_selection[i_selection]]; | ||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||
| MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT); | ||||
| vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE); | ||||
| MutableSpan<int> edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | MutableSpan<int> edge_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_EDGE); | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||