Cleanup: comments (long lines) in blenkernel
[blender.git] / source / blender / blenkernel / intern / mesh_iterators.c
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
17 /** \file
18  * \ingroup bke
19  *
20  * Functions for iterating mesh features.
21  */
22
23 #include "DNA_mesh_types.h"
24 #include "DNA_meshdata_types.h"
25
26 #include "BKE_customdata.h"
27 #include "BKE_mesh.h"
28 #include "BKE_mesh_iterators.h"
29
30 #include "BLI_bitmap.h"
31 #include "BLI_math.h"
32
33 #include "MEM_guardedalloc.h"
34
35 /* Copied from cdDM_foreachMappedVert */
36 void BKE_mesh_foreach_mapped_vert(Mesh *mesh,
37                                   void (*func)(void *userData,
38                                                int index,
39                                                const float co[3],
40                                                const float no_f[3],
41                                                const short no_s[3]),
42                                   void *userData,
43                                   MeshForeachFlag flag)
44 {
45   const MVert *mv = mesh->mvert;
46   const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
47
48   if (index) {
49     for (int i = 0; i < mesh->totvert; i++, mv++) {
50       const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
51       const int orig = *index++;
52       if (orig == ORIGINDEX_NONE) {
53         continue;
54       }
55       func(userData, orig, mv->co, NULL, no);
56     }
57   }
58   else {
59     for (int i = 0; i < mesh->totvert; i++, mv++) {
60       const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
61       func(userData, i, mv->co, NULL, no);
62     }
63   }
64 }
65
66 /* Copied from cdDM_foreachMappedEdge */
67 void BKE_mesh_foreach_mapped_edge(
68     Mesh *mesh,
69     void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
70     void *userData)
71 {
72   const MVert *mv = mesh->mvert;
73   const MEdge *med = mesh->medge;
74   const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
75
76   if (index) {
77     for (int i = 0; i < mesh->totedge; i++, med++) {
78       const int orig = *index++;
79       if (orig == ORIGINDEX_NONE) {
80         continue;
81       }
82       func(userData, orig, mv[med->v1].co, mv[med->v2].co);
83     }
84   }
85   else {
86     for (int i = 0; i < mesh->totedge; i++, med++) {
87       func(userData, i, mv[med->v1].co, mv[med->v2].co);
88     }
89   }
90 }
91
92 /* Copied from cdDM_foreachMappedLoop */
93 void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
94                                   void (*func)(void *userData,
95                                                int vertex_index,
96                                                int face_index,
97                                                const float co[3],
98                                                const float no[3]),
99                                   void *userData,
100                                   MeshForeachFlag flag)
101 {
102   /* We can't use dm->getLoopDataLayout(dm) here,
103    * we want to always access dm->loopData, EditDerivedBMesh would
104    * return loop data from bmesh itself. */
105   const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
106                                CustomData_get_layer(&mesh->ldata, CD_NORMAL) :
107                                NULL;
108
109   const MVert *mv = mesh->mvert;
110   const MLoop *ml = mesh->mloop;
111   const MPoly *mp = mesh->mpoly;
112   const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
113   const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
114   int p_idx, i;
115
116   if (v_index || f_index) {
117     for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
118       for (i = 0; i < mp->totloop; i++, ml++) {
119         const int v_idx = v_index ? v_index[ml->v] : ml->v;
120         const int f_idx = f_index ? f_index[p_idx] : p_idx;
121         const float *no = lnors ? *lnors++ : NULL;
122         if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
123           continue;
124         }
125         func(userData, v_idx, f_idx, mv[ml->v].co, no);
126       }
127     }
128   }
129   else {
130     for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
131       for (i = 0; i < mp->totloop; i++, ml++) {
132         const int v_idx = ml->v;
133         const int f_idx = p_idx;
134         const float *no = lnors ? *lnors++ : NULL;
135         func(userData, v_idx, f_idx, mv[ml->v].co, no);
136       }
137     }
138   }
139 }
140
141 /* Copied from cdDM_foreachMappedFaceCenter */
142 void BKE_mesh_foreach_mapped_face_center(
143     Mesh *mesh,
144     void (*func)(void *userData, int index, const float cent[3], const float no[3]),
145     void *userData,
146     MeshForeachFlag flag)
147 {
148   const MVert *mvert = mesh->mvert;
149   const MPoly *mp = mesh->mpoly;
150   const MLoop *ml;
151   float _no_buf[3];
152   float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
153   const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
154
155   if (index) {
156     for (int i = 0; i < mesh->totpoly; i++, mp++) {
157       const int orig = *index++;
158       if (orig == ORIGINDEX_NONE) {
159         continue;
160       }
161       float cent[3];
162       ml = &mesh->mloop[mp->loopstart];
163       BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
164       if (flag & MESH_FOREACH_USE_NORMAL) {
165         BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
166       }
167       func(userData, orig, cent, no);
168     }
169   }
170   else {
171     for (int i = 0; i < mesh->totpoly; i++, mp++) {
172       float cent[3];
173       ml = &mesh->mloop[mp->loopstart];
174       BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
175       if (flag & MESH_FOREACH_USE_NORMAL) {
176         BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
177       }
178       func(userData, i, cent, no);
179     }
180   }
181 }
182
183 /* Helpers based on above foreach loopers> */
184
185 typedef struct MappedVCosData {
186   float (*vertexcos)[3];
187   BLI_bitmap *vertex_visit;
188 } MappedVCosData;
189
190 static void get_vertexcos__mapFunc(void *user_data,
191                                    int index,
192                                    const float co[3],
193                                    const float UNUSED(no_f[3]),
194                                    const short UNUSED(no_s[3]))
195 {
196   MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
197
198   if (BLI_BITMAP_TEST(mapped_vcos_data->vertex_visit, index) == 0) {
199     /* We need coord from prototype vertex, not from copies,
200      * we assume they stored in the beginning of vertex array stored in evaluated mesh
201      * (mirror modifier for eg does this). */
202     copy_v3_v3(mapped_vcos_data->vertexcos[index], co);
203     BLI_BITMAP_ENABLE(mapped_vcos_data->vertex_visit, index);
204   }
205 }
206
207 void BKE_mesh_foreach_mapped_vert_coords_get(Mesh *me_eval, float (*r_cos)[3], const int totcos)
208 {
209   MappedVCosData user_data;
210   memset(r_cos, 0, sizeof(*r_cos) * totcos);
211   user_data.vertexcos = r_cos;
212   user_data.vertex_visit = BLI_BITMAP_NEW(totcos, __func__);
213   BKE_mesh_foreach_mapped_vert(me_eval, get_vertexcos__mapFunc, &user_data, MESH_FOREACH_NOP);
214   MEM_freeN(user_data.vertex_visit);
215 }