Blender V4.3
bmesh_mesh_validate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11/* debug builds only */
12#ifndef NDEBUG
13
14# include "BLI_map.hh"
15# include "BLI_ordered_edge.hh"
16# include "BLI_set.hh"
17# include "BLI_utildefines.h"
18
19# include "bmesh.hh"
20
21# include "bmesh_mesh_validate.hh"
22
23/* macro which inserts the function name */
24# if defined __GNUC__
25# define ERRMSG(format, args...) \
26 { \
27 fprintf(stderr, "%s: " format ", " AT "\n", __func__, ##args); \
28 errtot++; \
29 } \
30 (void)0
31# elif defined(_MSVC_TRADITIONAL) && !_MSVC_TRADITIONAL
32# define ERRMSG(format, ...) \
33 { \
34 fprintf(stderr, "%s: " format ", " AT "\n", __func__, ##__VA_ARGS__); \
35 errtot++; \
36 } \
37 (void)0
38# else
39# define ERRMSG(format, ...) \
40 { \
41 fprintf(stderr, "%s: " format ", " AT "\n", __func__, __VA_ARGS__); \
42 errtot++; \
43 } \
44 (void)0
45# endif
46
47template<> struct blender::DefaultHash<blender::Set<const BMVert *>> {
49 {
50 uint64_t hash = 0;
51 for (const BMVert *vert : value) {
52 hash = get_default_hash(hash, vert);
53 }
54 return hash;
55 }
56};
57
59{
61 edge_hash.reserve(bm->totedge);
62 int errtot;
63
64 BMIter iter;
65 BMVert *v;
66 BMEdge *e;
67 BMFace *f;
68
69 int i, j;
70
71 errtot = -1; /* 'ERRMSG' next line will set at zero */
72 fprintf(stderr, "\n");
73 ERRMSG("This is a debugging function and not intended for general use, running slow test!");
74
75 /* force recalc, even if tagged as valid, since this mesh is suspect! */
78
81 {
82 ERRMSG("vert %d: is hidden and selected", i);
83 }
84
85 if (v->e) {
86 if (!BM_vert_in_edge(v->e, v)) {
87 ERRMSG("vert %d: is not in its referenced edge: %d", i, BM_elem_index_get(v->e));
88 }
89 }
90 }
91
92 /* check edges */
94 if (e->v1 == e->v2) {
95 ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1));
96 }
97
98 /* Build edge-hash at the same time. */
99 edge_hash.add_or_modify(
101 [&](BMEdge **value) { *value = e; },
102 [&](BMEdge **value) {
103 ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(*value));
104 });
105 }
106
107 /* edge radial structure */
110 {
111 ERRMSG("edge %d: is hidden and selected", i);
112 }
113
114 if (e->l) {
115 BMLoop *l_iter;
116 BMLoop *l_first;
117
118 j = 0;
119
120 l_iter = l_first = e->l;
121 /* we could do more checks here, but save for face checks */
122 do {
123 if (l_iter->e != e) {
124 ERRMSG("edge %d: has invalid loop, loop is of face %d", i, BM_elem_index_get(l_iter->f));
125 }
126 else if (BM_vert_in_edge(e, l_iter->v) == false) {
127 ERRMSG("edge %d: has invalid loop with vert not in edge, loop is of face %d",
128 i,
129 BM_elem_index_get(l_iter->f));
130 }
131 else if (BM_vert_in_edge(e, l_iter->next->v) == false) {
132 ERRMSG("edge %d: has invalid loop with next vert not in edge, loop is of face %d",
133 i,
134 BM_elem_index_get(l_iter->f));
135 }
136 } while ((l_iter = l_iter->radial_next) != l_first);
137 }
138 }
139
140 /* face structure */
142 BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
143 BMLoop *l_iter;
144 BMLoop *l_first;
145
147 {
148 ERRMSG("face %d: is hidden and selected", i);
149 }
150
151 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
152
153 do {
157 } while ((l_iter = l_iter->next) != l_first);
158
159 j = 0;
160
162
163 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
164 do {
166 ERRMSG("face %d: has duplicate loop at corner: %d", i, j);
167 }
169 ERRMSG(
170 "face %d: has duplicate vert: %d, at corner: %d", i, BM_elem_index_get(l_iter->v), j);
171 }
173 ERRMSG(
174 "face %d: has duplicate edge: %d, at corner: %d", i, BM_elem_index_get(l_iter->e), j);
175 }
176
177 /* adjacent data checks */
178 if (l_iter->f != f) {
179 ERRMSG("face %d: has loop that points to face: %d at corner: %d",
180 i,
181 BM_elem_index_get(l_iter->f),
182 j);
183 }
184 if (l_iter != l_iter->prev->next) {
185 ERRMSG("face %d: has invalid 'prev/next' at corner: %d", i, j);
186 }
187 if (l_iter != l_iter->next->prev) {
188 ERRMSG("face %d: has invalid 'next/prev' at corner: %d", i, j);
189 }
190 if (l_iter != l_iter->radial_prev->radial_next) {
191 ERRMSG("face %d: has invalid 'radial_prev/radial_next' at corner: %d", i, j);
192 }
193 if (l_iter != l_iter->radial_next->radial_prev) {
194 ERRMSG("face %d: has invalid 'radial_next/radial_prev' at corner: %d", i, j);
195 }
196
200
201 face_verts.add(l_iter->v);
202
203 j++;
204 } while ((l_iter = l_iter->next) != l_first);
205
206 face_map.add_or_modify(
207 std::move(face_verts),
208 [&](int *value) { *value = i; },
209 [&](int *value) { ERRMSG("face %d: duplicate of %d", i, *value); });
210
211 if (j != f->len) {
212 ERRMSG("face %d: has length of %d but should be %d", i, f->len, j);
213 }
214
215 /* leave elements un-tagged, not essential but nice to avoid unintended dirty tag use later. */
216 do {
220 } while ((l_iter = l_iter->next) != l_first);
221 }
222
223 const bool is_valid = (errtot == 0);
224 ERRMSG("Finished - errors %d", errtot);
225 return is_valid;
226}
227
228#endif
@ BM_ELEM_HIDDEN
@ BM_ELEM_SELECT
@ BM_ELEM_INTERNAL_TAG
#define BM_ALL
#define BM_FACE_FIRST_LOOP(p)
#define BM_elem_index_get(ele)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
#define ERRMSG(format,...)
bool BM_mesh_validate(BMesh *bm)
BLI_INLINE bool BM_vert_in_edge(const 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
void reserve(int64_t n)
Definition BLI_map.hh:979
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition BLI_map.hh:457
bool add(const Key &key)
Definition BLI_set.hh:248
uint64_t get_default_hash(const T &v)
Definition BLI_hash.hh:219
#define hash
Definition noise.c:154
unsigned __int64 uint64_t
Definition stdint.h:90
struct BMVert * v
struct BMEdge * e
struct BMLoop * radial_prev
struct BMLoop * radial_next
struct BMLoop * prev
struct BMFace * f
struct BMLoop * next
struct BMEdge * e
char elem_index_dirty
int totedge
uint64_t operator()(const blender::Set< const BMVert * > &value) const