Sequencer: refactor clipboard copy to no longer increase user count.
[blender.git] / source / blender / blenkernel / intern / mesh_iterators.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Foundation
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/blenkernel/intern/mesh_iterators.c
24  *  \ingroup bke
25  *
26  * Functions for iterating mesh features.
27  */
28
29 #include "DNA_mesh_types.h"
30 #include "DNA_meshdata_types.h"
31
32 #include "BKE_customdata.h"
33 #include "BKE_mesh.h"
34 #include "BKE_mesh_iterators.h"
35
36 #include "BLI_bitmap.h"
37 #include "BLI_math.h"
38
39 #include "MEM_guardedalloc.h"
40
41 /* Copied from cdDM_foreachMappedVert */
42 void BKE_mesh_foreach_mapped_vert(
43         Mesh *mesh,
44         void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
45         void *userData,
46         MeshForeachFlag flag)
47 {
48         const MVert *mv = mesh->mvert;
49         const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
50
51         if (index) {
52                 for (int i = 0; i < mesh->totvert; i++, mv++) {
53                         const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
54                         const int orig = *index++;
55                         if (orig == ORIGINDEX_NONE) {
56                                 continue;
57                         }
58                         func(userData, orig, mv->co, NULL, no);
59                 }
60         }
61         else {
62                 for (int i = 0; i < mesh->totvert; i++, mv++) {
63                         const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL;
64                         func(userData, i, mv->co, NULL, no);
65                 }
66         }
67 }
68
69 /* Copied from cdDM_foreachMappedEdge */
70 void BKE_mesh_foreach_mapped_edge(
71         Mesh *mesh,
72         void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
73         void *userData)
74 {
75         const MVert *mv = mesh->mvert;
76         const MEdge *med = mesh->medge;
77         const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX);
78
79         if (index) {
80                 for (int i = 0; i < mesh->totedge; i++, med++) {
81                         const int orig = *index++;
82                         if (orig == ORIGINDEX_NONE) {
83                                 continue;
84                         }
85                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
86                 }
87         }
88         else {
89                 for (int i = 0; i < mesh->totedge; i++, med++) {
90                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
91                 }
92         }
93 }
94
95 /* Copied from cdDM_foreachMappedLoop */
96 void BKE_mesh_foreach_mapped_loop(
97         Mesh *mesh,
98         void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
99         void *userData,
100         MeshForeachFlag flag)
101 {
102         /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
103          * return loop data from bmesh itself. */
104         const float (*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? CustomData_get_layer(&mesh->ldata, CD_NORMAL) : NULL;
105
106         const MVert *mv = mesh->mvert;
107         const MLoop *ml = mesh->mloop;
108         const MPoly *mp = mesh->mpoly;
109         const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX);
110         const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
111         int p_idx, i;
112
113         if (v_index || f_index) {
114                 for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
115                         for (i = 0; i < mp->totloop; i++, ml++) {
116                                 const int v_idx = v_index ? v_index[ml->v] : ml->v;
117                                 const int f_idx = f_index ? f_index[p_idx] : p_idx;
118                                 const float *no = lnors ? *lnors++ : NULL;
119                                 if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
120                                         continue;
121                                 }
122                                 func(userData, v_idx, f_idx, mv[ml->v].co, no);
123                         }
124                 }
125         }
126         else {
127                 for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) {
128                         for (i = 0; i < mp->totloop; i++, ml++) {
129                                 const int v_idx = ml->v;
130                                 const int f_idx = p_idx;
131                                 const float *no = lnors ? *lnors++ : NULL;
132                                 func(userData, v_idx, f_idx, mv[ml->v].co, no);
133                         }
134                 }
135         }
136 }
137
138 /* Copied from cdDM_foreachMappedFaceCenter */
139 void BKE_mesh_foreach_mapped_face_center(
140         Mesh *mesh,
141         void (*func)(void *userData, int index, const float cent[3], const float no[3]),
142         void *userData,
143         MeshForeachFlag flag)
144 {
145         const MVert *mvert = mesh->mvert;
146         const MPoly *mp = mesh->mpoly;
147         const MLoop *ml;
148         float _no_buf[3];
149         float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
150         const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
151
152         if (index) {
153                 for (int i = 0; i < mesh->totpoly; i++, mp++) {
154                         const int orig = *index++;
155                         if (orig == ORIGINDEX_NONE) {
156                                 continue;
157                         }
158                         float cent[3];
159                         ml = &mesh->mloop[mp->loopstart];
160                         BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
161                         if (flag & MESH_FOREACH_USE_NORMAL) {
162                                 BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
163                         }
164                         func(userData, orig, cent, no);
165                 }
166         }
167         else {
168                 for (int i = 0; i < mesh->totpoly; i++, mp++) {
169                         float cent[3];
170                         ml = &mesh->mloop[mp->loopstart];
171                         BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
172                         if (flag & MESH_FOREACH_USE_NORMAL) {
173                                 BKE_mesh_calc_poly_normal(mp, ml, mvert, no);
174                         }
175                         func(userData, i, cent, no);
176                 }
177         }
178 }
179
180
181 /* Helpers based on above foreach loopers> */
182
183 typedef struct MappedVCosData {
184         float (*vertexcos)[3];
185         BLI_bitmap *vertex_visit;
186 } MappedVCosData;
187
188 static void get_vertexcos__mapFunc(
189         void *user_data, int index, const float co[3],
190         const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
191 {
192         MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
193
194         if (BLI_BITMAP_TEST(mapped_vcos_data->vertex_visit, index) == 0) {
195                 /* We need coord from prototype vertex, not from copies,
196                  * we assume they stored in the beginning of vertex array stored in evaluated mesh
197                  * (mirror modifier for eg does this). */
198                 copy_v3_v3(mapped_vcos_data->vertexcos[index], co);
199                 BLI_BITMAP_ENABLE(mapped_vcos_data->vertex_visit, index);
200         }
201 }
202
203 void BKE_mesh_foreach_mapped_vert_coords_get(Mesh *me_eval, float (*r_cos)[3], const int totcos)
204 {
205         MappedVCosData user_data;
206         memset(r_cos, 0, sizeof(*r_cos) * totcos);
207         user_data.vertexcos = r_cos;
208         user_data.vertex_visit = BLI_BITMAP_NEW(totcos, __func__);
209         BKE_mesh_foreach_mapped_vert(me_eval, get_vertexcos__mapFunc, &user_data, MESH_FOREACH_NOP);
210         MEM_freeN(user_data.vertex_visit);
211 }