| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bke | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Functions for iterating mesh features. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_customdata.h"
 | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  | #include "BKE_editmesh.h"
 | 
					
						
							|  |  |  | #include "BKE_editmesh_cache.h"
 | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh_iterators.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-28 15:42:00 +02:00
										 |  |  | #include "BLI_bitmap.h"
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Copied from cdDM_foreachMappedVert */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |   if (mesh->edit_mesh != NULL) { | 
					
						
							|  |  |  |     BMEditMesh *em = mesh->edit_mesh; | 
					
						
							|  |  |  |     BMesh *bm = em->bm; | 
					
						
							|  |  |  |     BMIter iter; | 
					
						
							|  |  |  |     BMVert *eve; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     if (mesh->runtime.edit_data->vertexCos != NULL) { | 
					
						
							|  |  |  |       const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos; | 
					
						
							|  |  |  |       const float(*vertexNos)[3]; | 
					
						
							|  |  |  |       if (flag & MESH_FOREACH_USE_NORMAL) { | 
					
						
							|  |  |  |         BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime.edit_data); | 
					
						
							|  |  |  |         vertexNos = mesh->runtime.edit_data->vertexNos; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         vertexNos = NULL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { | 
					
						
							|  |  |  |         const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL; | 
					
						
							|  |  |  |         func(userData, i, vertexCos[i], no, NULL); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { | 
					
						
							|  |  |  |         const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? eve->no : NULL; | 
					
						
							|  |  |  |         func(userData, i, eve->co, no, NULL); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |     const MVert *mv = mesh->mvert; | 
					
						
							|  |  |  |     const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (index) { | 
					
						
							|  |  |  |       for (int i = 0; i < mesh->totvert; i++, mv++) { | 
					
						
							|  |  |  |         const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL; | 
					
						
							|  |  |  |         const int orig = *index++; | 
					
						
							|  |  |  |         if (orig == ORIGINDEX_NONE) { | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         func(userData, orig, mv->co, NULL, no); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       for (int i = 0; i < mesh->totvert; i++, mv++) { | 
					
						
							|  |  |  |         const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL; | 
					
						
							|  |  |  |         func(userData, i, mv->co, NULL, no); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Copied from cdDM_foreachMappedEdge */ | 
					
						
							|  |  |  | void BKE_mesh_foreach_mapped_edge( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     Mesh *mesh, | 
					
						
							|  |  |  |     void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), | 
					
						
							|  |  |  |     void *userData) | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |   if (mesh->edit_mesh != NULL) { | 
					
						
							|  |  |  |     BMEditMesh *em = mesh->edit_mesh; | 
					
						
							|  |  |  |     BMesh *bm = em->bm; | 
					
						
							|  |  |  |     BMIter iter; | 
					
						
							|  |  |  |     BMEdge *eed; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     if (mesh->runtime.edit_data->vertexCos != NULL) { | 
					
						
							|  |  |  |       const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos; | 
					
						
							|  |  |  |       BM_mesh_elem_index_ensure(bm, BM_VERT); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |       BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { | 
					
						
							|  |  |  |         func(userData, | 
					
						
							|  |  |  |              i, | 
					
						
							|  |  |  |              vertexCos[BM_elem_index_get(eed->v1)], | 
					
						
							|  |  |  |              vertexCos[BM_elem_index_get(eed->v2)]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { | 
					
						
							|  |  |  |         func(userData, i, eed->v1->co, eed->v2->co); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |     const MVert *mv = mesh->mvert; | 
					
						
							|  |  |  |     const MEdge *med = mesh->medge; | 
					
						
							|  |  |  |     const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (index) { | 
					
						
							|  |  |  |       for (int i = 0; i < mesh->totedge; i++, med++) { | 
					
						
							|  |  |  |         const int orig = *index++; | 
					
						
							|  |  |  |         if (orig == ORIGINDEX_NONE) { | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         func(userData, orig, mv[med->v1].co, mv[med->v2].co); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       for (int i = 0; i < mesh->totedge; i++, med++) { | 
					
						
							|  |  |  |         func(userData, i, mv[med->v1].co, mv[med->v2].co); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Copied from cdDM_foreachMappedLoop */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |   /* We can't use dm->getLoopDataLayout(dm) here,
 | 
					
						
							|  |  |  |    * we want to always access dm->loopData, EditDerivedBMesh would | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |    * return loop data from bmesh itself. */ | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |   if (mesh->edit_mesh != NULL) { | 
					
						
							|  |  |  |     BMEditMesh *em = mesh->edit_mesh; | 
					
						
							|  |  |  |     BMesh *bm = em->bm; | 
					
						
							|  |  |  |     BMIter iter; | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |     const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* XXX: investigate using EditMesh data. */ | 
					
						
							|  |  |  |     const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? | 
					
						
							|  |  |  |                                  CustomData_get_layer(&mesh->ldata, CD_NORMAL) : | 
					
						
							|  |  |  |                                  NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int f_idx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BM_mesh_elem_index_ensure(bm, BM_VERT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) { | 
					
						
							|  |  |  |       BMLoop *l_iter, *l_first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       l_iter = l_first = BM_FACE_FIRST_LOOP(efa); | 
					
						
							|  |  |  |       do { | 
					
						
							|  |  |  |         const BMVert *eve = l_iter->v; | 
					
						
							|  |  |  |         const int v_idx = BM_elem_index_get(eve); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         const float *no = lnors ? *lnors++ : NULL; | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |         func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no); | 
					
						
							|  |  |  |       } while ((l_iter = l_iter->next) != l_first); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |     const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? | 
					
						
							|  |  |  |                                  CustomData_get_layer(&mesh->ldata, CD_NORMAL) : | 
					
						
							|  |  |  |                                  NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const MVert *mv = mesh->mvert; | 
					
						
							|  |  |  |     const MLoop *ml = mesh->mloop; | 
					
						
							|  |  |  |     const MPoly *mp = mesh->mpoly; | 
					
						
							|  |  |  |     const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); | 
					
						
							|  |  |  |     const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX); | 
					
						
							|  |  |  |     int p_idx, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (v_index || f_index) { | 
					
						
							|  |  |  |       for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) { | 
					
						
							|  |  |  |         for (i = 0; i < mp->totloop; i++, ml++) { | 
					
						
							|  |  |  |           const int v_idx = v_index ? v_index[ml->v] : ml->v; | 
					
						
							|  |  |  |           const int f_idx = f_index ? f_index[p_idx] : p_idx; | 
					
						
							|  |  |  |           const float *no = lnors ? *lnors++ : NULL; | 
					
						
							|  |  |  |           if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           func(userData, v_idx, f_idx, mv[ml->v].co, no); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) { | 
					
						
							|  |  |  |         for (i = 0; i < mp->totloop; i++, ml++) { | 
					
						
							|  |  |  |           const int v_idx = ml->v; | 
					
						
							|  |  |  |           const int f_idx = p_idx; | 
					
						
							|  |  |  |           const float *no = lnors ? *lnors++ : NULL; | 
					
						
							|  |  |  |           func(userData, v_idx, f_idx, mv[ml->v].co, no); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Copied from cdDM_foreachMappedFaceCenter */ | 
					
						
							|  |  |  | void BKE_mesh_foreach_mapped_face_center( | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     Mesh *mesh, | 
					
						
							|  |  |  |     void (*func)(void *userData, int index, const float cent[3], const float no[3]), | 
					
						
							|  |  |  |     void *userData, | 
					
						
							|  |  |  |     MeshForeachFlag flag) | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |   if (mesh->edit_mesh != NULL) { | 
					
						
							|  |  |  |     BMEditMesh *em = mesh->edit_mesh; | 
					
						
							|  |  |  |     BMesh *bm = em->bm; | 
					
						
							|  |  |  |     const float(*polyCos)[3]; | 
					
						
							|  |  |  |     const float(*polyNos)[3]; | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							|  |  |  |     BMIter iter; | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |     BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime.edit_data); | 
					
						
							|  |  |  |     polyCos = mesh->runtime.edit_data->polyCos; /* always set */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (flag & MESH_FOREACH_USE_NORMAL) { | 
					
						
							|  |  |  |       BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime.edit_data); | 
					
						
							|  |  |  |       polyNos = mesh->runtime.edit_data->polyNos; /* maybe NULL */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       polyNos = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (polyNos) { | 
					
						
							|  |  |  |       BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { | 
					
						
							|  |  |  |         const float *no = polyNos[i]; | 
					
						
							|  |  |  |         func(userData, i, polyCos[i], no); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { | 
					
						
							|  |  |  |         const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? efa->no : NULL; | 
					
						
							|  |  |  |         func(userData, i, polyCos[i], no); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-05-25 20:16:42 +10:00
										 |  |  |     const MVert *mvert = mesh->mvert; | 
					
						
							|  |  |  |     const MPoly *mp = mesh->mpoly; | 
					
						
							|  |  |  |     const MLoop *ml; | 
					
						
							|  |  |  |     float _no_buf[3]; | 
					
						
							|  |  |  |     float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL; | 
					
						
							|  |  |  |     const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (index) { | 
					
						
							|  |  |  |       for (int i = 0; i < mesh->totpoly; i++, mp++) { | 
					
						
							|  |  |  |         const int orig = *index++; | 
					
						
							|  |  |  |         if (orig == ORIGINDEX_NONE) { | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         float cent[3]; | 
					
						
							|  |  |  |         ml = &mesh->mloop[mp->loopstart]; | 
					
						
							|  |  |  |         BKE_mesh_calc_poly_center(mp, ml, mvert, cent); | 
					
						
							|  |  |  |         if (flag & MESH_FOREACH_USE_NORMAL) { | 
					
						
							|  |  |  |           BKE_mesh_calc_poly_normal(mp, ml, mvert, no); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         func(userData, orig, cent, no); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       for (int i = 0; i < mesh->totpoly; i++, mp++) { | 
					
						
							|  |  |  |         float cent[3]; | 
					
						
							|  |  |  |         ml = &mesh->mloop[mp->loopstart]; | 
					
						
							|  |  |  |         BKE_mesh_calc_poly_center(mp, ml, mvert, cent); | 
					
						
							|  |  |  |         if (flag & MESH_FOREACH_USE_NORMAL) { | 
					
						
							|  |  |  |           BKE_mesh_calc_poly_normal(mp, ml, mvert, no); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         func(userData, i, cent, no); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-20 10:03:50 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-28 15:42:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-07 18:58:11 +02:00
										 |  |  | /* Copied from cdDM_foreachMappedFaceCenter */ | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const MPoly *mp = mesh->mpoly; | 
					
						
							|  |  |  |   const MLoop *ml; | 
					
						
							|  |  |  |   const MVert *mv; | 
					
						
							|  |  |  |   float _no_buf[3]; | 
					
						
							|  |  |  |   float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL; | 
					
						
							|  |  |  |   const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (index) { | 
					
						
							|  |  |  |     for (int i = 0; i < mesh->totpoly; i++, mp++) { | 
					
						
							|  |  |  |       const int orig = *index++; | 
					
						
							|  |  |  |       if (orig == ORIGINDEX_NONE) { | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       ml = &mesh->mloop[mp->loopstart]; | 
					
						
							|  |  |  |       for (int j = 0; j < mp->totloop; j++, ml++) { | 
					
						
							|  |  |  |         mv = &mesh->mvert[ml->v]; | 
					
						
							|  |  |  |         if (mv->flag & ME_VERT_FACEDOT) { | 
					
						
							|  |  |  |           if (flag & MESH_FOREACH_USE_NORMAL) { | 
					
						
							|  |  |  |             normal_short_to_float_v3(no, mv->no); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           func(userData, orig, mv->co, no); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     for (int i = 0; i < mesh->totpoly; i++, mp++) { | 
					
						
							|  |  |  |       ml = &mesh->mloop[mp->loopstart]; | 
					
						
							|  |  |  |       for (int j = 0; j < mp->totloop; j++, ml++) { | 
					
						
							|  |  |  |         mv = &mesh->mvert[ml->v]; | 
					
						
							|  |  |  |         if (mv->flag & ME_VERT_FACEDOT) { | 
					
						
							|  |  |  |           if (flag & MESH_FOREACH_USE_NORMAL) { | 
					
						
							|  |  |  |             normal_short_to_float_v3(no, mv->no); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           func(userData, i, mv->co, no); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-28 15:42:00 +02:00
										 |  |  | /* Helpers based on above foreach loopers> */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct MappedVCosData { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float (*vertexcos)[3]; | 
					
						
							|  |  |  |   BLI_bitmap *vertex_visit; | 
					
						
							| 
									
										
										
										
											2018-06-28 15:42:00 +02:00
										 |  |  | } MappedVCosData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 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])) | 
					
						
							| 
									
										
										
										
											2018-06-28 15:42:00 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (BLI_BITMAP_TEST(mapped_vcos_data->vertex_visit, index) == 0) { | 
					
						
							|  |  |  |     /* We need coord from prototype vertex, not from copies,
 | 
					
						
							|  |  |  |      * we assume they stored in the beginning of vertex array stored in evaluated mesh | 
					
						
							|  |  |  |      * (mirror modifier for eg does this). */ | 
					
						
							|  |  |  |     copy_v3_v3(mapped_vcos_data->vertexcos[index], co); | 
					
						
							|  |  |  |     BLI_BITMAP_ENABLE(mapped_vcos_data->vertex_visit, index); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-28 15:42:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BKE_mesh_foreach_mapped_vert_coords_get(Mesh *me_eval, float (*r_cos)[3], const int totcos) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MappedVCosData user_data; | 
					
						
							|  |  |  |   memset(r_cos, 0, sizeof(*r_cos) * totcos); | 
					
						
							|  |  |  |   user_data.vertexcos = r_cos; | 
					
						
							|  |  |  |   user_data.vertex_visit = BLI_BITMAP_NEW(totcos, __func__); | 
					
						
							|  |  |  |   BKE_mesh_foreach_mapped_vert(me_eval, get_vertexcos__mapFunc, &user_data, MESH_FOREACH_NOP); | 
					
						
							|  |  |  |   MEM_freeN(user_data.vertex_visit); | 
					
						
							| 
									
										
										
										
											2018-06-28 15:42:00 +02:00
										 |  |  | } |