Blender V4.3
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
11#include "BLI_linklist_stack.h"
12#include "BLI_utildefines.h"
13
14#include "bmesh.hh"
15
16#include "intern/bmesh_operators_private.hh" /* own include */
17
22{
23 BMLoop *l_iter;
24 l_iter = l->radial_next;
25 do {
26 if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG) == 0) {
27 return false;
28 }
29 } while ((l_iter = l_iter->radial_next) != l);
30
31 return true;
32}
33
37static bool bm_loop_is_face_untag(const BMLoop *l, void * /*user_data*/)
38{
39 return (BM_elem_flag_test(l->f, BM_ELEM_TAG) == 0);
40}
41
46 BMLoop *l,
47 const bool use_normals,
48 const bool use_data)
49{
50 BMLoop *l_other = l->radial_next;
51 BMFace *f = l->f, *f_other;
52 while (BM_elem_flag_test(l_other->f, BM_ELEM_TAG)) {
53 l_other = l_other->radial_next;
54 }
55 f_other = l_other->f;
56
57 if (use_data) {
58 /* copy face-attrs */
59 BM_elem_attrs_copy(bm, f_other, f);
60
61 /* copy loop-attrs */
63 }
64
65 if (use_normals) {
66 /* copy winding (flipping) */
67 if (l->v == l_other->v) {
69 }
70 }
71}
72
76static uint bmesh_face_attribute_fill(BMesh *bm, const bool use_normals, const bool use_data)
77{
78 BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *);
79 BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *);
80
81 BMFace *f;
82 BMIter iter;
83 BMLoop *l;
84
85 uint face_tot = 0;
86
87 BLI_LINKSTACK_INIT(loop_queue_prev);
88 BLI_LINKSTACK_INIT(loop_queue_next);
89
90 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
92 BMLoop *l_iter, *l_first;
93 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
94 do {
95 if (bm_loop_is_all_radial_tag(l_iter) == false) {
96 BLI_LINKSTACK_PUSH(loop_queue_prev, l_iter);
97 }
98 } while ((l_iter = l_iter->next) != l_first);
99 }
100 }
101
102 while (BLI_LINKSTACK_SIZE(loop_queue_prev)) {
103 while ((l = BLI_LINKSTACK_POP(loop_queue_prev))) {
104 /* check we're still un-assigned */
106 BMLoop *l_iter;
107
109
110 l_iter = l->next;
111 do {
112 BMLoop *l_radial_iter = l_iter->radial_next;
113 if (l_radial_iter != l_iter) {
114 do {
115 if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
116 BLI_LINKSTACK_PUSH(loop_queue_next, l_radial_iter);
117 }
118 } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
119 }
120 } while ((l_iter = l_iter->next) != l);
121
122 /* do last because of face flipping */
123 bm_face_copy_shared_all(bm, l, use_normals, use_data);
124 face_tot += 1;
125 }
126 }
127
128 BLI_LINKSTACK_SWAP(loop_queue_prev, loop_queue_next);
129 }
130
131 BLI_LINKSTACK_FREE(loop_queue_prev);
132 BLI_LINKSTACK_FREE(loop_queue_next);
133
134 return face_tot;
135}
136
138{
139 const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
140 const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
141
142 int face_tot;
143
145
146 /* do inline */
148
149 /* now we can copy adjacent data */
150 face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data);
151
152 if (face_tot != BMO_slot_buffer_len(op->slots_in, "faces")) {
153 /* any remaining tags will be skipped */
155 bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG);
156 }
157}
unsigned int uint
@ BM_ELEM_TAG
#define BM_FACE_FIRST_LOOP(p)
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
ATTR_WARN_UNUSED_RESULT 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]