Blender V4.3
mesh_flip_faces.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "DNA_mesh_types.h"
7
8#include "BLI_task.hh"
9
10#include "BKE_attribute.hh"
11#include "BKE_attribute_math.hh"
12#include "BKE_customdata.hh"
13#include "BKE_mesh.hh"
14
15namespace blender::bke {
16
17template<typename T>
18static void flip_corner_data(const OffsetIndices<int> faces,
19 const IndexMask &face_selection,
20 MutableSpan<T> data)
21{
22 face_selection.foreach_index(GrainSize(1024),
23 [&](const int i) { data.slice(faces[i].drop_front(1)).reverse(); });
24}
25
26template<typename T>
28 CustomData &corner_data,
29 const IndexMask &face_selection,
30 const eCustomDataType data_type)
31{
32 BLI_assert(sizeof(T) == CustomData_sizeof(data_type));
33 for (const int i : IndexRange(CustomData_number_of_layers(&corner_data, data_type))) {
34 T *data = static_cast<T *>(
35 CustomData_get_layer_n_for_write(&corner_data, data_type, i, faces.total_size()));
36 flip_corner_data(faces, face_selection, MutableSpan(data, faces.total_size()));
37 }
38}
39
40void mesh_flip_faces(Mesh &mesh, const IndexMask &selection)
41{
42 if (mesh.faces_num == 0 || selection.is_empty()) {
43 return;
44 }
45
46 const OffsetIndices faces = mesh.faces();
47 MutableSpan<int> corner_verts = mesh.corner_verts_for_write();
48 MutableSpan<int> corner_edges = mesh.corner_edges_for_write();
49
50 selection.foreach_index(GrainSize(1024), [&](const int i) {
51 const IndexRange face = faces[i];
52 for (const int j : IndexRange(face.size() / 2)) {
53 const int a = face[j + 1];
54 const int b = face.last(j);
55 std::swap(corner_verts[a], corner_verts[b]);
56 std::swap(corner_edges[a - 1], corner_edges[b]);
57 }
58 });
59
60 flip_custom_data_type<float4>(faces, mesh.corner_data, selection, CD_TANGENT);
61 flip_custom_data_type<float4>(faces, mesh.corner_data, selection, CD_MLOOPTANGENT);
62 flip_custom_data_type<short2>(faces, mesh.corner_data, selection, CD_CUSTOMLOOPNORMAL);
63 flip_custom_data_type<GridPaintMask>(faces, mesh.corner_data, selection, CD_GRID_PAINT_MASK);
64 flip_custom_data_type<OrigSpaceLoop>(faces, mesh.corner_data, selection, CD_ORIGSPACE_MLOOP);
65 flip_custom_data_type<MDisps>(faces, mesh.corner_data, selection, CD_MDISPS);
66 if (MDisps *mdisp = static_cast<MDisps *>(
67 CustomData_get_layer_for_write(&mesh.corner_data, CD_MDISPS, mesh.corners_num)))
68 {
69 selection.foreach_index(GrainSize(512), [&](const int i) {
70 for (const int corner : faces[i]) {
71 BKE_mesh_mdisp_flip(&mdisp[corner], true);
72 }
73 });
74 }
75
76 MutableAttributeAccessor attributes = mesh.attributes_for_write();
77 attributes.foreach_attribute([&](const AttributeIter &iter) {
78 if (iter.data_type == CD_PROP_STRING) {
79 return;
80 }
81 if (iter.domain != AttrDomain::Corner) {
82 return;
83 }
84 if (ELEM(iter.name, ".corner_vert", ".corner_edge")) {
85 return;
86 }
87 GSpanAttributeWriter attribute = attributes.lookup_for_write_span(iter.name);
89 using T = decltype(dummy);
90 flip_corner_data(faces, selection, attribute.span.typed<T>());
91 });
92 attribute.finish();
93 });
94
95 mesh.tag_face_winding_changed();
96}
97
98} // namespace blender::bke
CustomData interface, see also DNA_customdata_types.h.
int CustomData_sizeof(eCustomDataType type)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_n_for_write(CustomData *data, eCustomDataType type, int n, int totelem)
void BKE_mesh_mdisp_flip(MDisps *md, bool use_loop_mdisp_flip)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
@ CD_MLOOPTANGENT
@ CD_CUSTOMLOOPNORMAL
@ CD_ORIGSPACE_MLOOP
@ CD_GRID_PAINT_MASK
@ CD_PROP_STRING
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
void foreach_index(Fn &&fn) const
local_group_size(16, 16) .push_constant(Type b
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
static void flip_corner_data(const OffsetIndices< int > faces, const IndexMask &face_selection, MutableSpan< T > data)
static void flip_custom_data_type(const OffsetIndices< int > faces, CustomData &corner_data, const IndexMask &face_selection, const eCustomDataType data_type)
void mesh_flip_faces(Mesh &mesh, const IndexMask &selection)