Blender  V2.93
mesh_iterators.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include "DNA_mesh_types.h"
24 #include "DNA_meshdata_types.h"
25 
26 #include "BKE_customdata.h"
27 #include "BKE_editmesh.h"
28 #include "BKE_editmesh_cache.h"
29 #include "BKE_mesh.h"
30 #include "BKE_mesh_iterators.h"
31 
32 #include "BLI_bitmap.h"
33 #include "BLI_math.h"
34 
35 #include "MEM_guardedalloc.h"
36 
37 /* Copied from cdDM_foreachMappedVert */
39  void (*func)(void *userData,
40  int index,
41  const float co[3],
42  const float no_f[3],
43  const short no_s[3]),
44  void *userData,
45  MeshForeachFlag flag)
46 {
47  if (mesh->edit_mesh != NULL) {
48  BMEditMesh *em = mesh->edit_mesh;
49  BMesh *bm = em->bm;
50  BMIter iter;
51  BMVert *eve;
52  int i;
53  if (mesh->runtime.edit_data->vertexCos != NULL) {
54  const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
55  const float(*vertexNos)[3];
56  if (flag & MESH_FOREACH_USE_NORMAL) {
58  vertexNos = mesh->runtime.edit_data->vertexNos;
59  }
60  else {
61  vertexNos = NULL;
62  }
63  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
64  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
65  func(userData, i, vertexCos[i], no, NULL);
66  }
67  }
68  else {
69  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
70  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? eve->no : NULL;
71  func(userData, i, eve->co, no, NULL);
72  }
73  }
74  }
75  else {
76  const MVert *mv = mesh->mvert;
77  const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
78 
79  if (index) {
80  for (int i = 0; i < mesh->totvert; i++, mv++) {
81  const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
82  const int orig = *index++;
83  if (orig == ORIGINDEX_NONE) {
84  continue;
85  }
86  func(userData, orig, mv->co, NULL, no);
87  }
88  }
89  else {
90  for (int i = 0; i < mesh->totvert; i++, mv++) {
91  const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
92  func(userData, i, mv->co, NULL, no);
93  }
94  }
95  }
96 }
97 
98 /* Copied from cdDM_foreachMappedEdge */
100  Mesh *mesh,
101  void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
102  void *userData)
103 {
104  if (mesh->edit_mesh != NULL) {
105  BMEditMesh *em = mesh->edit_mesh;
106  BMesh *bm = em->bm;
107  BMIter iter;
108  BMEdge *eed;
109  int i;
110  if (mesh->runtime.edit_data->vertexCos != NULL) {
111  const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
113 
114  BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
115  func(userData,
116  i,
117  vertexCos[BM_elem_index_get(eed->v1)],
118  vertexCos[BM_elem_index_get(eed->v2)]);
119  }
120  }
121  else {
122  BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
123  func(userData, i, eed->v1->co, eed->v2->co);
124  }
125  }
126  }
127  else {
128  const MVert *mv = mesh->mvert;
129  const MEdge *med = mesh->medge;
130  const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
131 
132  if (index) {
133  for (int i = 0; i < mesh->totedge; i++, med++) {
134  const int orig = *index++;
135  if (orig == ORIGINDEX_NONE) {
136  continue;
137  }
138  func(userData, orig, mv[med->v1].co, mv[med->v2].co);
139  }
140  }
141  else {
142  for (int i = 0; i < mesh->totedge; i++, med++) {
143  func(userData, i, mv[med->v1].co, mv[med->v2].co);
144  }
145  }
146  }
147 }
148 
149 /* Copied from cdDM_foreachMappedLoop */
151  void (*func)(void *userData,
152  int vertex_index,
153  int face_index,
154  const float co[3],
155  const float no[3]),
156  void *userData,
157  MeshForeachFlag flag)
158 {
159 
160  /* We can't use dm->getLoopDataLayout(dm) here,
161  * we want to always access dm->loopData, EditDerivedBMesh would
162  * return loop data from bmesh itself. */
163  if (mesh->edit_mesh != NULL) {
164  BMEditMesh *em = mesh->edit_mesh;
165  BMesh *bm = em->bm;
166  BMIter iter;
167  BMFace *efa;
168 
169  const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
170 
171  /* XXX: investigate using EditMesh data. */
172  const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
174  NULL;
175 
176  int f_idx;
177 
179 
180  BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) {
181  BMLoop *l_iter, *l_first;
182 
183  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
184  do {
185  const BMVert *eve = l_iter->v;
186  const int v_idx = BM_elem_index_get(eve);
187  const float *no = lnors ? *lnors++ : NULL;
188  func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
189  } while ((l_iter = l_iter->next) != l_first);
190  }
191  }
192  else {
193  const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
195  NULL;
196 
197  const MVert *mv = mesh->mvert;
198  const MLoop *ml = mesh->mloop;
199  const MPoly *mp = mesh->mpoly;
200  const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
201  const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
202  int p_idx, i;
203 
204  if (v_index || f_index) {
205  for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
206  for (i = 0; i < mp->totloop; i++, ml++) {
207  const int v_idx = v_index ? v_index[ml->v] : ml->v;
208  const int f_idx = f_index ? f_index[p_idx] : p_idx;
209  const float *no = lnors ? *lnors++ : NULL;
210  if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
211  continue;
212  }
213  func(userData, v_idx, f_idx, mv[ml->v].co, no);
214  }
215  }
216  }
217  else {
218  for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
219  for (i = 0; i < mp->totloop; i++, ml++) {
220  const int v_idx = ml->v;
221  const int f_idx = p_idx;
222  const float *no = lnors ? *lnors++ : NULL;
223  func(userData, v_idx, f_idx, mv[ml->v].co, no);
224  }
225  }
226  }
227  }
228 }
229 
230 /* Copied from cdDM_foreachMappedFaceCenter */
232  Mesh *mesh,
233  void (*func)(void *userData, int index, const float cent[3], const float no[3]),
234  void *userData,
235  MeshForeachFlag flag)
236 {
237  if (mesh->edit_mesh != NULL) {
238  BMEditMesh *em = mesh->edit_mesh;
239  BMesh *bm = em->bm;
240  const float(*polyCos)[3];
241  const float(*polyNos)[3];
242  BMFace *efa;
243  BMIter iter;
244  int i;
245 
247  polyCos = mesh->runtime.edit_data->polyCos; /* always set */
248 
249  if (flag & MESH_FOREACH_USE_NORMAL) {
251  polyNos = mesh->runtime.edit_data->polyNos; /* maybe NULL */
252  }
253  else {
254  polyNos = NULL;
255  }
256 
257  if (polyNos) {
258  BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
259  const float *no = polyNos[i];
260  func(userData, i, polyCos[i], no);
261  }
262  }
263  else {
264  BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
265  const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? efa->no : NULL;
266  func(userData, i, polyCos[i], no);
267  }
268  }
269  }
270  else {
271  const MVert *mvert = mesh->mvert;
272  const MPoly *mp = mesh->mpoly;
273  const MLoop *ml;
274  float _no_buf[3];
275  float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
276  const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
277 
278  if (index) {
279  for (int i = 0; i < mesh->totpoly; i++, mp++) {
280  const int orig = *index++;
281  if (orig == ORIGINDEX_NONE) {
282  continue;
283  }
284  float cent[3];
285  ml = &mesh->mloop[mp->loopstart];
286  BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
287  if (flag & MESH_FOREACH_USE_NORMAL) {
288  BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
289  }
290  func(userData, orig, cent, no);
291  }
292  }
293  else {
294  for (int i = 0; i < mesh->totpoly; i++, mp++) {
295  float cent[3];
296  ml = &mesh->mloop[mp->loopstart];
297  BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
298  if (flag & MESH_FOREACH_USE_NORMAL) {
299  BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
300  }
301  func(userData, i, cent, no);
302  }
303  }
304  }
305 }
306 
307 /* Copied from cdDM_foreachMappedFaceCenter */
309  Mesh *mesh,
310  void (*func)(void *userData, int index, const float cent[3], const float no[3]),
311  void *userData,
312  MeshForeachFlag flag)
313 {
314  const MPoly *mp = mesh->mpoly;
315  const MLoop *ml;
316  const MVert *mv;
317  float _no_buf[3];
318  float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
319  const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
320 
321  if (index) {
322  for (int i = 0; i < mesh->totpoly; i++, mp++) {
323  const int orig = *index++;
324  if (orig == ORIGINDEX_NONE) {
325  continue;
326  }
327  ml = &mesh->mloop[mp->loopstart];
328  for (int j = 0; j < mp->totloop; j++, ml++) {
329  mv = &mesh->mvert[ml->v];
330  if (mv->flag & ME_VERT_FACEDOT) {
331  if (flag & MESH_FOREACH_USE_NORMAL) {
332  normal_short_to_float_v3(no, mv->no);
333  }
334  func(userData, orig, mv->co, no);
335  }
336  }
337  }
338  }
339  else {
340  for (int i = 0; i < mesh->totpoly; i++, mp++) {
341  ml = &mesh->mloop[mp->loopstart];
342  for (int j = 0; j < mp->totloop; j++, ml++) {
343  mv = &mesh->mvert[ml->v];
344  if (mv->flag & ME_VERT_FACEDOT) {
345  if (flag & MESH_FOREACH_USE_NORMAL) {
346  normal_short_to_float_v3(no, mv->no);
347  }
348  func(userData, i, mv->co, no);
349  }
350  }
351  }
352  }
353 }
354 
355 /* Helpers based on above foreach loopers> */
356 
357 typedef struct MappedVCosData {
361 
363  int index,
364  const float co[3],
365  const float UNUSED(no_f[3]),
366  const short UNUSED(no_s[3]))
367 {
368  MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
369 
370  if (BLI_BITMAP_TEST(mapped_vcos_data->vertex_visit, index) == 0) {
371  /* We need coord from prototype vertex, not from copies,
372  * we assume they stored in the beginning of vertex array stored in evaluated mesh
373  * (mirror modifier for eg does this). */
374  copy_v3_v3(mapped_vcos_data->vertexcos[index], co);
375  BLI_BITMAP_ENABLE(mapped_vcos_data->vertex_visit, index);
376  }
377 }
378 
379 void BKE_mesh_foreach_mapped_vert_coords_get(Mesh *me_eval, float (*r_cos)[3], const int totcos)
380 {
382  memset(r_cos, 0, sizeof(*r_cos) * totcos);
383  user_data.vertexcos = r_cos;
384  user_data.vertex_visit = BLI_BITMAP_NEW(totcos, __func__);
386  MEM_freeN(user_data.vertex_visit);
387 }
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])
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_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
MINLINE void normal_short_to_float_v3(float r[3], const short n[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
#define ELEM(...)
@ CD_ORIGINDEX
@ ME_VERT_FACEDOT
Read Guarded memory(de)allocation.
@ BM_VERT
Definition: bmesh_class.h:383
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#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.c:2152
void * user_data
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
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_vert(Mesh *mesh, void(*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), void *userData, MeshForeachFlag flag)
static void get_vertexcos__mapFunc(void *user_data, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
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_edge(Mesh *mesh, void(*func)(void *userData, int index, const float v0co[3], const float v1co[3]), void *userData)
struct MappedVCosData MappedVCosData
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)
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
struct BMesh * bm
Definition: BKE_editmesh.h:52
float no[3]
Definition: bmesh_class.h:280
struct BMVert * v
Definition: bmesh_class.h:165
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
float no[3]
Definition: bmesh_class.h:100
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
struct MEdge * medge
struct BMEditMesh * edit_mesh
struct CustomData pdata ldata
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
Mesh_Runtime runtime
int totpoly
struct MPoly * mpoly