Blender V4.3
bmo_fill_edgeloop.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 "MEM_guardedalloc.h"
12
13#include "bmesh.hh"
14
15#include "intern/bmesh_operators_private.hh" /* own include */
16
17#define VERT_USED 1
18#define EDGE_MARK 2
19#define ELE_OUT 4
20
22{
23 /* first collect an array of unique from the edges */
24 const int tote = BMO_slot_buffer_len(op->slots_in, "edges");
25 const int totv = tote; /* these should be the same */
26 BMVert **verts = static_cast<BMVert **>(MEM_mallocN(sizeof(*verts) * totv, __func__));
27
28 BMVert *v;
29 BMEdge *e;
30 int i;
31 bool ok = true;
32
33 BMOIter oiter;
34
35 const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
36 const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
37
38 /* 'VERT_USED' will be disabled, so enable and fill the array */
39 i = 0;
40 BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
41 BMIter viter;
43 BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
44 if (BMO_vert_flag_test(bm, v, VERT_USED) == false) {
45 if (i == tote) {
46 goto cleanup;
47 }
48
50 verts[i++] = v;
51 }
52 }
53 }
54
55 /* we have a different number of verts to edges */
56 if (i != tote) {
57 goto cleanup;
58 }
59
60 /* loop over connected flagged edges and fill in faces, this is made slightly more
61 * complicated because there may be multiple disconnected loops to fill. */
62
63 /* sanity check - that each vertex has 2 edge users */
64 for (i = 0; i < totv; i++) {
65 v = verts[i];
66 /* count how many flagged edges this vertex uses */
68 ok = false;
69 break;
70 }
71 }
72
73 if (ok) {
74 /* NOTE: in the case of multiple loops, this over-allocates (which is fine). */
75 BMVert **f_verts = static_cast<BMVert **>(MEM_mallocN(sizeof(*verts) * totv, __func__));
76 BMIter eiter;
77
78 /* build array of connected verts and edges */
79 BMEdge *e_prev = nullptr;
80 BMEdge *e_next = nullptr;
81 int totv_used = 0;
82
83 while (totv_used < totv) {
84 for (i = 0; i < totv; i++) {
85 v = verts[i];
87 break;
88 }
89 }
90
91 /* this should never fail, as long as (totv_used < totv)
92 * we should have marked verts available */
94
95 /* watch it, 'i' is used for final face length */
96 i = 0;
97 do {
98 /* we know that there are 2 edges per vertex so no need to check */
99 BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
101 if (e != e_prev) {
102 e_next = e;
103 break;
104 }
105 }
106 }
107
108 /* fill in the array */
109 f_verts[i] = v;
111 totv_used++;
112
113 /* step over the edges */
114 v = BM_edge_other_vert(e_next, v);
115 e_prev = e_next;
116 i++;
117 } while (v != f_verts[0]);
118
119 if (!BM_face_exists(f_verts, i)) {
120 BMFace *f;
121
122 /* don't use calc_edges option because we already have the edges */
123 f = BM_face_create_ngon_verts(bm, f_verts, i, nullptr, BM_CREATE_NOP, true, false);
125 f->mat_nr = mat_nr;
126 if (use_smooth) {
128 }
129 }
130 }
131 MEM_freeN(f_verts);
132
134 }
135
136cleanup:
138}
#define BLI_assert(a)
Definition BLI_assert.h:50
Read Guarded memory(de)allocation.
@ BM_ELEM_SMOOTH
BMFace * BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool calc_winding, const bool create_edges)
@ BM_CREATE_NOP
Definition bmesh_core.hh:24
#define BM_elem_flag_enable(ele, hflag)
int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value)
Elem Iter Tool Flag Count.
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_VERTS_OF_EDGE
@ BM_EDGES_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
#define BM_FACE
#define BM_EDGE
#define BMO_vert_flag_disable(bm, e, oflag)
#define BMO_edge_flag_test(bm, e, oflag)
#define BMO_edge_flag_enable(bm, e, oflag)
#define BMO_vert_flag_enable(bm, e, oflag)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, short oflag)
#define BMO_face_flag_enable(bm, e, oflag)
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
#define BMO_vert_flag_test(bm, e, oflag)
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
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)
BMFace * BM_face_exists(BMVert *const *varr, int len)
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define ELE_OUT
void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
#define VERT_USED
#define EDGE_MARK
static float verts[][3]
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
short mat_nr
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]