[Bf-blender-cvs] [dae6a66c1bb] temp-geometry-nodes-extrude-mesh: Fix offset of selected vertices inside extrude regions in face mode
Hans Goudey
noreply at git.blender.org
Thu Jan 6 01:58:59 CET 2022
Commit: dae6a66c1bb4a8ae3818a4d821dccf5ffef18cc9
Author: Hans Goudey
Date: Wed Jan 5 18:58:49 2022 -0600
Branches: temp-geometry-nodes-extrude-mesh
https://developer.blender.org/rBdae6a66c1bb4a8ae3818a4d821dccf5ffef18cc9
Fix offset of selected vertices inside extrude regions in face mode
===================================================================
M source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
===================================================================
diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
index 1287dd4ec85..bab1d5b9554 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -15,6 +15,7 @@
*/
#include "BLI_task.hh"
+#include "BLI_vector_set.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -627,25 +628,46 @@ static void extrude_mesh_faces(MeshComponent &component,
const IndexMask poly_selection = poly_evaluator.get_evaluated_selection_as_mask();
const VArray<float3> &poly_offsets = poly_evaluator.get_evaluated<float3>(0);
+ Array<float3> vert_offsets;
+ if (!poly_offsets.is_single()) {
+ vert_offsets.reinitialize(orig_vert_size);
+ attribute_math::DefaultMixer<float3> mixer(vert_offsets);
+ for (const int i_poly : poly_selection) {
+ const MPoly &poly = orig_polys[i_poly];
+ const float3 offset = poly_offsets[i_poly];
+ for (const MLoop &loop : orig_loops.slice(poly.loopstart, poly.totloop)) {
+ mixer.mix_in(loop.v, offset);
+ }
+ }
+ mixer.finalize();
+ }
+
+ /* All vertices that are connected to the selected polygons. */
+ VectorSet<int> all_selected_verts;
/* Keep track of the selected face that each edge corresponds to. Only edges with one selected
* face will have a single associated face. However, we need to keep track of a value for every
* face in the mesh at this point, because we don't know how many edges will be selected for
- * extrusion in the end. */
+ * extrusion in the end. Alternatively, #mesh_calculate_polys_of_edge could be used, possibly
+ * simplifying the rest of this algorithm slightly, but at a higher up-front cost. */
Array<int> edge_face_indices(orig_edges.size(), -1);
+ /* The number of connected faces for every edge, just to tell which should be extruded. */
Array<int> edge_neighbor_count(orig_edges.size(), 0);
for (const int i_poly : poly_selection) {
const MPoly &poly = orig_polys[i_poly];
for (const MLoop &loop : orig_loops.slice(poly.loopstart, poly.totloop)) {
edge_neighbor_count[loop.e]++;
edge_face_indices[loop.e] = i_poly;
+ all_selected_verts.add(loop.v);
}
}
+ /* These edges are on top of an extruded region. Their vertices should be moved, but the edges
+ * themselves should not be duplicated. */
Vector<int> in_between_edges;
/* The extruded face corresponding to each extruded edge (and each extruded face). */
Vector<int> edge_orig_face_indices;
Vector<int64_t> selected_edges_orig_indices;
- for (const int i_edge : IndexRange(orig_edges.size())) {
+ for (const int i_edge : orig_edges.index_range()) {
if (edge_neighbor_count[i_edge] == 1) {
selected_edges_orig_indices.append(i_edge);
edge_orig_face_indices.append(edge_face_indices[i_edge]);
@@ -715,8 +737,7 @@ static void extrude_mesh_faces(MeshComponent &component,
poly.flag = 0;
}
- /* Connect original edges that are in between two selected faces to the new vertices.
- * The edge's vertices may have been extruded even though the edge itself was not. */
+ /* Connect original edges that are in between two selected faces to the new vertices. */
for (const int i : in_between_edges) {
MEdge &edge = edges[i];
if (new_vert_indices[edge.v1] != -1) {
@@ -867,40 +888,31 @@ static void extrude_mesh_faces(MeshComponent &component,
if (poly_offsets.is_single()) {
const float3 offset = poly_offsets.get_internal_single();
- threading::parallel_for(IndexRange(orig_vert_size), 1024, [&](const IndexRange range) {
- for (const int i_orig : range) {
- const int i_new = new_vert_indices[i_orig];
- /* 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 still need an offset, but it
- * was reused on the inside of a group of extruded faces. */
- MVert &vert = bke::mesh_verts(mesh)[(i_new != -1) ? i_new : i_orig];
- add_v3_v3(vert.co, offset);
- }
- });
+ threading::parallel_for(
+ IndexRange(all_selected_verts.size()), 1024, [&](const IndexRange range) {
+ for (const int i_orig : all_selected_verts.as_span().slice(range)) {
+ const int i_new = new_vert_indices[i_orig];
+ /* 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 still need an offset,
+ * but it was reused on the inside of a group of extruded faces. */
+ MVert &vert = bke::mesh_verts(mesh)[(i_new == -1) ? i_orig : i_new];
+ add_v3_v3(vert.co, offset);
+ }
+ });
}
else {
- Array<float3> vert_offsets(orig_vert_size);
- attribute_math::DefaultMixer<float3> mixer(vert_offsets);
- for (const int i_poly : poly_selection) {
- const MPoly &poly = orig_polys[i_poly];
- const float3 offset = poly_offsets[i_poly];
- for (const MLoop &loop : orig_loops.slice(poly.loopstart, poly.totloop)) {
- mixer.mix_in(loop.v, offset);
- }
- }
- mixer.finalize();
-
- threading::parallel_for(IndexRange(orig_vert_size), 1024, [&](const IndexRange range) {
- for (const int i_orig : range) {
- const int i_new = new_vert_indices[i_orig];
- const float3 offset = vert_offsets[i_orig];
- /* 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 still need an offset, but it
- * was reused on the inside of a group of extruded faces. */
- MVert &vert = bke::mesh_verts(mesh)[(i_new != -1) ? i_new : i_orig];
- add_v3_v3(vert.co, offset);
- }
- });
+ threading::parallel_for(
+ IndexRange(all_selected_verts.size()), 1024, [&](const IndexRange range) {
+ for (const int i_orig : all_selected_verts.as_span().slice(range)) {
+ const int i_new = new_vert_indices[i_orig];
+ const float3 offset = vert_offsets[i_orig];
+ /* 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 still need an offset,
+ * but it was reused on the inside of a group of extruded faces. */
+ MVert &vert = bke::mesh_verts(mesh)[(i_new == -1) ? i_orig : i_new];
+ add_v3_v3(vert.co, offset);
+ }
+ });
}
BKE_mesh_runtime_clear_cache(&mesh);
More information about the Bf-blender-cvs
mailing list