Blender  V3.3
mesh_iterators.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "DNA_mesh_types.h"
10 #include "DNA_meshdata_types.h"
11 
12 #include "BKE_customdata.h"
13 #include "BKE_editmesh.h"
14 #include "BKE_editmesh_cache.h"
15 #include "BKE_mesh.h"
16 #include "BKE_mesh_iterators.h"
17 
18 #include "BLI_bitmap.h"
19 #include "BLI_math.h"
20 
21 #include "MEM_guardedalloc.h"
22 
23 /* General note on iterating verts/loops/edges/polys and end mode.
24  *
25  * The edit mesh pointer is set for both final and cage meshes in both cases when there are
26  * modifiers applied and not. This helps consistency of checks in the draw manager, where the
27  * existence of the edit mesh pointer does not depend on object configuration.
28  *
29  * For the iterating, however, we need to follow the `CD_ORIGINDEX` code paths when there are
30  * modifiers applied on the cage. In the code terms it means that the check for the edit mode code
31  * path needs to consist of both edit mesh and edit data checks. */
32 
34  Mesh *mesh,
35  void (*func)(void *userData, int index, const float co[3], const float no[3]),
36  void *userData,
37  MeshForeachFlag flag)
38 {
39  if (mesh->edit_mesh != NULL && mesh->runtime.edit_data != NULL) {
40  BMEditMesh *em = mesh->edit_mesh;
41  BMesh *bm = em->bm;
42  BMIter iter;
43  BMVert *eve;
44  int i;
45  if (mesh->runtime.edit_data->vertexCos != NULL) {
46  const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
47  const float(*vertexNos)[3];
48  if (flag & MESH_FOREACH_USE_NORMAL) {
50  vertexNos = mesh->runtime.edit_data->vertexNos;
51  }
52  else {
53  vertexNos = NULL;
54  }
55  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
56  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
57  func(userData, i, vertexCos[i], no);
58  }
59  }
60  else {
61  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
62  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? eve->no : NULL;
63  func(userData, i, eve->co, no);
64  }
65  }
66  }
67  else {
68  const MVert *mv = mesh->mvert;
69  const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
70  const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
72  NULL;
73 
74  if (index) {
75  for (int i = 0; i < mesh->totvert; i++, mv++) {
76  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[i] : NULL;
77  const int orig = *index++;
78  if (orig == ORIGINDEX_NONE) {
79  continue;
80  }
81  func(userData, orig, mv->co, no);
82  }
83  }
84  else {
85  for (int i = 0; i < mesh->totvert; i++, mv++) {
86  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[i] : NULL;
87  func(userData, i, mv->co, no);
88  }
89  }
90  }
91 }
92 
94  Mesh *mesh,
95  const int tot_edges,
96  void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
97  void *userData)
98 {
99  if (mesh->edit_mesh != NULL && mesh->runtime.edit_data) {
100  BMEditMesh *em = mesh->edit_mesh;
101  BMesh *bm = em->bm;
102  BMIter iter;
103  BMEdge *eed;
104  int i;
105  if (mesh->runtime.edit_data->vertexCos != NULL) {
106  const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
108 
109  BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
110  func(userData,
111  i,
112  vertexCos[BM_elem_index_get(eed->v1)],
113  vertexCos[BM_elem_index_get(eed->v2)]);
114  }
115  }
116  else {
117  BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
118  func(userData, i, eed->v1->co, eed->v2->co);
119  }
120  }
121  }
122  else {
123  const MVert *mv = mesh->mvert;
124  const MEdge *med = mesh->medge;
125  const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
126 
127  if (index) {
128  for (int i = 0; i < mesh->totedge; i++, med++) {
129  const int orig = *index++;
130  if (orig == ORIGINDEX_NONE) {
131  continue;
132  }
133  func(userData, orig, mv[med->v1].co, mv[med->v2].co);
134  }
135  }
136  else if (mesh->totedge == tot_edges) {
137  for (int i = 0; i < mesh->totedge; i++, med++) {
138  func(userData, i, mv[med->v1].co, mv[med->v2].co);
139  }
140  }
141  }
142 }
143 
145  void (*func)(void *userData,
146  int vertex_index,
147  int face_index,
148  const float co[3],
149  const float no[3]),
150  void *userData,
151  MeshForeachFlag flag)
152 {
153 
154  /* We can't use dm->getLoopDataLayout(dm) here,
155  * we want to always access dm->loopData, EditDerivedBMesh would
156  * return loop data from bmesh itself. */
157  if (mesh->edit_mesh != NULL && mesh->runtime.edit_data) {
158  BMEditMesh *em = mesh->edit_mesh;
159  BMesh *bm = em->bm;
160  BMIter iter;
161  BMFace *efa;
162 
163  const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
164 
165  /* XXX: investigate using EditMesh data. */
166  const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
168  NULL;
169 
170  int f_idx;
171 
173 
174  BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) {
175  BMLoop *l_iter, *l_first;
176 
177  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
178  do {
179  const BMVert *eve = l_iter->v;
180  const int v_idx = BM_elem_index_get(eve);
181  const float *no = lnors ? *lnors++ : NULL;
182  func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
183  } while ((l_iter = l_iter->next) != l_first);
184  }
185  }
186  else {
187  const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
189  NULL;
190 
191  const MVert *mv = mesh->mvert;
192  const MLoop *ml = mesh->mloop;
193  const MPoly *mp = mesh->mpoly;
194  const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
195  const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
196  int p_idx, i;
197 
198  if (v_index || f_index) {
199  for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
200  for (i = 0; i < mp->totloop; i++, ml++) {
201  const int v_idx = v_index ? v_index[ml->v] : ml->v;
202  const int f_idx = f_index ? f_index[p_idx] : p_idx;
203  const float *no = lnors ? *lnors++ : NULL;
204  if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
205  continue;
206  }
207  func(userData, v_idx, f_idx, mv[ml->v].co, no);
208  }
209  }
210  }
211  else {
212  for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
213  for (i = 0; i < mp->totloop; i++, ml++) {
214  const int v_idx = ml->v;
215  const int f_idx = p_idx;
216  const float *no = lnors ? *lnors++ : NULL;
217  func(userData, v_idx, f_idx, mv[ml->v].co, no);
218  }
219  }
220  }
221  }
222 }
223 
225  Mesh *mesh,
226  void (*func)(void *userData, int index, const float cent[3], const float no[3]),
227  void *userData,
228  MeshForeachFlag flag)
229 {
230  if (mesh->edit_mesh != NULL && mesh->runtime.edit_data != NULL) {
231  BMEditMesh *em = mesh->edit_mesh;
232  BMesh *bm = em->bm;
233  const float(*polyCos)[3];
234  const float(*polyNos)[3];
235  BMFace *efa;
236  BMIter iter;
237  int i;
238 
240  polyCos = mesh->runtime.edit_data->polyCos; /* always set */
241 
242  if (flag & MESH_FOREACH_USE_NORMAL) {
244  polyNos = mesh->runtime.edit_data->polyNos; /* maybe NULL */
245  }
246  else {
247  polyNos = NULL;
248  }
249 
250  if (polyNos) {
251  BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
252  const float *no = polyNos[i];
253  func(userData, i, polyCos[i], no);
254  }
255  }
256  else {
257  BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
258  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? efa->no : NULL;
259  func(userData, i, polyCos[i], no);
260  }
261  }
262  }
263  else {
264  const MVert *mvert = mesh->mvert;
265  const MPoly *mp = mesh->mpoly;
266  const MLoop *ml;
267  float _no_buf[3];
268  float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
269  const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
270 
271  if (index) {
272  for (int i = 0; i < mesh->totpoly; i++, mp++) {
273  const int orig = *index++;
274  if (orig == ORIGINDEX_NONE) {
275  continue;
276  }
277  float cent[3];
278  ml = &mesh->mloop[mp->loopstart];
279  BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
280  if (flag & MESH_FOREACH_USE_NORMAL) {
281  BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
282  }
283  func(userData, orig, cent, no);
284  }
285  }
286  else {
287  for (int i = 0; i < mesh->totpoly; i++, mp++) {
288  float cent[3];
289  ml = &mesh->mloop[mp->loopstart];
290  BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
291  if (flag & MESH_FOREACH_USE_NORMAL) {
292  BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
293  }
294  func(userData, i, cent, no);
295  }
296  }
297  }
298 }
299 
301  Mesh *mesh,
302  void (*func)(void *userData, int index, const float cent[3], const float no[3]),
303  void *userData,
304  MeshForeachFlag flag)
305 {
306  const MPoly *mp = mesh->mpoly;
307  const MLoop *ml;
308  const MVert *mv;
309  const float(*vert_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
311  NULL;
312  const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
313  const BLI_bitmap *facedot_tags = mesh->runtime.subsurf_face_dot_tags;
314  BLI_assert(facedot_tags != NULL);
315 
316  if (index) {
317  for (int i = 0; i < mesh->totpoly; i++, mp++) {
318  const int orig = *index++;
319  if (orig == ORIGINDEX_NONE) {
320  continue;
321  }
322  ml = &mesh->mloop[mp->loopstart];
323  for (int j = 0; j < mp->totloop; j++, ml++) {
324  mv = &mesh->mvert[ml->v];
325  if (BLI_BITMAP_TEST(facedot_tags, ml->v)) {
326  func(userData,
327  orig,
328  mv->co,
329  (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[ml->v] : NULL);
330  }
331  }
332  }
333  }
334  else {
335  for (int i = 0; i < mesh->totpoly; i++, mp++) {
336  ml = &mesh->mloop[mp->loopstart];
337  for (int j = 0; j < mp->totloop; j++, ml++) {
338  mv = &mesh->mvert[ml->v];
339  if (BLI_BITMAP_TEST(facedot_tags, ml->v)) {
340  func(userData, i, mv->co, (flag & MESH_FOREACH_USE_NORMAL) ? vert_normals[ml->v] : NULL);
341  }
342  }
343  }
344  }
345 }
346 
347 /* Helpers based on above foreach loopers> */
348 
349 typedef struct MappedVCosData {
353 
355  int index,
356  const float co[3],
357  const float UNUSED(no[3]))
358 {
359  MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
360 
361  if (BLI_BITMAP_TEST(mapped_vcos_data->vertex_visit, index) == 0) {
362  /* We need coord from prototype vertex, not from copies,
363  * we assume they stored in the beginning of vertex array stored in evaluated mesh
364  * (mirror modifier for eg does this). */
365  copy_v3_v3(mapped_vcos_data->vertexcos[index], co);
366  BLI_BITMAP_ENABLE(mapped_vcos_data->vertex_visit, index);
367  }
368 }
369 
370 void BKE_mesh_foreach_mapped_vert_coords_get(Mesh *me_eval, float (*r_cos)[3], const int totcos)
371 {
373  memset(r_cos, 0, sizeof(*r_cos) * totcos);
374  user_data.vertexcos = r_cos;
375  user_data.vertex_visit = BLI_BITMAP_NEW(totcos, __func__);
377  MEM_freeN(user_data.vertex_visit);
378 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
#define ORIGINDEX_NONE
void * CustomData_get_layer(const struct CustomData *data, int type)
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, struct EditMeshData *emd)
void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, struct EditMeshData *emd)
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, struct EditMeshData *emd)
void BKE_mesh_calc_poly_center(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, float r_cent[3])
const float(* BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, float r_no[3])
MeshForeachFlag
@ MESH_FOREACH_NOP
@ MESH_FOREACH_USE_NORMAL
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:64
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
#define ELEM(...)
@ CD_ORIGINDEX
Read Guarded memory(de)allocation.
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_VERT
Definition: bmesh_class.h:383
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#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)
Definition: bmesh_mesh.cc:446
void * user_data
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void BKE_mesh_foreach_mapped_vert_coords_get(Mesh *me_eval, float(*r_cos)[3], const int totcos)
void BKE_mesh_foreach_mapped_subdiv_face_center(Mesh *mesh, void(*func)(void *userData, int index, const float cent[3], const float no[3]), void *userData, MeshForeachFlag flag)
void BKE_mesh_foreach_mapped_loop(Mesh *mesh, void(*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]), void *userData, MeshForeachFlag flag)
void BKE_mesh_foreach_mapped_vert(Mesh *mesh, void(*func)(void *userData, int index, const float co[3], const float no[3]), void *userData, MeshForeachFlag flag)
struct MappedVCosData MappedVCosData
static void get_vertexcos__mapFunc(void *user_data, int index, const float co[3], const float UNUSED(no[3]))
void BKE_mesh_foreach_mapped_face_center(Mesh *mesh, void(*func)(void *userData, int index, const float cent[3], const float no[3]), void *userData, MeshForeachFlag flag)
void BKE_mesh_foreach_mapped_edge(Mesh *mesh, const int tot_edges, void(*func)(void *userData, int index, const float v0co[3], const float v1co[3]), void *userData)
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMesh * bm
Definition: BKE_editmesh.h:40
float no[3]
Definition: bmesh_class.h:271
struct BMVert * v
Definition: bmesh_class.h:153
struct BMLoop * next
Definition: bmesh_class.h:233
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
float const (* polyNos)[3]
const float(* polyCos)[3]
float const (* vertexNos)[3]
const float(* vertexCos)[3]
unsigned int v1
unsigned int v2
unsigned int v
BLI_bitmap * vertex_visit
float(* vertexcos)[3]
struct EditMeshData * edit_data
uint32_t * subsurf_face_dot_tags
struct MEdge * medge
struct BMEditMesh * edit_mesh
CustomData vdata
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
Mesh_Runtime runtime
CustomData pdata
int totpoly
CustomData edata
struct MPoly * mpoly
CustomData ldata