[Bf-blender-cvs] [780e2bfb58b] temp-geometry-nodes-extrude-mesh: Finish attribute interpolation for edges mode
Hans Goudey
noreply at git.blender.org
Wed Jan 5 00:53:52 CET 2022
Commit: 780e2bfb58b1df22bbebb04b63e71f4685d68683
Author: Hans Goudey
Date: Tue Jan 4 17:53:43 2022 -0600
Branches: temp-geometry-nodes-extrude-mesh
https://developer.blender.org/rB780e2bfb58b1df22bbebb04b63e71f4685d68683
Finish attribute interpolation for edges 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 f5f10ec6a8d..6dd938ac16c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -128,13 +128,14 @@ static void expand_mesh_size(Mesh &mesh,
}
}
-static Array<Vector<int>> create_vert_to_edge_map(const Mesh &mesh)
+static Array<Vector<int>> create_vert_to_edge_map(const int vert_size,
+ Span<MEdge> edges,
+ const int vert_offset = 0)
{
- Span<MEdge> edges = bke::mesh_edges(mesh);
- Array<Vector<int>> vert_to_edge_map(mesh.totvert);
+ Array<Vector<int>> vert_to_edge_map(vert_size);
for (const int i : edges.index_range()) {
- vert_to_edge_map[edges[i].v1].append(i);
- vert_to_edge_map[edges[i].v2].append(i);
+ vert_to_edge_map[edges[i].v1 - vert_offset].append(i);
+ vert_to_edge_map[edges[i].v2 - vert_offset].append(i);
}
return vert_to_edge_map;
}
@@ -156,7 +157,8 @@ static void extrude_mesh_vertices(MeshComponent &component,
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
const VArray<float3> offsets = evaluator.get_evaluated<float3>(0);
- Array<Vector<int>> vert_to_edge_map = create_vert_to_edge_map(mesh);
+ Array<Vector<int>> vert_to_edge_map = create_vert_to_edge_map(orig_vert_size,
+ bke::mesh_edges(mesh));
expand_mesh_size(mesh, selection.size(), selection.size(), 0, 0);
@@ -196,8 +198,8 @@ static void extrude_mesh_vertices(MeshComponent &component,
MutableSpan<T> new_data = data.slice(new_edge_range);
threading::parallel_for(selection.index_range(), 512, [&](const IndexRange range) {
for (const int i : range) {
- /* Create a separate mixer for every point to avoid allocating temporary buffers
- * in the mixer the size of the result point cloud and to allow multi-threading. */
+ /* Create a separate mixer for every point to avoid allocating temporary
+ * buffers in the mixer the size of the result and to allow multi-threading. */
attribute_math::DefaultMixer<T> mixer{new_data.slice(i, 1)};
const int i_src_vert = selection[i];
@@ -437,6 +439,12 @@ static void extrude_mesh_edges(MeshComponent &component,
connect_edge_range[extrude_index_2]);
}
+ /* Create a map of all of an index in the extruded vertices array to all of the indices of edges
+ * in the duplicate edges array that connect to that vertex. This can be used to simplify the
+ * mixing of attribute data for the connecting edges. */
+ Array<Vector<int>> new_vert_to_duplicate_edge_map = create_vert_to_edge_map(
+ new_vert_range.size(), duplicate_edges, orig_vert_size);
+
component.attribute_foreach([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
OutputAttribute attribute = component.attribute_try_get_for_output(
id, meta_data.domain, meta_data.data_type);
@@ -457,25 +465,37 @@ static void extrude_mesh_edges(MeshComponent &component,
}
case ATTR_DOMAIN_EDGE: {
MutableSpan<T> duplicate_data = data.slice(duplicate_edge_range);
- MutableSpan<T> connect_data = data.slice(connect_edge_range);
- connect_data.fill(T());
for (const int i : edge_selection.index_range()) {
duplicate_data[i] = data[edge_selection[i]];
}
+ MutableSpan<T> connect_data = data.slice(connect_edge_range);
+ threading::parallel_for(connect_data.index_range(), 512, [&](const IndexRange range) {
+ for (const int i : range) {
+ /* Create a separate mixer for every point to avoid allocating temporary
+ * buffers in the mixer the size of the result and to allow multi-threading. */
+ attribute_math::DefaultMixer<T> mixer{connect_data.slice(i, 1)};
+
+ for (const int i_connected_duplicate_edge : new_vert_to_duplicate_edge_map[i]) {
+ /* Use the duplicate data because it's slightly simpler to access and was just
+ * filled in the previous loop. */
+ mixer.mix_in(0, duplicate_data[i_connected_duplicate_edge]);
+ }
+
+ mixer.finalize();
+ }
+ });
break;
}
case ATTR_DOMAIN_FACE: {
MutableSpan<T> new_data = data.slice(new_poly_range);
threading::parallel_for(edge_selection.index_range(), 512, [&](const IndexRange range) {
for (const int i : range) {
- /* Create a separate mixer for every point to avoid allocating temporary buffers
- * in the mixer the size of the result point cloud and to allow multi-threading. */
+ /* Create a separate mixer for every point to avoid allocating temporary
+ * buffers in the mixer the size of the result and to allow multi-threading. */
attribute_math::DefaultMixer<T> mixer{new_data.slice(i, 1)};
const int i_src_edge = edge_selection[i];
- Span<int> connected_polys = edge_to_poly_map[i_src_edge];
-
- for (const int i_connected_poly : connected_polys) {
+ for (const int i_connected_poly : edge_to_poly_map[i_src_edge]) {
mixer.mix_in(0, data[i_connected_poly]);
}
@@ -486,7 +506,60 @@ static void extrude_mesh_edges(MeshComponent &component,
}
case ATTR_DOMAIN_CORNER: {
MutableSpan<T> new_data = data.slice(new_loop_range);
- new_data.fill(T());
+ threading::parallel_for(edge_selection.index_range(), 256, [&](const IndexRange range) {
+ for (const int i_edge_selection : range) {
+ const int orig_edge_index = edge_selection[i_edge_selection];
+
+ Span<int> connected_polys = edge_to_poly_map[orig_edge_index];
+ if (connected_polys.is_empty()) {
+ /* If there are no connected polygons, there is no corner data to
+ * interpolate. */
+ new_data.slice(4 * i_edge_selection, 4).fill(T());
+ continue;
+ }
+
+ /* Each corner at the same location if the offset is zero gets the same value,
+ * so there are two separate values for the corner data of this new polygon. */
+ Array<T> side_poly_corner_data(2);
+ attribute_math::DefaultMixer<T> mixer{side_poly_corner_data};
+
+ const MEdge &duplicate_edge = duplicate_edges[i_edge_selection];
+ const int new_vert_1 = duplicate_edge.v1;
+ const int new_vert_2 = duplicate_edge.v2;
+ const int orig_vert_1 = new_vert_orig_indices[new_vert_1 - orig_vert_size];
+ const int orig_vert_2 = new_vert_orig_indices[new_vert_2 - orig_vert_size];
+
+ /* Average the corner data from the corners that share a vertex from the
+ * polygons that share an edge with the extruded edge. */
+ for (const int i_connected_poly : connected_polys.index_range()) {
+ const MPoly &connected_poly = polys[connected_polys[i_connected_poly]];
+ for (const int i_loop :
+ IndexRange(connected_poly.loopstart, connected_poly.totloop)) {
+ const MLoop &loop = loops[i_loop];
+ if (loop.v == orig_vert_1) {
+ mixer.mix_in(0, data[i_loop]);
+ }
+ if (loop.v == orig_vert_2) {
+ mixer.mix_in(1, data[i_loop]);
+ }
+ }
+ }
+
+ mixer.finalize();
+
+ /* Instead of replicating the order in #fill_quad_consistent_direction here, it's
+ * simpler (though probably not faster) to just match the corner data based on the
+ * vertex indices. */
+ for (const int i : IndexRange(4 * i_edge_selection, 4)) {
+ if (ELEM(new_loops[i].v, new_vert_1, orig_vert_1)) {
+ new_data[i] = side_poly_corner_data.first();
+ }
+ else if (ELEM(new_loops[i].v, new_vert_2, orig_vert_2)) {
+ new_data[i] = side_poly_corner_data.last();
+ }
+ }
+ }
+ });
break;
}
default:
@@ -947,7 +1020,6 @@ static void extrude_individual_mesh_faces(MeshComponent &component,
}
}
});
-
break;
}
default:
More information about the Bf-blender-cvs
mailing list