Blender V5.0
bmo_fill_attribute.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
10
11#include "BLI_linklist_stack.h"
12
13#include "bmesh.hh"
14
15#include "intern/bmesh_operators_private.hh" /* own include */
16
21{
22 BMLoop *l_iter;
23 l_iter = l->radial_next;
24 do {
25 if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG) == 0) {
26 return false;
27 }
28 } while ((l_iter = l_iter->radial_next) != l);
29
30 return true;
31}
32
36static bool bm_loop_is_face_untag(const BMLoop *l, void * /*user_data*/)
37{
38 return (BM_elem_flag_test(l->f, BM_ELEM_TAG) == 0);
39}
40
45 BMLoop *l,
46 const bool use_normals,
47 const bool use_data)
48{
49 BMLoop *l_other = l->radial_next;
50 BMFace *f = l->f, *f_other;
51 while (BM_elem_flag_test(l_other->f, BM_ELEM_TAG)) {
52 l_other = l_other->radial_next;
53 }
54 f_other = l_other->f;
55
56 if (use_data) {
57 /* copy face-attrs */
58 BM_elem_attrs_copy(bm, f_other, f);
59
60 /* copy loop-attrs */
62 }
63
64 if (use_normals) {
65 /* copy winding (flipping) */
66 if (l->v == l_other->v) {
68 }
69 }
70}
71
75static uint bmesh_face_attribute_fill(BMesh *bm, const bool use_normals, const bool use_data)
76{
77 BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *);
78 BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *);
79
80 BMFace *f;
81 BMIter iter;
82 BMLoop *l;
83
84 uint face_tot = 0;
85
86 BLI_LINKSTACK_INIT(loop_queue_prev);
87 BLI_LINKSTACK_INIT(loop_queue_next);
88
89 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
91 BMLoop *l_iter, *l_first;
92 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
93 do {
94 if (bm_loop_is_all_radial_tag(l_iter) == false) {
95 BLI_LINKSTACK_PUSH(loop_queue_prev, l_iter);
96 }
97 } while ((l_iter = l_iter->next) != l_first);
98 }
99 }
100
101 while (BLI_LINKSTACK_SIZE(loop_queue_prev)) {
102 while ((l = BLI_LINKSTACK_POP(loop_queue_prev))) {
103 /* check we're still un-assigned */
105 BMLoop *l_iter;
106
108
109 l_iter = l->next;
110 do {
111 BMLoop *l_radial_iter = l_iter->radial_next;
112 if (l_radial_iter != l_iter) {
113 do {
114 if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
115 BLI_LINKSTACK_PUSH(loop_queue_next, l_radial_iter);
116 }
117 } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
118 }
119 } while ((l_iter = l_iter->next) != l);
120
121 /* do last because of face flipping */
122 bm_face_copy_shared_all(bm, l, use_normals, use_data);
123 face_tot += 1;
124 }
125 }
126
127 BLI_LINKSTACK_SWAP(loop_queue_prev, loop_queue_next);
128 }
129
130 BLI_LINKSTACK_FREE(loop_queue_prev);
131 BLI_LINKSTACK_FREE(loop_queue_next);
132
133 return face_tot;
134}
135
137{
138 const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
139 const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
140
141 int face_tot;
142
144
145 /* do inline */
147
148 /* now we can copy adjacent data */
149 face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data);
150
151 if (face_tot != BMO_slot_buffer_len(op->slots_in, "faces")) {
152 /* any remaining tags will be skipped */
154 bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG);
155 }
156}
unsigned int uint
#define BM_FACE_FIRST_LOOP(p)
@ BM_ELEM_TAG
void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data)
copies face loop data from shared adjacent faces.
void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMVert *src, BMVert *dst)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
BMesh * bm
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
#define BM_FACE
void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, char hflag, bool do_flush)
BMO_FLAG_BUFFER.
void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, char hflag)
int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BM_face_normal_flip(BMesh *bm, BMFace *f)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
static bool bm_loop_is_all_radial_tag(BMLoop *l)
static bool bm_loop_is_face_untag(const BMLoop *l, void *)
static uint bmesh_face_attribute_fill(BMesh *bm, const bool use_normals, const bool use_data)
static void bm_face_copy_shared_all(BMesh *bm, BMLoop *l, const bool use_normals, const bool use_data)
struct BMVert * v
struct BMLoop * radial_next
struct BMFace * f
struct BMLoop * next
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]