Cleanup: move flip faces code from nodes to geometry module

This commit is contained in:
Jacques Lucke
2023-03-30 18:43:46 +02:00
parent 55d473ee40
commit a145d1563a
4 changed files with 89 additions and 42 deletions
+2
View File
@@ -18,6 +18,7 @@ set(SRC
intern/add_curves_on_mesh.cc
intern/curve_constraints.cc
intern/fillet_curves.cc
intern/mesh_flip_faces.cc
intern/mesh_merge_by_distance.cc
intern/mesh_primitive_cuboid.cc
intern/mesh_split_edges.cc
@@ -37,6 +38,7 @@ set(SRC
GEO_add_curves_on_mesh.hh
GEO_curve_constraints.hh
GEO_fillet_curves.hh
GEO_mesh_flip_faces.hh
GEO_mesh_merge_by_distance.hh
GEO_mesh_primitive_cuboid.hh
GEO_mesh_split_edges.hh
@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_index_mask.hh"
struct Mesh;
namespace blender::geometry {
/**
* Reverse the order of the vertices in the selected faces. This effectively changes the
* direction of the face normal.
*/
void flip_faces(Mesh &mesh, const IndexMask &selection);
} // namespace blender::geometry
@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "GEO_mesh_flip_faces.hh"
#include "DNA_mesh_types.h"
#include "BLI_task.hh"
#include "BKE_attribute.hh"
#include "BKE_attribute_math.hh"
#include "BKE_mesh.hh"
namespace blender::geometry {
void flip_faces(Mesh &mesh, const IndexMask &selection)
{
if (mesh.totpoly == 0 || selection.is_empty()) {
return;
}
const Span<MPoly> polys = mesh.polys();
MutableSpan<int> corner_verts = mesh.corner_verts_for_write();
MutableSpan<int> corner_edges = mesh.corner_edges_for_write();
threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) {
for (const int i : selection.slice(range)) {
const IndexRange poly(polys[i].loopstart, polys[i].totloop);
for (const int j : IndexRange(poly.size() / 2)) {
const int a = poly[j + 1];
const int b = poly.last(j);
std::swap(corner_verts[a], corner_verts[b]);
std::swap(corner_edges[a - 1], corner_edges[b]);
}
}
});
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.for_all(
[&](const bke::AttributeIDRef &attribute_id, const bke::AttributeMetaData &meta_data) {
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (meta_data.domain != ATTR_DOMAIN_CORNER) {
return true;
}
if (ELEM(attribute_id.name(), ".corner_vert", ".corner_edge")) {
return true;
}
bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(attribute_id);
attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
using T = decltype(dummy);
MutableSpan<T> dst_span = attribute.span.typed<T>();
threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) {
for (const int i : selection.slice(range)) {
const IndexRange poly(polys[i].loopstart, polys[i].totloop);
dst_span.slice(poly.drop_front(1)).reverse();
}
});
});
attribute.finish();
return true;
});
BKE_mesh_tag_topology_changed(&mesh);
}
} // namespace blender::geometry
@@ -7,6 +7,8 @@
#include "BKE_attribute_math.hh"
#include "GEO_mesh_flip_faces.hh"
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_flip_faces_cc {
@@ -29,48 +31,7 @@ static void mesh_flip_faces(Mesh &mesh, const Field<bool> &selection_field)
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_as_mask(0);
const Span<MPoly> polys = mesh.polys();
MutableSpan<int> corner_verts = mesh.corner_verts_for_write();
MutableSpan<int> corner_edges = mesh.corner_edges_for_write();
threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) {
for (const int i : selection.slice(range)) {
const IndexRange poly(polys[i].loopstart, polys[i].totloop);
for (const int j : IndexRange(poly.size() / 2)) {
const int a = poly[j + 1];
const int b = poly.last(j);
std::swap(corner_verts[a], corner_verts[b]);
std::swap(corner_edges[a - 1], corner_edges[b]);
}
}
});
MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.for_all(
[&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (meta_data.domain != ATTR_DOMAIN_CORNER) {
return true;
}
if (ELEM(attribute_id.name(), ".corner_vert", ".corner_edge")) {
return true;
}
GSpanAttributeWriter attribute = attributes.lookup_for_write_span(attribute_id);
attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
using T = decltype(dummy);
MutableSpan<T> dst_span = attribute.span.typed<T>();
threading::parallel_for(selection.index_range(), 1024, [&](const IndexRange range) {
for (const int i : selection.slice(range)) {
const IndexRange poly(polys[i].loopstart, polys[i].totloop);
dst_span.slice(poly.drop_front(1)).reverse();
}
});
});
attribute.finish();
return true;
});
geometry::flip_faces(mesh, selection);
}
static void node_geo_exec(GeoNodeExecParams params)