[Bf-blender-cvs] [94cb0355a92] temp-geometry-nodes-extrude-mesh: Add individual face mode
Hans Goudey
noreply at git.blender.org
Sun Jan 2 01:46:42 CET 2022
Commit: 94cb0355a923483f85e9a99a5cf1719512db1f9e
Author: Hans Goudey
Date: Sat Jan 1 18:46:26 2022 -0600
Branches: temp-geometry-nodes-extrude-mesh
https://developer.blender.org/rB94cb0355a923483f85e9a99a5cf1719512db1f9e
Add individual 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 9e32379a036..ecb936544f0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -41,6 +41,7 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_input<decl::Geometry>("Mesh").supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value();
b.add_input<decl::Vector>(N_("Offset")).supports_field().subtype(PROP_TRANSLATION);
+ b.add_input<decl::Bool>(N_("Individual"));
b.add_output<decl::Geometry>("Mesh");
b.add_output<decl::Bool>(N_("Top")).field_source();
b.add_output<decl::Bool>(N_("Side")).field_source();
@@ -743,6 +744,270 @@ static void extrude_mesh_faces(MeshComponent &component,
BLI_assert(BKE_mesh_is_valid(component.get_for_write()));
}
+static void extrude_individual_mesh_faces(MeshComponent &component,
+ const Field<bool> &selection_field,
+ const Field<float3> &offset_field,
+ const AttributeOutputs &attribute_outputs)
+{
+ Mesh &mesh = *component.get_for_write();
+ const int orig_vert_size = mesh.totvert;
+ const int orig_edge_size = mesh.totedge;
+ Span<MPoly> orig_polys{mesh.mpoly, mesh.totpoly};
+ Span<MLoop> orig_loops{mesh.mloop, mesh.totloop};
+
+ Array<float3> poly_offset(orig_polys.size());
+ GeometryComponentFieldContext poly_context{component, ATTR_DOMAIN_FACE};
+ FieldEvaluator poly_evaluator{poly_context, mesh.totpoly};
+ poly_evaluator.set_selection(selection_field);
+ poly_evaluator.add_with_destination(offset_field, poly_offset.as_mutable_span());
+ poly_evaluator.evaluate();
+ const IndexMask poly_selection = poly_evaluator.get_evaluated_selection_as_mask();
+
+ int extrude_corner_size = 0;
+ Array<int> index_offsets(poly_selection.size() + 1);
+ for (const int i_selection : poly_selection.index_range()) {
+ const MPoly &poly = orig_polys[poly_selection[i_selection]];
+ index_offsets[i_selection] = extrude_corner_size;
+ extrude_corner_size += poly.totloop;
+ }
+ index_offsets.last() = extrude_corner_size;
+
+ const IndexRange new_vert_range{orig_vert_size, extrude_corner_size};
+ /* One edge connects each selected vertex to a new vertex on the extruded polygons. */
+ const IndexRange connect_edge_range{orig_edge_size, extrude_corner_size};
+ /* Each selected edge is duplicated to form a single edge on the extrusion. */
+ const IndexRange duplicate_edge_range{connect_edge_range.one_after_last(), extrude_corner_size};
+ /* Each edge selected for extrusion is extruded into a single face. */
+ const IndexRange side_poly_range{orig_polys.size(), duplicate_edge_range.size()};
+ const IndexRange side_loop_range{orig_loops.size(), side_poly_range.size() * 4};
+
+ expand_mesh_size(mesh,
+ new_vert_range.size(),
+ connect_edge_range.size() + duplicate_edge_range.size(),
+ side_poly_range.size(),
+ side_loop_range.size());
+
+ MutableSpan<MVert> new_verts = bke::mesh_verts(mesh).slice(new_vert_range);
+ MutableSpan<MEdge> edges{mesh.medge, mesh.totedge};
+ MutableSpan<MEdge> connect_edges = edges.slice(connect_edge_range);
+ MutableSpan<MEdge> duplicate_edges = edges.slice(duplicate_edge_range);
+ MutableSpan<MPoly> polys{mesh.mpoly, mesh.totpoly};
+ MutableSpan<MPoly> new_polys = polys.slice(side_poly_range);
+ MutableSpan<MLoop> loops{mesh.mloop, mesh.totloop};
+
+ for (MVert &vert : new_verts) {
+ vert.flag = 0;
+ }
+
+ // threading::parallel_for(poly_selection.index_range(), 256, [&](const IndexRange range) {
+ // for (const int i_selection : poly_selection.slice(range)) {
+ // const int corner_offset = index_offsets[i_selection];
+ // const int corner_offset_next = index_offsets[i_selection + 1];
+ // const int poly_totloop = corner_offset_next - corner_offset;
+
+ // for (const int i : IndexRange(poly_totloop)) {
+ // const int i_next = (i == poly_totloop - 1) ? 0 : i + 1;
+ // const int i_extrude = corner_offset + i;
+ // const int i_extrude_next = corner_offset + i_next;
+
+ // const int i_duplicate_edge = duplicate_edge_range[i_extrude];
+
+ // MEdge &duplicate_edge = edges[i_duplicate_edge];
+ // duplicate_edge.v1 = new_vert_range[i_extrude];
+ // duplicate_edge.v2 = new_vert_range[i_extrude_next];
+ // duplicate_edge.flag = (ME_EDGEDRAW | ME_EDGERENDER);
+ // }
+ // }
+ // });
+
+ 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);
+ if (!attribute) {
+ return true; /* Impossible to write the "normal" attribute. */
+ }
+
+ attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
+ using T = decltype(dummy);
+ MutableSpan<T> data = attribute.as_span().typed<T>();
+ switch (attribute.domain()) {
+ case ATTR_DOMAIN_POINT: {
+ MutableSpan<T> new_data = data.slice(new_vert_range);
+
+ threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) {
+ for (const int i_selection : range) {
+ const MPoly &poly = polys[poly_selection[i_selection]];
+ Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
+
+ const int corner_offset = index_offsets[i_selection];
+ for (const int i : poly_loops.index_range()) {
+ const int orig_index = poly_loops[i].v;
+ new_data[corner_offset + i] = data[orig_index];
+ }
+ }
+ });
+ break;
+ }
+ 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());
+ threading::parallel_for(poly_selection.index_range(), 512, [&](const IndexRange range) {
+ for (const int i_selection : range) {
+ const MPoly &poly = polys[poly_selection[i_selection]];
+ Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
+
+ /* The data for the duplicate edge is simply a copy of the original edge's data. */
+ const int corner_offset = index_offsets[i_selection];
+ for (const int i : poly_loops.index_range()) {
+ const int orig_index = poly_loops[i].e;
+ duplicate_data[corner_offset + i] = data[orig_index];
+ }
+
+ /* For the extruded edges, mix the data from the two neighboring original edges of
+ * the polygon. */
+ for (const int i : poly_loops.index_range()) {
+ const int i_loop_next = (i == poly.totloop - 1) ? 0 : i + 1;
+ const int orig_index = poly_loops[i].e;
+ const int orig_index_next = poly_loops[i_loop_next].e;
+ connect_data[corner_offset + i] = attribute_math::mix2(
+ 0.5f, data[orig_index], data[orig_index_next]);
+ }
+ }
+ });
+ break;
+ }
+ case ATTR_DOMAIN_FACE: {
+ MutableSpan<T> new_data = data.slice(side_poly_range);
+
+ threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange range) {
+ for (const int i_selection : range) {
+ const int poly_index = poly_selection[i_selection];
+
+ const int corner_offset = index_offsets[i_selection];
+ const int corner_offset_next = index_offsets[i_selection + 1];
+
+ MutableSpan<T> side_poly_data = new_data.slice(corner_offset,
+ corner_offset_next - corner_offset);
+ side_poly_data.fill(data[poly_index]);
+ }
+ });
+ break;
+ }
+ case ATTR_DOMAIN_CORNER: {
+ MutableSpan<T> new_data = data.slice(side_loop_range);
+ new_data.fill(T());
+ // threading::parallel_for(poly_selection.index_range(), 1024, [&](const IndexRange
+ // range) {
+ // for (const int i_selection : range) {
+ // const int poly_index = poly_selection[i_selection];
+
+ // const int corner_offset = index_offsets[i_selection] * 4;
+ // const int corner_offset_next = index_offsets[i_selection + 1] * 4;
+
+ // MutableSpan<T> side_loop_data = new_data.slice(corner_offset,
+ // corner_offset_next -
+ // corner_offset);
+ // side_loop_data.fill(data[poly_index]);
+ // }
+ // });
+ break;
+ }
+ default:
+ BLI_assert_unreachable();
+ }
+ });
+
+ attribute.save();
+ return true;
+ });
+
+ /* Some of these loops could be easily split. */
+ threading::parallel_for(poly_selection.index_range(), 256, [&](const IndexRange range) {
+ for (const int i_selection : range) {
+ const MPoly &poly = polys[poly_selection[i_selection]];
+ MutableSpan<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
+
+ const int corner_offset = index_offsets[i_selection];
+
+ for (const int i : IndexRange(poly.totloop)) {
+ const int i_next = (i == poly.totloop - 1) ? 0 : i + 1;
+ const MLoop &loop = poly_loops[i];
+ const MLoop &loop_next = poly_loops[i_next];
+
+ const int i_extrude = corner_offset + i;
+ const int i_extrude_next = corner_offset + i_next;
+
+ const int i_duplicate_edge = duplicate_edge_range[i_extrude];
+ const int new_vert = new_vert_range[i_extrude];
+ const int new_vert_next = new_v
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list