Blender V4.3
sculpt_flood_fill.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
5
6#include "BKE_mesh.hh"
7
8#include "DNA_mesh_types.h"
9
10#include "paint_intern.hh"
11#include "sculpt_hide.hh"
12#include "sculpt_intern.hh"
13
14/* -------------------------------------------------------------------- */
21
22void FillDataMesh::add_initial(const int vertex)
23{
24 this->queue.push(vertex);
25}
26
28{
29 for (const int vert : verts) {
30 this->add_initial(vert);
31 }
32}
33
35{
36 this->queue.push(vertex);
37}
38
40{
41 for (const int vert : verts) {
43 }
44}
45
47{
48 this->queue.push(vertex);
49}
50
52{
53 for (const int vert : verts) {
54 this->add_initial(BM_vert_at_index(&bm, vert));
55 }
56}
57
59{
60 this->queue.push(vertex);
61 this->visited_verts[vertex].set();
62}
63
64void FillDataGrids::add_and_skip_initial(const SubdivCCGCoord vertex, const int index)
65{
66 this->queue.push(vertex);
67 this->visited_verts[index].set();
68}
69
70void FillDataBMesh::add_and_skip_initial(BMVert *vertex, const int index)
71{
72 this->queue.push(vertex);
73 this->visited_verts[index].set();
74}
75
77 const GroupedSpan<int> vert_to_face_map,
78 FunctionRef<bool(int from_v, int to_v)> func)
79{
80 Mesh &mesh = *static_cast<Mesh *>(object.data);
81 const OffsetIndices faces = mesh.faces();
82 const Span<int> corner_verts = mesh.corner_verts();
83 const bke::AttributeAccessor attributes = mesh.attributes();
84 const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
85 const VArray hide_vert = *attributes.lookup_or_default<bool>(
86 ".hide_vert", bke::AttrDomain::Point, false);
87
88 Vector<int> neighbors;
89 while (!this->queue.empty()) {
90 const int from_v = this->queue.front();
91 this->queue.pop();
92
93 for (const int neighbor : vert_neighbors_get_mesh(
94 faces, corner_verts, vert_to_face_map, hide_poly, from_v, neighbors))
95 {
96 if (this->visited_verts[neighbor]) {
97 continue;
98 }
99
100 if (!hide_vert.is_empty() && hide_vert[neighbor]) {
101 continue;
102 }
103
104 this->visited_verts[neighbor].set();
105 if (func(from_v, neighbor)) {
106 this->queue.push(neighbor);
107 }
108 }
109 }
110}
111
113 Object & /*object*/,
114 const SubdivCCG &subdiv_ccg,
115 FunctionRef<bool(SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate)> func)
116{
117 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
118 while (!this->queue.empty()) {
119 SubdivCCGCoord from_v = this->queue.front();
120 this->queue.pop();
121
122 SubdivCCGNeighbors neighbors;
123 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, from_v, true, neighbors);
124 const int num_unique = neighbors.coords.size() - neighbors.num_duplicates;
125
126 /* Flood fill expects the duplicate entries to be passed to the per-neighbor lambda first, so
127 * iterate from the end of the vector to the beginning. */
128 for (int i = neighbors.coords.size() - 1; i >= 0; i--) {
129 SubdivCCGCoord neighbor = neighbors.coords[i];
130 const int index_in_grid = neighbor.y * key.grid_size + neighbor.x;
131 const int index = neighbor.grid_index * key.grid_area + index_in_grid;
132 if (this->visited_verts[index]) {
133 continue;
134 }
135
136 if (!subdiv_ccg.grid_hidden.is_empty() &&
137 subdiv_ccg.grid_hidden[neighbor.grid_index][index_in_grid])
138 {
139 continue;
140 }
141
142 this->visited_verts[index].set();
143 const bool is_duplicate = i >= num_unique;
144 if (func(from_v, neighbor, is_duplicate)) {
145 this->queue.push(neighbor);
146 }
147 }
148 }
149}
150
152 FunctionRef<bool(BMVert *from_v, BMVert *to_v)> func)
153{
154 Vector<BMVert *, 64> neighbors;
155 while (!this->queue.empty()) {
156 BMVert *from_v = this->queue.front();
157 this->queue.pop();
158
159 for (BMVert *neighbor : vert_neighbors_get_bmesh(*from_v, neighbors)) {
160 const int neighbor_idx = BM_elem_index_get(neighbor);
161 if (this->visited_verts[neighbor_idx]) {
162 continue;
163 }
164
165 if (BM_elem_flag_test(neighbor, BM_ELEM_HIDDEN)) {
166 continue;
167 }
168
169 this->visited_verts[neighbor_idx].set();
170 if (func(from_v, neighbor)) {
171 this->queue.push(neighbor);
172 }
173 }
174 }
175}
176
177} // namespace blender::ed::sculpt_paint::flood_fill
178
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
@ BM_ELEM_HIDDEN
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
ATTR_WARN_UNUSED_RESULT BMesh * bm
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
int64_t size() const
static float verts[][3]
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
Definition sculpt.cc:389
Span< int > vert_neighbors_get_mesh(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face, const Span< bool > hide_poly, const int vert, Vector< int > &r_neighbors)
Definition sculpt.cc:431
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
static SubdivCCGCoord from_index(const CCGKey &key, int index)
blender::Vector< SubdivCCGCoord, 256 > coords
blender::BitGroupVector grid_hidden
void execute(Object &object, FunctionRef< bool(BMVert *from_v, BMVert *to_v)> func)
void execute(Object &object, const SubdivCCG &subdiv_ccg, FunctionRef< bool(SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate)> func)
void add_and_skip_initial(SubdivCCGCoord vertex, int index)
void execute(Object &object, GroupedSpan< int > vert_to_face_map, FunctionRef< bool(int from_v, int to_v)> func)