Files
test/source/blender/geometry/intern/mesh_flip_faces.cc
Hans Goudey 367145209c Cleanup: Move attribute_math to proper blenkernel namespace
The fact that blenlib doesn't know about the set of attribute types is
actually an important detail right now that can influence how things
are designed. Longer term it would be good to consolidate many of
these attribute propagation algorithms anyway.
2023-05-03 12:10:54 -04:00

67 lines
2.1 KiB
C++

/* 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 OffsetIndices 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];
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);
bke::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)) {
dst_span.slice(polys[i].drop_front(1)).reverse();
}
});
});
attribute.finish();
return true;
});
BKE_mesh_tag_face_winding_changed(&mesh);
}
} // namespace blender::geometry