Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / mesh_remap.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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/blenkernel/intern/mesh_remap.c
22  *  \ingroup bke
23  *
24  * Functions for mapping data between meshes.
25  */
26
27 #include <limits.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "DNA_meshdata_types.h"
32
33 #include "BLI_utildefines.h"
34 #include "BLI_alloca.h"
35 #include "BLI_astar.h"
36 #include "BLI_bitmap.h"
37 #include "BLI_math.h"
38 #include "BLI_memarena.h"
39 #include "BLI_polyfill_2d.h"
40 #include "BLI_rand.h"
41
42 #include "BKE_bvhutils.h"
43 #include "BKE_customdata.h"
44 #include "BKE_DerivedMesh.h"
45 #include "BKE_mesh.h"
46 #include "BKE_mesh_mapping.h"
47 #include "BKE_mesh_remap.h"  /* own include */
48
49 #include "BLI_strict_flags.h"
50
51
52 /* -------------------------------------------------------------------- */
53
54 /** \name Some generic helpers.
55  * \{ */
56
57 static bool mesh_remap_bvhtree_query_nearest(
58         BVHTreeFromMesh *treedata, BVHTreeNearest *nearest,
59         const float co[3], const float max_dist_sq, float *r_hit_dist)
60 {
61         /* Use local proximity heuristics (to reduce the nearest search). */
62         if (nearest->index != -1) {
63                 nearest->dist_sq = min_ff(len_squared_v3v3(co, nearest->co), max_dist_sq);
64         }
65         else {
66                 nearest->dist_sq = max_dist_sq;
67         }
68         /* Compute and store result. If invalid (-1 index), keep FLT_MAX dist. */
69         BLI_bvhtree_find_nearest(treedata->tree, co, nearest, treedata->nearest_callback, treedata);
70
71         if ((nearest->index != -1) && (nearest->dist_sq <= max_dist_sq)) {
72                 *r_hit_dist = sqrtf(nearest->dist_sq);
73                 return true;
74         }
75         else {
76                 return false;
77         }
78 }
79
80 static bool mesh_remap_bvhtree_query_raycast(
81         BVHTreeFromMesh *treedata, BVHTreeRayHit *rayhit,
82         const float co[3], const float no[3], const float radius, const float max_dist, float *r_hit_dist)
83 {
84         BVHTreeRayHit rayhit_tmp;
85         float inv_no[3];
86
87         rayhit->index = -1;
88         rayhit->dist = max_dist;
89         BLI_bvhtree_ray_cast(treedata->tree, co, no, radius, rayhit, treedata->raycast_callback, treedata);
90
91         /* Also cast in the other direction! */
92         rayhit_tmp = *rayhit;
93         negate_v3_v3(inv_no, no);
94         BLI_bvhtree_ray_cast(treedata->tree, co, inv_no, radius, &rayhit_tmp, treedata->raycast_callback, treedata);
95         if (rayhit_tmp.dist < rayhit->dist) {
96                 *rayhit = rayhit_tmp;
97         }
98
99         if ((rayhit->index != -1) && (rayhit->dist <= max_dist)) {
100                 *r_hit_dist = rayhit->dist;
101                 return true;
102         }
103         else {
104                 return false;
105         }
106 }
107
108 /** \} */
109
110 /**
111  * \name Auto-match.
112  *
113  * Find transform of a mesh to get best match with another.
114  * \{ */
115
116 /**
117  * Compute a value of the difference between both given meshes.
118  * The smaller the result, the better the match.
119  *
120  * We return the inverse of the average of the inversed shortest distance from each dst vertex to src ones.
121  * In other words, beyond a certain (relatively small) distance, all differences have more or less the same weight
122  * in final result, which allows to reduce influence of a few high differences, in favor of a global good matching.
123  */
124 float BKE_mesh_remap_calc_difference_from_dm(
125         const SpaceTransform *space_transform, const MVert *verts_dst, const int numverts_dst, DerivedMesh *dm_src)
126 {
127         BVHTreeFromMesh treedata = {NULL};
128         BVHTreeNearest nearest = {0};
129         float hit_dist;
130
131         float result = 0.0f;
132         int i;
133
134         bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
135         nearest.index = -1;
136
137         for (i = 0; i < numverts_dst; i++) {
138                 float tmp_co[3];
139
140                 copy_v3_v3(tmp_co, verts_dst[i].co);
141
142                 /* Convert the vertex to tree coordinates, if needed. */
143                 if (space_transform) {
144                         BLI_space_transform_apply(space_transform, tmp_co);
145                 }
146
147                 if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, FLT_MAX, &hit_dist)) {
148                         result += 1.0f / (hit_dist + 1.0f);
149                 }
150                 else {
151                         /* No source for this dest vertex! */
152                         result += 1e-18f;
153                 }
154         }
155
156         result = ((float)numverts_dst / result) - 1.0f;
157
158 //      printf("%s: Computed difference between meshes (the lower the better): %f\n", __func__, result);
159
160         return result;
161 }
162
163 /* This helper computes the eigen values & vectors for covariance matrix of all given vertices coordinates.
164  *
165  * Those vectors define the 'average ellipsoid' of the mesh (i.e. the 'best fitting' ellipsoid
166  * containing 50% of the vertices).
167  *
168  * Note that it will not perform fantastic in case two or more eigen values are equal (e.g. a cylinder or
169  * parallelepiped with a square section give two identical eigenvalues, a sphere or tetrahedron give
170  * three identical ones, etc.), since you cannot really define all axes in those cases. We default to dummy
171  * generated orthogonal vectors in this case, instead of using eigen vectors.
172  */
173 static void mesh_calc_eigen_matrix(
174         const MVert *verts, const float (*vcos)[3], const int numverts, float r_mat[4][4])
175 {
176         float center[3], covmat[3][3];
177         float eigen_val[3], eigen_vec[3][3];
178         float (*cos)[3] = NULL;
179
180         bool eigen_success;
181         int i;
182
183         if (verts) {
184                 const MVert *mv;
185                 float (*co)[3];
186
187                 cos = MEM_mallocN(sizeof(*cos) * (size_t)numverts, __func__);
188                 for (i = 0, co = cos, mv = verts; i < numverts; i++, co++, mv++) {
189                         copy_v3_v3(*co, mv->co);
190                 }
191                 /* TODO(sergey): For until we officially drop all compilers which
192                  * doesn't handle casting correct we use workaround to avoid explicit
193                  * cast here.
194                  */
195                 vcos = (void *)cos;
196         }
197         unit_m4(r_mat);
198
199         /* Note: here we apply sample correction to covariance matrix, since we consider the vertices as a sample
200          *       of the whole 'surface' population of our mesh... */
201         BLI_covariance_m3_v3n(vcos, numverts, true, covmat, center);
202
203         if (cos) {
204                 MEM_freeN(cos);
205         }
206
207         eigen_success = BLI_eigen_solve_selfadjoint_m3((const float (*)[3])covmat, eigen_val, eigen_vec);
208         BLI_assert(eigen_success);
209         UNUSED_VARS_NDEBUG(eigen_success);
210
211         /* Special handling of cases where some eigen values are (nearly) identical. */
212         if (compare_ff_relative(eigen_val[0], eigen_val[1], FLT_EPSILON, 64)) {
213                 if (compare_ff_relative(eigen_val[0], eigen_val[2], FLT_EPSILON, 64)) {
214                         /* No preferred direction, that set of vertices has a spherical average,
215                          * so we simply returned scaled/translated identity matrix (with no rotation). */
216                         unit_m3(eigen_vec);
217                 }
218                 else {
219                         /* Ellipsoid defined by eigen values/vectors has a spherical section,
220                          * we can only define one axis from eigen_vec[2] (two others computed eigen vecs
221                          * are not so nice for us here, they tend to 'randomly' rotate around valid one).
222                          * Note that eigen vectors as returned by BLI_eigen_solve_selfadjoint_m3() are normalized. */
223                         ortho_basis_v3v3_v3(eigen_vec[0], eigen_vec[1], eigen_vec[2]);
224                 }
225         }
226         else if (compare_ff_relative(eigen_val[0], eigen_val[2], FLT_EPSILON, 64)) {
227                 /* Same as above, but with eigen_vec[1] as valid axis. */
228                 ortho_basis_v3v3_v3(eigen_vec[2], eigen_vec[0], eigen_vec[1]);
229         }
230         else if (compare_ff_relative(eigen_val[1], eigen_val[2], FLT_EPSILON, 64)) {
231                 /* Same as above, but with eigen_vec[0] as valid axis. */
232                 ortho_basis_v3v3_v3(eigen_vec[1], eigen_vec[2], eigen_vec[0]);
233         }
234
235         for (i = 0; i < 3; i++) {
236                 float evi = eigen_val[i];
237
238                 /* Protect against 1D/2D degenerated cases! */
239                 /* Note: not sure why we need square root of eigen values here (which are equivalent to singular values,
240                  * as far as I have understood), but it seems to heavily reduce (if not completely nullify)
241                  * the error due to non-uniform scalings... */
242                 evi = (evi < 1e-6f && evi > -1e-6f) ? ((evi < 0.0f) ? -1e-3f : 1e-3f) : sqrtf_signed(evi);
243                 mul_v3_fl(eigen_vec[i], evi);
244         }
245
246         copy_m4_m3(r_mat, eigen_vec);
247         copy_v3_v3(r_mat[3], center);
248 }
249
250 /**
251  * Set r_space_transform so that best bbox of dst matches best bbox of src.
252  */
253 void BKE_mesh_remap_find_best_match_from_dm(
254         const MVert *verts_dst, const int numverts_dst, DerivedMesh *dm_src, SpaceTransform *r_space_transform)
255 {
256         /* Note that those are done so that we successively get actual mirror matrix (by multiplication of columns)... */
257         const float mirrors[][3] = {
258             {-1.0f,  1.0f,  1.0f},  /* -> -1,  1,  1 */
259             { 1.0f, -1.0f,  1.0f},  /* -> -1, -1,  1 */
260             { 1.0f,  1.0f, -1.0f},  /* -> -1, -1, -1 */
261             { 1.0f, -1.0f,  1.0f},  /* -> -1,  1, -1 */
262             {-1.0f,  1.0f,  1.0f},  /* ->  1,  1, -1 */
263             { 1.0f, -1.0f,  1.0f},  /* ->  1, -1, -1 */
264             { 1.0f,  1.0f, -1.0f},  /* ->  1, -1,  1 */
265             {0.0f, 0.0f, 0.0f},
266         };
267         const float (*mirr)[3];
268
269         float mat_src[4][4], mat_dst[4][4], best_mat_dst[4][4];
270         float best_match = FLT_MAX, match;
271
272         const int numverts_src = dm_src->getNumVerts(dm_src);
273         float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)numverts_src, __func__);
274         dm_src->getVertCos(dm_src, vcos_src);
275
276         mesh_calc_eigen_matrix(NULL, (const float (*)[3])vcos_src, numverts_src, mat_src);
277         mesh_calc_eigen_matrix(verts_dst, NULL, numverts_dst, mat_dst);
278
279         BLI_space_transform_global_from_matrices(r_space_transform, mat_dst, mat_src);
280         match = BKE_mesh_remap_calc_difference_from_dm(r_space_transform, verts_dst, numverts_dst, dm_src);
281         best_match = match;
282         copy_m4_m4(best_mat_dst, mat_dst);
283
284         /* And now, we have to check the otehr sixth possible mirrored versions... */
285         for (mirr = mirrors; (*mirr)[0]; mirr++) {
286                 mul_v3_fl(mat_dst[0], (*mirr)[0]);
287                 mul_v3_fl(mat_dst[1], (*mirr)[1]);
288                 mul_v3_fl(mat_dst[2], (*mirr)[2]);
289
290                 BLI_space_transform_global_from_matrices(r_space_transform, mat_dst, mat_src);
291                 match = BKE_mesh_remap_calc_difference_from_dm(r_space_transform, verts_dst, numverts_dst, dm_src);
292                 if (match < best_match) {
293                         best_match = match;
294                         copy_m4_m4(best_mat_dst, mat_dst);
295                 }
296         }
297
298         BLI_space_transform_global_from_matrices(r_space_transform, best_mat_dst, mat_src);
299
300         MEM_freeN(vcos_src);
301 }
302
303 /** \} */
304
305 /** \name Mesh to mesh mapping
306  * \{ */
307
308 void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num)
309 {
310         MemArena *mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
311
312         BKE_mesh_remap_free(map);
313
314         map->items = BLI_memarena_alloc(mem, sizeof(*map->items) * (size_t)items_num);
315         map->items_num = items_num;
316
317         map->mem = mem;
318 }
319
320 void BKE_mesh_remap_free(MeshPairRemap *map)
321 {
322         if (map->mem) {
323                 BLI_memarena_free((MemArena *)map->mem);
324         }
325
326         map->items_num = 0;
327         map->items = NULL;
328         map->mem = NULL;
329 }
330
331 static void mesh_remap_item_define(
332         MeshPairRemap *map, const int index, const float UNUSED(hit_dist), const int island,
333         const int sources_num, const int *indices_src, const float *weights_src)
334 {
335         MeshPairRemapItem *mapit = &map->items[index];
336         MemArena *mem = map->mem;
337
338         if (sources_num) {
339                 mapit->sources_num = sources_num;
340                 mapit->indices_src = BLI_memarena_alloc(mem, sizeof(*mapit->indices_src) * (size_t)sources_num);
341                 memcpy(mapit->indices_src, indices_src, sizeof(*mapit->indices_src) * (size_t)sources_num);
342                 mapit->weights_src = BLI_memarena_alloc(mem, sizeof(*mapit->weights_src) * (size_t)sources_num);
343                 memcpy(mapit->weights_src, weights_src, sizeof(*mapit->weights_src) * (size_t)sources_num);
344         }
345         else {
346                 mapit->sources_num = 0;
347                 mapit->indices_src = NULL;
348                 mapit->weights_src = NULL;
349         }
350         /* UNUSED */
351         // mapit->hit_dist = hit_dist;
352         mapit->island = island;
353 }
354
355 void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index)
356 {
357         mesh_remap_item_define(map, index, FLT_MAX, 0, 0, NULL, NULL);
358 }
359
360 static int mesh_remap_interp_poly_data_get(
361         const MPoly *mp, MLoop *mloops, const float (*vcos_src)[3], const float point[3],
362         size_t *buff_size, float (**vcos)[3], const bool use_loops, int **indices, float **weights,
363         const bool do_weights, int *r_closest_index)
364 {
365         MLoop *ml;
366         float (*vco)[3];
367         float ref_dist_sq = FLT_MAX;
368         int *index;
369         const int sources_num = mp->totloop;
370         int i;
371
372         if ((size_t)sources_num > *buff_size) {
373                 *buff_size = (size_t)sources_num;
374                 *vcos = MEM_reallocN(*vcos, sizeof(**vcos) * *buff_size);
375                 *indices = MEM_reallocN(*indices, sizeof(**indices) * *buff_size);
376                 if (do_weights) {
377                         *weights = MEM_reallocN(*weights, sizeof(**weights) * *buff_size);
378                 }
379         }
380
381         for (i = 0, ml = &mloops[mp->loopstart], vco = *vcos, index = *indices; i < sources_num; i++, ml++, vco++, index++) {
382                 *index = use_loops ? (int)mp->loopstart + i : (int)ml->v;
383                 copy_v3_v3(*vco, vcos_src[ml->v]);
384                 if (r_closest_index) {
385                         /* Find closest vert/loop in this case. */
386                         const float dist_sq = len_squared_v3v3(point, *vco);
387                         if (dist_sq < ref_dist_sq) {
388                                 ref_dist_sq = dist_sq;
389                                 *r_closest_index = *index;
390                         }
391                 }
392         }
393
394         if (do_weights) {
395                 interp_weights_poly_v3(*weights, *vcos, sources_num, point);
396         }
397
398         return sources_num;
399 }
400
401 /* Little helper when dealing with source islands */
402 typedef struct IslandResult {
403         float factor;           /* A factor, based on which best island for a given set of elements will be selected. */
404         int   index_src;        /* Index of the source. */
405         float hit_dist;         /* The actual hit distance. */
406         float hit_point[3];     /* The hit point, if relevant. */
407 } IslandResult;
408
409 /* Note about all bvh/raycasting stuff below:
410  *      * We must use our ray radius as BVH epsilon too, else rays not hitting anything but 'passing near' an item
411  *        would be missed (since BVH handling would not detect them, 'refining' callbacks won't be executed,
412  *        even though they would return a valid hit).
413  *      * However, in 'islands' case where each hit gets a weight, 'precise' hits should have a better weight than
414  *        'approximate' hits. To address that, we simplify things with:
415  *        ** A first raycast with default, given rayradius;
416  *        ** If first one fails, we do more raycasting with bigger radius, but if hit is found
417  *           it will get smaller weight.
418  *        This only concerns loops, currently (because of islands), and 'sampled' edges/polys norproj.
419  */
420
421 /* At most n raycasts per 'real' ray. */
422 #define MREMAP_RAYCAST_APPROXIMATE_NR 3
423 /* Each approximated raycasts will have n times bigger radius than previous one. */
424 #define MREMAP_RAYCAST_APPROXIMATE_FAC 5.0f
425 /* BVH epsilon value we have to give to bvh 'constructor' when doing approximated raycasting. */
426 #define MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(_ray_radius) \
427         ((float)MREMAP_RAYCAST_APPROXIMATE_NR * MREMAP_RAYCAST_APPROXIMATE_FAC * (_ray_radius))
428
429 /* min 16 rays/face, max 400. */
430 #define MREMAP_RAYCAST_TRI_SAMPLES_MIN 4
431 #define MREMAP_RAYCAST_TRI_SAMPLES_MAX 20
432
433 /* Will be enough in 99% of cases. */
434 #define MREMAP_DEFAULT_BUFSIZE 32
435
436 void BKE_mesh_remap_calc_verts_from_dm(
437         const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
438         const MVert *verts_dst, const int numverts_dst, const bool UNUSED(dirty_nors_dst), DerivedMesh *dm_src,
439         MeshPairRemap *r_map)
440 {
441         const float full_weight = 1.0f;
442         const float max_dist_sq = max_dist * max_dist;
443         int i;
444
445         BLI_assert(mode & MREMAP_MODE_VERT);
446
447         BKE_mesh_remap_init(r_map, numverts_dst);
448
449         if (mode == MREMAP_MODE_TOPOLOGY) {
450                 BLI_assert(numverts_dst == dm_src->getNumVerts(dm_src));
451                 for (i = 0; i < numverts_dst; i++) {
452                         mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
453                 }
454         }
455         else {
456                 BVHTreeFromMesh treedata = {NULL};
457                 BVHTreeNearest nearest = {0};
458                 BVHTreeRayHit rayhit = {0};
459                 float hit_dist;
460                 float tmp_co[3], tmp_no[3];
461
462                 if (mode == MREMAP_MODE_VERT_NEAREST) {
463                         bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
464                         nearest.index = -1;
465
466                         for (i = 0; i < numverts_dst; i++) {
467                                 copy_v3_v3(tmp_co, verts_dst[i].co);
468
469                                 /* Convert the vertex to tree coordinates, if needed. */
470                                 if (space_transform) {
471                                         BLI_space_transform_apply(space_transform, tmp_co);
472                                 }
473
474                                 if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
475                                         mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &nearest.index, &full_weight);
476                                 }
477                                 else {
478                                         /* No source for this dest vertex! */
479                                         BKE_mesh_remap_item_define_invalid(r_map, i);
480                                 }
481                         }
482                 }
483                 else if (ELEM(mode, MREMAP_MODE_VERT_EDGE_NEAREST, MREMAP_MODE_VERT_EDGEINTERP_NEAREST)) {
484                         MEdge *edges_src = dm_src->getEdgeArray(dm_src);
485                         float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
486                         dm_src->getVertCos(dm_src, vcos_src);
487
488                         bvhtree_from_mesh_edges(&treedata, dm_src, 0.0f, 2, 6);
489                         nearest.index = -1;
490
491                         for (i = 0; i < numverts_dst; i++) {
492                                 copy_v3_v3(tmp_co, verts_dst[i].co);
493
494                                 /* Convert the vertex to tree coordinates, if needed. */
495                                 if (space_transform) {
496                                         BLI_space_transform_apply(space_transform, tmp_co);
497                                 }
498
499                                 if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
500                                         MEdge *me = &edges_src[nearest.index];
501                                         const float *v1cos = vcos_src[me->v1];
502                                         const float *v2cos = vcos_src[me->v2];
503
504                                         if (mode == MREMAP_MODE_VERT_EDGE_NEAREST) {
505                                                 const float dist_v1 = len_squared_v3v3(tmp_co, v1cos);
506                                                 const float dist_v2 = len_squared_v3v3(tmp_co, v2cos);
507                                                 const int index = (int)((dist_v1 > dist_v2) ? me->v2 : me->v1);
508                                                 mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight);
509                                         }
510                                         else if (mode == MREMAP_MODE_VERT_EDGEINTERP_NEAREST) {
511                                                 int indices[2];
512                                                 float weights[2];
513
514                                                 indices[0] = (int)me->v1;
515                                                 indices[1] = (int)me->v2;
516
517                                                 /* Weight is inverse of point factor here... */
518                                                 weights[0] = line_point_factor_v3(tmp_co, v2cos, v1cos);
519                                                 CLAMP(weights[0], 0.0f, 1.0f);
520                                                 weights[1] = 1.0f - weights[0];
521
522                                                 mesh_remap_item_define(r_map, i, hit_dist, 0, 2, indices, weights);
523                                         }
524                                 }
525                                 else {
526                                         /* No source for this dest vertex! */
527                                         BKE_mesh_remap_item_define_invalid(r_map, i);
528                                 }
529                         }
530
531                         MEM_freeN(vcos_src);
532                 }
533                 else if (ELEM(mode, MREMAP_MODE_VERT_POLY_NEAREST, MREMAP_MODE_VERT_POLYINTERP_NEAREST,
534                                     MREMAP_MODE_VERT_POLYINTERP_VNORPROJ))
535                 {
536                         MPoly *polys_src = dm_src->getPolyArray(dm_src);
537                         MLoop *loops_src = dm_src->getLoopArray(dm_src);
538                         float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
539
540                         size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
541                         float (*vcos)[3] = MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__);
542                         int *indices = MEM_mallocN(sizeof(*indices) * tmp_buff_size, __func__);
543                         float *weights = MEM_mallocN(sizeof(*weights) * tmp_buff_size, __func__);
544
545                         dm_src->getVertCos(dm_src, vcos_src);
546                         bvhtree_from_mesh_looptri(&treedata, dm_src, (mode & MREMAP_USE_NORPROJ) ? ray_radius : 0.0f, 2, 6);
547
548                         if (mode == MREMAP_MODE_VERT_POLYINTERP_VNORPROJ) {
549                                 for (i = 0; i < numverts_dst; i++) {
550                                         copy_v3_v3(tmp_co, verts_dst[i].co);
551                                         normal_short_to_float_v3(tmp_no, verts_dst[i].no);
552
553                                         /* Convert the vertex to tree coordinates, if needed. */
554                                         if (space_transform) {
555                                                 BLI_space_transform_apply(space_transform, tmp_co);
556                                                 BLI_space_transform_apply_normal(space_transform, tmp_no);
557                                         }
558
559                                         if (mesh_remap_bvhtree_query_raycast(
560                                                 &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
561                                         {
562                                                 const MLoopTri *lt = &treedata.looptri[rayhit.index];
563                                                 MPoly *mp_src = &polys_src[lt->poly];
564                                                 const int sources_num = mesh_remap_interp_poly_data_get(
565                                                         mp_src, loops_src, (const float (*)[3])vcos_src, rayhit.co,
566                                                         &tmp_buff_size, &vcos, false, &indices, &weights, true, NULL);
567
568                                                 mesh_remap_item_define(r_map, i, hit_dist, 0, sources_num, indices, weights);
569                                         }
570                                         else {
571                                                 /* No source for this dest vertex! */
572                                                 BKE_mesh_remap_item_define_invalid(r_map, i);
573                                         }
574                                 }
575                         }
576                         else {
577                                 nearest.index = -1;
578
579                                 for (i = 0; i < numverts_dst; i++) {
580                                         copy_v3_v3(tmp_co, verts_dst[i].co);
581
582                                         /* Convert the vertex to tree coordinates, if needed. */
583                                         if (space_transform) {
584                                                 BLI_space_transform_apply(space_transform, tmp_co);
585                                         }
586
587                                         if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
588                                                 const MLoopTri *lt = &treedata.looptri[nearest.index];
589                                                 MPoly *mp = &polys_src[lt->poly];
590
591                                                 if (mode == MREMAP_MODE_VERT_POLY_NEAREST) {
592                                                         int index;
593                                                         mesh_remap_interp_poly_data_get(
594                                                                 mp, loops_src, (const float (*)[3])vcos_src, nearest.co,
595                                                                 &tmp_buff_size, &vcos, false, &indices, &weights, false,
596                                                                 &index);
597
598                                                         mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight);
599                                                 }
600                                                 else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) {
601                                                         const int sources_num = mesh_remap_interp_poly_data_get(
602                                                                 mp, loops_src, (const float (*)[3])vcos_src, nearest.co,
603                                                                 &tmp_buff_size, &vcos, false, &indices, &weights, true,
604                                                                 NULL);
605
606                                                         mesh_remap_item_define(r_map, i, hit_dist, 0, sources_num, indices, weights);
607                                                 }
608                                         }
609                                         else {
610                                                 /* No source for this dest vertex! */
611                                                 BKE_mesh_remap_item_define_invalid(r_map, i);
612                                         }
613                                 }
614                         }
615
616                         MEM_freeN(vcos_src);
617                         MEM_freeN(vcos);
618                         MEM_freeN(indices);
619                         MEM_freeN(weights);
620                 }
621                 else {
622                         printf("WARNING! Unsupported mesh-to-mesh vertex mapping mode (%d)!\n", mode);
623                         memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numverts_dst);
624                 }
625
626                 free_bvhtree_from_mesh(&treedata);
627         }
628 }
629
630 void BKE_mesh_remap_calc_edges_from_dm(
631         const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
632         const MVert *verts_dst, const int numverts_dst, const MEdge *edges_dst, const int numedges_dst,
633         const bool UNUSED(dirty_nors_dst), DerivedMesh *dm_src, MeshPairRemap *r_map)
634 {
635         const float full_weight = 1.0f;
636         const float max_dist_sq = max_dist * max_dist;
637         int i;
638
639         BLI_assert(mode & MREMAP_MODE_EDGE);
640
641         BKE_mesh_remap_init(r_map, numedges_dst);
642
643         if (mode == MREMAP_MODE_TOPOLOGY) {
644                 BLI_assert(numedges_dst == dm_src->getNumEdges(dm_src));
645                 for (i = 0; i < numedges_dst; i++) {
646                         mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
647                 }
648         }
649         else {
650                 BVHTreeFromMesh treedata = {NULL};
651                 BVHTreeNearest nearest = {0};
652                 BVHTreeRayHit rayhit = {0};
653                 float hit_dist;
654                 float tmp_co[3], tmp_no[3];
655
656                 if (mode == MREMAP_MODE_EDGE_VERT_NEAREST) {
657                         const int num_verts_src = dm_src->getNumVerts(dm_src);
658                         const int num_edges_src = dm_src->getNumEdges(dm_src);
659                         MEdge *edges_src = dm_src->getEdgeArray(dm_src);
660                         float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
661
662                         MeshElemMap *vert_to_edge_src_map;
663                         int         *vert_to_edge_src_map_mem;
664
665                         struct {
666                                 float hit_dist;
667                                 int   index;
668                         } *v_dst_to_src_map = MEM_mallocN(sizeof(*v_dst_to_src_map) * (size_t)numverts_dst, __func__);
669
670                         for (i = 0; i < numverts_dst; i++) {
671                                 v_dst_to_src_map[i].hit_dist = -1.0f;
672                         }
673
674                         BKE_mesh_vert_edge_map_create(&vert_to_edge_src_map, &vert_to_edge_src_map_mem,
675                                                       edges_src, num_verts_src, num_edges_src);
676
677                         dm_src->getVertCos(dm_src, vcos_src);
678
679                         bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
680                         nearest.index = -1;
681
682                         for (i = 0; i < numedges_dst; i++) {
683                                 const MEdge *e_dst = &edges_dst[i];
684                                 float best_totdist = FLT_MAX;
685                                 int best_eidx_src = -1;
686                                 int j = 2;
687
688                                 while (j--) {
689                                         const unsigned int vidx_dst = j ? e_dst->v1 : e_dst->v2;
690
691                                         /* Compute closest verts only once! */
692                                         if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
693                                                 copy_v3_v3(tmp_co, verts_dst[vidx_dst].co);
694
695                                                 /* Convert the vertex to tree coordinates, if needed. */
696                                                 if (space_transform) {
697                                                         BLI_space_transform_apply(space_transform, tmp_co);
698                                                 }
699
700                                                 if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
701                                                         v_dst_to_src_map[vidx_dst].hit_dist = hit_dist;
702                                                         v_dst_to_src_map[vidx_dst].index = nearest.index;
703                                                 }
704                                                 else {
705                                                         /* No source for this dest vert! */
706                                                         v_dst_to_src_map[vidx_dst].hit_dist = FLT_MAX;
707                                                 }
708                                         }
709                                 }
710
711                                 /* Now, check all source edges of closest sources vertices, and select the one giving the smallest
712                                  * total verts-to-verts distance. */
713                                 for (j = 2; j--;) {
714                                         const unsigned int vidx_dst = j ? e_dst->v1 : e_dst->v2;
715                                         const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist;
716                                         const int vidx_src = v_dst_to_src_map[vidx_dst].index;
717                                         int *eidx_src, k;
718
719                                         if (vidx_src < 0) {
720                                                 continue;
721                                         }
722
723                                         eidx_src = vert_to_edge_src_map[vidx_src].indices;
724                                         k = vert_to_edge_src_map[vidx_src].count;
725
726                                         for (; k--; eidx_src++) {
727                                                 MEdge *e_src = &edges_src[*eidx_src];
728                                                 const float *other_co_src = vcos_src[BKE_mesh_edge_other_vert(e_src, vidx_src)];
729                                                 const float *other_co_dst = verts_dst[BKE_mesh_edge_other_vert(e_dst, (int)vidx_dst)].co;
730                                                 const float totdist = first_dist + len_v3v3(other_co_src, other_co_dst);
731
732                                                 if (totdist < best_totdist) {
733                                                         best_totdist = totdist;
734                                                         best_eidx_src = *eidx_src;
735                                                 }
736                                         }
737                                 }
738
739                                 if (best_eidx_src >= 0) {
740                                         const float *co1_src = vcos_src[edges_src[best_eidx_src].v1];
741                                         const float *co2_src = vcos_src[edges_src[best_eidx_src].v2];
742                                         const float *co1_dst = verts_dst[e_dst->v1].co;
743                                         const float *co2_dst = verts_dst[e_dst->v2].co;
744                                         float co_src[3], co_dst[3];
745
746                                         /* TODO: would need an isect_seg_seg_v3(), actually! */
747                                         const int isect_type = isect_line_line_v3(co1_src, co2_src, co1_dst, co2_dst, co_src, co_dst);
748                                         if (isect_type != 0) {
749                                                 const float fac_src = line_point_factor_v3(co_src, co1_src, co2_src);
750                                                 const float fac_dst = line_point_factor_v3(co_dst, co1_dst, co2_dst);
751                                                 if (fac_src < 0.0f) {
752                                                         copy_v3_v3(co_src, co1_src);
753                                                 }
754                                                 else if (fac_src > 1.0f) {
755                                                         copy_v3_v3(co_src, co2_src);
756                                                 }
757                                                 if (fac_dst < 0.0f) {
758                                                         copy_v3_v3(co_dst, co1_dst);
759                                                 }
760                                                 else if (fac_dst > 1.0f) {
761                                                         copy_v3_v3(co_dst, co2_dst);
762                                                 }
763                                         }
764                                         hit_dist = len_v3v3(co_dst, co_src);
765                                         mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight);
766                                 }
767                                 else {
768                                         /* No source for this dest edge! */
769                                         BKE_mesh_remap_item_define_invalid(r_map, i);
770                                 }
771                         }
772
773                         MEM_freeN(vcos_src);
774                         MEM_freeN(v_dst_to_src_map);
775                         MEM_freeN(vert_to_edge_src_map);
776                         MEM_freeN(vert_to_edge_src_map_mem);
777                 }
778                 else if (mode == MREMAP_MODE_EDGE_NEAREST) {
779                         bvhtree_from_mesh_edges(&treedata, dm_src, 0.0f, 2, 6);
780                         nearest.index = -1;
781
782                         for (i = 0; i < numedges_dst; i++) {
783                                 interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
784
785                                 /* Convert the vertex to tree coordinates, if needed. */
786                                 if (space_transform) {
787                                         BLI_space_transform_apply(space_transform, tmp_co);
788                                 }
789
790                                 if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
791                                         mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &nearest.index, &full_weight);
792                                 }
793                                 else {
794                                         /* No source for this dest edge! */
795                                         BKE_mesh_remap_item_define_invalid(r_map, i);
796                                 }
797                         }
798                 }
799                 else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) {
800                         MEdge *edges_src = dm_src->getEdgeArray(dm_src);
801                         MPoly *polys_src = dm_src->getPolyArray(dm_src);
802                         MLoop *loops_src = dm_src->getLoopArray(dm_src);
803                         float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)dm_src->getNumVerts(dm_src), __func__);
804
805                         dm_src->getVertCos(dm_src, vcos_src);
806                         bvhtree_from_mesh_looptri(&treedata, dm_src, 0.0f, 2, 6);
807
808                         for (i = 0; i < numedges_dst; i++) {
809                                 interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
810
811                                 /* Convert the vertex to tree coordinates, if needed. */
812                                 if (space_transform) {
813                                         BLI_space_transform_apply(space_transform, tmp_co);
814                                 }
815
816                                 if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
817                                         const MLoopTri *lt = &treedata.looptri[nearest.index];
818                                         MPoly *mp_src = &polys_src[lt->poly];
819                                         MLoop *ml_src = &loops_src[mp_src->loopstart];
820                                         int nloops = mp_src->totloop;
821                                         float best_dist_sq = FLT_MAX;
822                                         int best_eidx_src = -1;
823
824                                         for (; nloops--; ml_src++) {
825                                                 MEdge *me_src = &edges_src[ml_src->e];
826                                                 float *co1_src = vcos_src[me_src->v1];
827                                                 float *co2_src = vcos_src[me_src->v2];
828                                                 float co_src[3];
829                                                 float dist_sq;
830
831                                                 interp_v3_v3v3(co_src, co1_src, co2_src, 0.5f);
832                                                 dist_sq = len_squared_v3v3(tmp_co, co_src);
833                                                 if (dist_sq < best_dist_sq) {
834                                                         best_dist_sq = dist_sq;
835                                                         best_eidx_src = (int)ml_src->e;
836                                                 }
837                                         }
838                                         if (best_eidx_src >= 0) {
839                                                 mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight);
840                                         }
841                                 }
842                                 else {
843                                         /* No source for this dest edge! */
844                                         BKE_mesh_remap_item_define_invalid(r_map, i);
845                                 }
846                         }
847
848                         MEM_freeN(vcos_src);
849                 }
850                 else if (mode == MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ) {
851                         const int num_rays_min = 5, num_rays_max = 100;
852                         const int numedges_src = dm_src->getNumEdges(dm_src);
853
854                         /* Subtleness - this one we can allocate only max number of cast rays per edges! */
855                         int *indices = MEM_mallocN(sizeof(*indices) * (size_t)min_ii(numedges_src, num_rays_max), __func__);
856                         /* Here it's simpler to just allocate for all edges :/ */
857                         float *weights = MEM_mallocN(sizeof(*weights) * (size_t)numedges_src, __func__);
858
859                         bvhtree_from_mesh_edges(&treedata, dm_src, MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius), 2, 6);
860
861                         for (i = 0; i < numedges_dst; i++) {
862                                 /* For each dst edge, we sample some rays from it (interpolated from its vertices)
863                                  * and use their hits to interpolate from source edges. */
864                                 const MEdge *me = &edges_dst[i];
865                                 float v1_co[3], v2_co[3];
866                                 float v1_no[3], v2_no[3];
867
868                                 int grid_size;
869                                 float edge_dst_len;
870                                 float grid_step;
871
872                                 float totweights = 0.0f;
873                                 float hit_dist_accum = 0.0f;
874                                 int sources_num = 0;
875                                 int j;
876
877                                 copy_v3_v3(v1_co, verts_dst[me->v1].co);
878                                 copy_v3_v3(v2_co, verts_dst[me->v2].co);
879
880                                 normal_short_to_float_v3(v1_no, verts_dst[me->v1].no);
881                                 normal_short_to_float_v3(v2_no, verts_dst[me->v2].no);
882
883                                 /* We do our transform here, allows to interpolate from normals already in src space. */
884                                 if (space_transform) {
885                                         BLI_space_transform_apply(space_transform, v1_co);
886                                         BLI_space_transform_apply(space_transform, v2_co);
887                                         BLI_space_transform_apply_normal(space_transform, v1_no);
888                                         BLI_space_transform_apply_normal(space_transform, v2_no);
889                                 }
890
891                                 copy_vn_fl(weights, (int)numedges_src, 0.0f);
892
893                                 /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast),
894                                  * with lower/upper bounds. */
895                                 edge_dst_len = len_v3v3(v1_co, v2_co);
896
897                                 grid_size = (int)((edge_dst_len / ray_radius) + 0.5f);
898                                 CLAMP(grid_size, num_rays_min, num_rays_max);  /* min 5 rays/edge, max 100. */
899
900                                 grid_step = 1.0f / (float)grid_size;  /* Not actual distance here, rather an interp fac... */
901
902                                 /* And now we can cast all our rays, and see what we get! */
903                                 for (j = 0; j < grid_size; j++) {
904                                         const float fac = grid_step * (float)j;
905
906                                         int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
907                                         float w = 1.0f;
908
909                                         interp_v3_v3v3(tmp_co, v1_co, v2_co, fac);
910                                         interp_v3_v3v3_slerp_safe(tmp_no, v1_no, v2_no, fac);
911
912                                         while (n--) {
913                                                 if (mesh_remap_bvhtree_query_raycast(
914                                                         &treedata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
915                                                 {
916                                                         weights[rayhit.index] += w;
917                                                         totweights += w;
918                                                         hit_dist_accum += hit_dist;
919                                                         break;
920                                                 }
921                                                 /* Next iteration will get bigger radius but smaller weight! */
922                                                 w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
923                                         }
924                                 }
925                                 /* A sampling is valid (as in, its result can be considered as valid sources) only if at least
926                                  * half of the rays found a source! */
927                                 if (totweights > ((float)grid_size / 2.0f)) {
928                                         for (j = 0; j < (int)numedges_src; j++) {
929                                                 if (!weights[j]) {
930                                                         continue;
931                                                 }
932                                                 /* Note: sources_num is always <= j! */
933                                                 weights[sources_num] = weights[j] / totweights;
934                                                 indices[sources_num] = j;
935                                                 sources_num++;
936                                         }
937                                         mesh_remap_item_define(r_map, i, hit_dist_accum / totweights, 0,
938                                                                           sources_num, indices, weights);
939                                 }
940                                 else {
941                                         /* No source for this dest edge! */
942                                         BKE_mesh_remap_item_define_invalid(r_map, i);
943                                 }
944                         }
945
946                         MEM_freeN(indices);
947                         MEM_freeN(weights);
948                 }
949                 else {
950                         printf("WARNING! Unsupported mesh-to-mesh edge mapping mode (%d)!\n", mode);
951                         memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numedges_dst);
952                 }
953
954                 free_bvhtree_from_mesh(&treedata);
955         }
956 }
957
958 #define POLY_UNSET       0
959 #define POLY_CENTER_INIT 1
960 #define POLY_COMPLETE    2
961
962 static void mesh_island_to_astar_graph_edge_process(
963         MeshIslandStore *islands, const int island_index, BLI_AStarGraph *as_graph,
964         MVert *verts, MPoly *polys, MLoop *loops,
965         const int edge_idx, BLI_bitmap *done_edges, MeshElemMap *edge_to_poly_map, const bool is_edge_innercut,
966         int *poly_island_index_map, float (*poly_centers)[3], unsigned char *poly_status)
967 {
968         int *poly_island_indices = BLI_array_alloca(poly_island_indices, (size_t)edge_to_poly_map[edge_idx].count);
969         int i, j;
970
971         for (i = 0; i < edge_to_poly_map[edge_idx].count; i++) {
972                 const int pidx = edge_to_poly_map[edge_idx].indices[i];
973                 MPoly *mp = &polys[pidx];
974                 const int pidx_isld = islands ? poly_island_index_map[pidx] : pidx;
975                 void *custom_data = is_edge_innercut ? SET_INT_IN_POINTER(edge_idx) : SET_INT_IN_POINTER(-1);
976
977                 if (UNLIKELY(islands && (islands->items_to_islands[mp->loopstart] != island_index))) {
978                         /* poly not in current island, happens with border edges... */
979                         poly_island_indices[i] = -1;
980                         continue;
981                 }
982
983                 if (poly_status[pidx_isld] == POLY_COMPLETE) {
984                         poly_island_indices[i] = pidx_isld;
985                         continue;
986                 }
987
988                 if (poly_status[pidx_isld] == POLY_UNSET) {
989                         BKE_mesh_calc_poly_center(mp, &loops[mp->loopstart], verts, poly_centers[pidx_isld]);
990                         BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]);
991                         poly_status[pidx_isld] = POLY_CENTER_INIT;
992                 }
993
994                 for (j = i; j--;) {
995                         float dist_cost;
996                         const int pidx_isld_other = poly_island_indices[j];
997
998                         if (pidx_isld_other == -1 || poly_status[pidx_isld_other] == POLY_COMPLETE) {
999                                 /* If the other poly is complete, that link has already been added! */
1000                                 continue;
1001                         }
1002                         dist_cost = len_v3v3(poly_centers[pidx_isld_other], poly_centers[pidx_isld]);
1003                         BLI_astar_node_link_add(as_graph, pidx_isld_other, pidx_isld, dist_cost, custom_data);
1004                 }
1005
1006                 poly_island_indices[i] = pidx_isld;
1007         }
1008
1009         BLI_BITMAP_ENABLE(done_edges, edge_idx);
1010 }
1011
1012 static void mesh_island_to_astar_graph(
1013         MeshIslandStore *islands, const int island_index,
1014         MVert *verts, MeshElemMap *edge_to_poly_map, const int numedges, MLoop *loops, MPoly *polys, const int numpolys,
1015         BLI_AStarGraph *r_as_graph)
1016 {
1017         MeshElemMap *island_poly_map = islands ? islands->islands[island_index] : NULL;
1018         MeshElemMap *island_einnercut_map = islands ? islands->innercuts[island_index] : NULL;
1019
1020         int *poly_island_index_map = NULL;
1021         BLI_bitmap *done_edges = BLI_BITMAP_NEW(numedges, __func__);
1022
1023         const int node_num = islands ? island_poly_map->count : numpolys;
1024         unsigned char *poly_status = MEM_callocN(sizeof(*poly_status) * (size_t)node_num, __func__);
1025         float (*poly_centers)[3];
1026
1027         int pidx_isld;
1028         int i;
1029
1030         BLI_astar_graph_init(r_as_graph, node_num, NULL);
1031         /* poly_centers is owned by graph memarena. */
1032         poly_centers = BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_centers) * (size_t)node_num);
1033
1034         if (islands) {
1035                 /* poly_island_index_map is owned by graph memarena. */
1036                 poly_island_index_map = BLI_memarena_calloc(r_as_graph->mem, sizeof(*poly_island_index_map) * (size_t)numpolys);
1037                 for (i = island_poly_map->count; i--;) {
1038                         poly_island_index_map[island_poly_map->indices[i]] = i;
1039                 }
1040
1041                 r_as_graph->custom_data = poly_island_index_map;
1042
1043                 for (i = island_einnercut_map->count; i--;) {
1044                         mesh_island_to_astar_graph_edge_process(
1045                                 islands, island_index, r_as_graph, verts, polys, loops,
1046                                 island_einnercut_map->indices[i], done_edges, edge_to_poly_map, true,
1047                                 poly_island_index_map, poly_centers, poly_status);
1048                 }
1049         }
1050
1051         for (pidx_isld = node_num; pidx_isld--;) {
1052                 const int pidx = islands ? island_poly_map->indices[pidx_isld] : pidx_isld;
1053                 MPoly *mp = &polys[pidx];
1054                 int pl_idx, l_idx;
1055
1056                 if (poly_status[pidx_isld] == POLY_COMPLETE) {
1057                         continue;
1058                 }
1059
1060                 for (pl_idx = 0, l_idx = mp->loopstart; pl_idx < mp->totloop; pl_idx++, l_idx++) {
1061                         MLoop *ml = &loops[l_idx];
1062
1063                         if (BLI_BITMAP_TEST(done_edges, ml->e)) {
1064                                 continue;
1065                         }
1066
1067                         mesh_island_to_astar_graph_edge_process(
1068                                 islands, island_index, r_as_graph, verts, polys, loops,
1069                                 (int)ml->e, done_edges, edge_to_poly_map, false,
1070                                 poly_island_index_map, poly_centers, poly_status);
1071                 }
1072                 poly_status[pidx_isld] = POLY_COMPLETE;
1073         }
1074
1075         MEM_freeN(done_edges);
1076         MEM_freeN(poly_status);
1077 }
1078
1079 #undef POLY_UNSET
1080 #undef POLY_CENTER_INIT
1081 #undef POLY_COMPLETE
1082
1083 /* Our 'f_cost' callback func, to find shortest poly-path between two remapped-loops.
1084  * Note we do not want to make innercuts 'walls' here, just detect when the shortest path goes by those. */
1085 static float mesh_remap_calc_loops_astar_f_cost(
1086         BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, BLI_AStarGNLink *link,
1087         const int node_idx_curr, const int node_idx_next, const int node_idx_dst)
1088 {
1089         float *co_next, *co_dest;
1090
1091         if (link && (GET_INT_FROM_POINTER(link->custom_data) != -1)) {
1092                 /* An innercut edge... We tag our solution as potentially crossing innercuts.
1093                  * Note it might not be the case in the end (AStar will explore around optimal path), but helps
1094                  * trimming off some processing later... */
1095                 if (!GET_INT_FROM_POINTER(as_solution->custom_data)) {
1096                         as_solution->custom_data = SET_INT_IN_POINTER(true);
1097                 }
1098         }
1099
1100         /* Our heuristic part of current f_cost is distance from next node to destination one.
1101          * It is guaranteed to be less than (or equal to) actual shortest poly-path between next node and destination one.
1102          */
1103         co_next = (float *)as_graph->nodes[node_idx_next].custom_data;
1104         co_dest = (float *)as_graph->nodes[node_idx_dst].custom_data;
1105         return (link ? (as_solution->g_costs[node_idx_curr] + link->cost) : 0.0f) + len_v3v3(co_next, co_dest);
1106 }
1107
1108 #define ASTAR_STEPS_MAX 64
1109
1110
1111 void BKE_mesh_remap_calc_loops_from_dm(
1112         const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
1113         MVert *verts_dst, const int numverts_dst, MEdge *edges_dst, const int numedges_dst,
1114         MLoop *loops_dst, const int numloops_dst, MPoly *polys_dst, const int numpolys_dst,
1115         CustomData *ldata_dst, CustomData *pdata_dst,
1116         const bool use_split_nors_dst, const float split_angle_dst, const bool dirty_nors_dst,
1117         DerivedMesh *dm_src, const bool use_split_nors_src, const float split_angle_src,
1118         MeshRemapIslandsCalc gen_islands_src, const float islands_precision_src, MeshPairRemap *r_map)
1119 {
1120         const float full_weight = 1.0f;
1121         const float max_dist_sq = max_dist * max_dist;
1122
1123         int i;
1124
1125         BLI_assert(mode & MREMAP_MODE_LOOP);
1126         BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
1127
1128         BKE_mesh_remap_init(r_map, numloops_dst);
1129
1130         if (mode == MREMAP_MODE_TOPOLOGY) {
1131                 /* In topology mapping, we assume meshes are identical, islands included! */
1132                 BLI_assert(numloops_dst == dm_src->getNumLoops(dm_src));
1133                 for (i = 0; i < numloops_dst; i++) {
1134                         mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
1135                 }
1136         }
1137         else {
1138                 BVHTreeFromMesh *treedata = NULL;
1139                 BVHTreeNearest nearest = {0};
1140                 BVHTreeRayHit rayhit = {0};
1141                 int num_trees = 0;
1142                 float hit_dist;
1143                 float tmp_co[3], tmp_no[3];
1144
1145                 const bool use_from_vert = (mode & MREMAP_USE_VERT);
1146
1147                 MeshIslandStore island_store = {0};
1148                 bool use_islands = false;
1149
1150                 BLI_AStarGraph *as_graphdata = NULL;
1151                 BLI_AStarSolution as_solution = {0};
1152                 const int isld_steps_src = islands_precision_src ?
1153                                            max_ii((int)(ASTAR_STEPS_MAX * islands_precision_src + 0.499f), 1) : 0;
1154
1155                 float (*poly_nors_src)[3] = NULL;
1156                 float (*loop_nors_src)[3] = NULL;
1157                 float (*poly_nors_dst)[3] = NULL;
1158                 float (*loop_nors_dst)[3] = NULL;
1159
1160                 float (*poly_cents_src)[3] = NULL;
1161
1162                 MeshElemMap *vert_to_loop_map_src = NULL;
1163                 int *vert_to_loop_map_src_buff = NULL;
1164                 MeshElemMap *vert_to_poly_map_src = NULL;
1165                 int *vert_to_poly_map_src_buff = NULL;
1166                 MeshElemMap *edge_to_poly_map_src = NULL;
1167                 int *edge_to_poly_map_src_buff = NULL;
1168                 MeshElemMap *poly_to_looptri_map_src = NULL;
1169                 int *poly_to_looptri_map_src_buff = NULL;
1170
1171                 /* Unlike above, those are one-to-one mappings, simpler! */
1172                 int *loop_to_poly_map_src = NULL;
1173
1174                 bool verts_allocated_src;
1175                 MVert *verts_src = DM_get_vert_array(dm_src, &verts_allocated_src);
1176                 const int num_verts_src = dm_src->getNumVerts(dm_src);
1177                 float (*vcos_src)[3] = NULL;
1178                 bool edges_allocated_src;
1179                 MEdge *edges_src = DM_get_edge_array(dm_src, &edges_allocated_src);
1180                 const int num_edges_src = dm_src->getNumEdges(dm_src);
1181                 bool loops_allocated_src;
1182                 MLoop *loops_src = DM_get_loop_array(dm_src, &loops_allocated_src);
1183                 const int num_loops_src = dm_src->getNumLoops(dm_src);
1184                 bool polys_allocated_src;
1185                 MPoly *polys_src = DM_get_poly_array(dm_src, &polys_allocated_src);
1186                 const int num_polys_src = dm_src->getNumPolys(dm_src);
1187                 const MLoopTri *looptri_src = NULL;
1188                 int num_looptri_src = 0;
1189
1190                 size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE;
1191                 float (*vcos_interp)[3] = NULL;
1192                 int *indices_interp = NULL;
1193                 float *weights_interp = NULL;
1194
1195                 MLoop *ml_src, *ml_dst;
1196                 MPoly *mp_src, *mp_dst;
1197                 int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
1198
1199                 IslandResult **islands_res;
1200                 size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE;
1201
1202                 const float bvh_epsilon = (mode & MREMAP_USE_NORPROJ) ? MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius) : 0.0f;
1203
1204                 if (!use_from_vert) {
1205                         vcos_src = MEM_mallocN(sizeof(*vcos_src) * (size_t)num_verts_src, __func__);
1206                         dm_src->getVertCos(dm_src, vcos_src);
1207
1208                         vcos_interp = MEM_mallocN(sizeof(*vcos_interp) * buff_size_interp, __func__);
1209                         indices_interp = MEM_mallocN(sizeof(*indices_interp) * buff_size_interp, __func__);
1210                         weights_interp = MEM_mallocN(sizeof(*weights_interp) * buff_size_interp, __func__);
1211                 }
1212
1213                 {
1214                         const bool need_lnors_src = (mode & MREMAP_USE_LOOP) && (mode & MREMAP_USE_NORMAL);
1215                         const bool need_lnors_dst = need_lnors_src || (mode & MREMAP_USE_NORPROJ);
1216                         const bool need_pnors_src = need_lnors_src || ((mode & MREMAP_USE_POLY) && (mode & MREMAP_USE_NORMAL));
1217                         const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
1218
1219                         if (need_pnors_dst) {
1220                                 /* Cache poly nors into a temp CDLayer. */
1221                                 poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
1222                                 if (!poly_nors_dst) {
1223                                         poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
1224                                         CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
1225                                 }
1226                                 if (dirty_nors_dst) {
1227                                         BKE_mesh_calc_normals_poly(verts_dst, NULL, numverts_dst, loops_dst, polys_dst,
1228                                                                    numloops_dst, numpolys_dst, poly_nors_dst, true);
1229                                 }
1230                         }
1231                         if (need_lnors_dst) {
1232                                 short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
1233
1234                                 /* Cache poly nors into a temp CDLayer. */
1235                                 loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
1236                                 if (dirty_nors_dst || !loop_nors_dst) {
1237                                         if (!loop_nors_dst) {
1238                                                 loop_nors_dst = CustomData_add_layer(ldata_dst, CD_NORMAL, CD_CALLOC, NULL, numloops_dst);
1239                                                 CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
1240                                         }
1241                                         BKE_mesh_normals_loop_split(verts_dst, numverts_dst, edges_dst, numedges_dst,
1242                                                                     loops_dst, loop_nors_dst, numloops_dst,
1243                                                                     polys_dst, (const float (*)[3])poly_nors_dst, numpolys_dst,
1244                                                                     use_split_nors_dst, split_angle_dst, NULL, custom_nors_dst, NULL);
1245                                 }
1246                         }
1247                         if (need_pnors_src || need_lnors_src) {
1248                                 /* Simpler for now, calcNormals never stores pnors :( */
1249                                 dm_src->calcLoopNormals(dm_src, use_split_nors_src, split_angle_src);
1250
1251                                 if (need_pnors_src) {
1252                                         poly_nors_src = dm_src->getPolyDataArray(dm_src, CD_NORMAL);
1253                                 }
1254                                 if (need_lnors_src) {
1255                                         loop_nors_src = dm_src->getLoopDataArray(dm_src, CD_NORMAL);
1256                                 }
1257                         }
1258                 }
1259
1260                 if (use_from_vert) {
1261                         BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, &vert_to_loop_map_src_buff,
1262                                                       polys_src, loops_src, num_verts_src, num_polys_src, num_loops_src);
1263                         if (mode & MREMAP_USE_POLY) {
1264                                 BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, &vert_to_poly_map_src_buff,
1265                                                               polys_src, loops_src, num_verts_src, num_polys_src, num_loops_src);
1266                         }
1267                 }
1268
1269                 /* Needed for islands (or plain mesh) to AStar graph conversion. */
1270                 BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src, &edge_to_poly_map_src_buff,
1271                                               edges_src, num_edges_src, polys_src, num_polys_src, loops_src, num_loops_src);
1272                 if (use_from_vert) {
1273                         loop_to_poly_map_src = MEM_mallocN(sizeof(*loop_to_poly_map_src) * (size_t)num_loops_src, __func__);
1274                         poly_cents_src = MEM_mallocN(sizeof(*poly_cents_src) * (size_t)num_polys_src, __func__);
1275                         for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) {
1276                                 ml_src = &loops_src[mp_src->loopstart];
1277                                 for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop; plidx_src++, lidx_src++) {
1278                                         loop_to_poly_map_src[lidx_src] = pidx_src;
1279                                 }
1280                                 BKE_mesh_calc_poly_center(mp_src, ml_src, verts_src, poly_cents_src[pidx_src]);
1281                         }
1282                 }
1283
1284                 /* Island makes things slightly more complex here.
1285                  * Basically, we:
1286                  *     * Make one treedata for each island's elements.
1287                  *     * Check all loops of a same dest poly against all treedata.
1288                  *     * Choose the island's elements giving the best results.
1289                  */
1290
1291                 /* First, generate the islands, if possible. */
1292                 if (gen_islands_src) {
1293                         use_islands = gen_islands_src(
1294                                 verts_src, num_verts_src,
1295                                 edges_src, num_edges_src,
1296                                 polys_src, num_polys_src,
1297                                 loops_src, num_loops_src,
1298                                 &island_store);
1299
1300                         num_trees = use_islands ? island_store.islands_num : 1;
1301                         treedata = MEM_callocN(sizeof(*treedata) * (size_t)num_trees, __func__);
1302                         if (isld_steps_src) {
1303                                 as_graphdata = MEM_callocN(sizeof(*as_graphdata) * (size_t)num_trees, __func__);
1304                         }
1305
1306                         if (use_islands) {
1307                                 /* We expect our islands to contain poly indices, with edge indices of 'inner cuts',
1308                                  * and a mapping loops -> islands indices.
1309                                  * This implies all loops of a same poly are in the same island. */
1310                                 BLI_assert((island_store.item_type == MISLAND_TYPE_LOOP) &&
1311                                            (island_store.island_type == MISLAND_TYPE_POLY) &&
1312                                            (island_store.innercut_type == MISLAND_TYPE_EDGE));
1313                         }
1314                 }
1315                 else {
1316                         num_trees = 1;
1317                         treedata = MEM_callocN(sizeof(*treedata), __func__);
1318                         if (isld_steps_src) {
1319                                 as_graphdata = MEM_callocN(sizeof(*as_graphdata), __func__);
1320                         }
1321                 }
1322
1323                 /* Build our AStar graphs. */
1324                 if (isld_steps_src) {
1325                         for (tindex = 0; tindex < num_trees; tindex++) {
1326                                 mesh_island_to_astar_graph(
1327                                         use_islands ? &island_store : NULL, tindex, verts_src, edge_to_poly_map_src, num_edges_src,
1328                                         loops_src, polys_src, num_polys_src, &as_graphdata[tindex]);
1329                         }
1330                 }
1331
1332                 /* Build our BVHtrees, either from verts or tessfaces. */
1333                 if (use_from_vert) {
1334                         if (use_islands) {
1335                                 BLI_bitmap *verts_active = BLI_BITMAP_NEW((size_t)num_verts_src, __func__);
1336
1337                                 for (tindex = 0; tindex < num_trees; tindex++) {
1338                                         MeshElemMap *isld = island_store.islands[tindex];
1339                                         int num_verts_active = 0;
1340                                         BLI_BITMAP_SET_ALL(verts_active, false, (size_t)num_verts_src);
1341                                         for (i = 0; i < isld->count; i++) {
1342                                                 mp_src = &polys_src[isld->indices[i]];
1343                                                 for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; lidx_src++) {
1344                                                         const unsigned int vidx_src = loops_src[lidx_src].v;
1345                                                         if (!BLI_BITMAP_TEST(verts_active, vidx_src)) {
1346                                                                 BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v);
1347                                                                 num_verts_active++;
1348                                                         }
1349                                                 }
1350                                         }
1351                                         /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */
1352                                         bvhtree_from_mesh_verts_ex(&treedata[tindex], verts_src, num_verts_src, verts_allocated_src,
1353                                                                    verts_active, num_verts_active, bvh_epsilon, 2, 6);
1354                                         if (verts_allocated_src) {
1355                                                 verts_allocated_src = false;  /* Only 'give' our verts once, to first tree! */
1356                                         }
1357                                 }
1358
1359                                 MEM_freeN(verts_active);
1360                         }
1361                         else {
1362                                 BLI_assert(num_trees == 1);
1363                                 bvhtree_from_mesh_verts(&treedata[0], dm_src, bvh_epsilon, 2, 6);
1364                         }
1365                 }
1366                 else {  /* We use polygons. */
1367                         if (use_islands) {
1368                                 /* bvhtree here uses looptri faces... */
1369                                 const unsigned int dirty_tess_flag = dm_src->dirty & DM_DIRTY_TESS_CDLAYERS;
1370                                 BLI_bitmap *looptri_active;
1371
1372                                 /* We do not care about tessellated data here, only geometry itself is important. */
1373                                 if (dirty_tess_flag) {
1374                                         dm_src->dirty &= ~dirty_tess_flag;
1375                                 }
1376                                 if (dirty_tess_flag) {
1377                                         dm_src->dirty |= dirty_tess_flag;
1378                                 }
1379
1380                                 looptri_src = dm_src->getLoopTriArray(dm_src);
1381                                 num_looptri_src = dm_src->getNumLoopTri(dm_src);
1382                                 looptri_active = BLI_BITMAP_NEW((size_t)num_looptri_src, __func__);
1383
1384                                 for (tindex = 0; tindex < num_trees; tindex++) {
1385                                         int num_looptri_active = 0;
1386                                         BLI_BITMAP_SET_ALL(looptri_active, false, (size_t)num_looptri_src);
1387                                         for (i = 0; i < num_looptri_src; i++) {
1388                                                 mp_src = &polys_src[looptri_src[i].poly];
1389                                                 if (island_store.items_to_islands[mp_src->loopstart] == tindex) {
1390                                                         BLI_BITMAP_ENABLE(looptri_active, i);
1391                                                         num_looptri_active++;
1392                                                 }
1393                                         }
1394                                         /* verts and faces 'ownership' is transfered to treedata here, which will handle its freeing. */
1395                                         bvhtree_from_mesh_looptri_ex(
1396                                                 &treedata[tindex],
1397                                                 verts_src, verts_allocated_src,
1398                                                 loops_src, loops_allocated_src,
1399                                                 looptri_src, num_looptri_src, false,
1400                                                 looptri_active, num_looptri_active, bvh_epsilon, 2, 6);
1401                                         if (verts_allocated_src) {
1402                                                 verts_allocated_src = false;  /* Only 'give' our verts once, to first tree! */
1403                                         }
1404                                         if (loops_allocated_src) {
1405                                                 loops_allocated_src = false;  /* Only 'give' our loops once, to first tree! */
1406                                         }
1407                                 }
1408
1409                                 MEM_freeN(looptri_active);
1410                         }
1411                         else {
1412                                 BLI_assert(num_trees == 1);
1413                                 bvhtree_from_mesh_looptri(&treedata[0], dm_src, bvh_epsilon, 2, 6);
1414                         }
1415                 }
1416
1417                 /* And check each dest poly! */
1418                 islands_res = MEM_mallocN(sizeof(*islands_res) * (size_t)num_trees, __func__);
1419                 for (tindex = 0; tindex < num_trees; tindex++) {
1420                         islands_res[tindex] = MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__);
1421                 }
1422
1423                 for (pidx_dst = 0, mp_dst = polys_dst; pidx_dst < numpolys_dst; pidx_dst++, mp_dst++) {
1424                         float pnor_dst[3];
1425
1426                         /* Only in use_from_vert case, we may need polys' centers as fallback in case we cannot decide which
1427                          * corner to use from normals only. */
1428                         float pcent_dst[3];
1429                         bool pcent_dst_valid = false;
1430
1431                         if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
1432                                 copy_v3_v3(pnor_dst, poly_nors_dst[pidx_dst]);
1433                                 if (space_transform) {
1434                                         BLI_space_transform_apply_normal(space_transform, pnor_dst);
1435                                 }
1436                         }
1437
1438                         if ((size_t)mp_dst->totloop > islands_res_buff_size) {
1439                                 islands_res_buff_size = (size_t)mp_dst->totloop + MREMAP_DEFAULT_BUFSIZE;
1440                                 for (tindex = 0; tindex < num_trees; tindex++) {
1441                                         islands_res[tindex] = MEM_reallocN(islands_res[tindex], sizeof(**islands_res) * islands_res_buff_size);
1442                                 }
1443                         }
1444
1445                         for (tindex = 0; tindex < num_trees; tindex++) {
1446                                 BVHTreeFromMesh *tdata = &treedata[tindex];
1447
1448                                 ml_dst = &loops_dst[mp_dst->loopstart];
1449                                 for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) {
1450                                         if (use_from_vert) {
1451                                                 MeshElemMap *vert_to_refelem_map_src = NULL;
1452
1453                                                 copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
1454                                                 nearest.index = -1;
1455
1456                                                 /* Convert the vertex to tree coordinates, if needed. */
1457                                                 if (space_transform) {
1458                                                         BLI_space_transform_apply(space_transform, tmp_co);
1459                                                 }
1460
1461                                                 if (mesh_remap_bvhtree_query_nearest(tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
1462                                                         float (*nor_dst)[3];
1463                                                         float (*nors_src)[3];
1464                                                         float best_nor_dot = -2.0f;
1465                                                         float best_sqdist_fallback = FLT_MAX;
1466                                                         int best_index_src = -1;
1467
1468                                                         if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) {
1469                                                                 copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]);
1470                                                                 if (space_transform) {
1471                                                                         BLI_space_transform_apply_normal(space_transform, tmp_no);
1472                                                                 }
1473                                                                 nor_dst = &tmp_no;
1474                                                                 nors_src = loop_nors_src;
1475                                                                 vert_to_refelem_map_src = vert_to_loop_map_src;
1476                                                         }
1477                                                         else {  /* if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { */
1478                                                                 nor_dst = &pnor_dst;
1479                                                                 nors_src = poly_nors_src;
1480                                                                 vert_to_refelem_map_src = vert_to_poly_map_src;
1481                                                         }
1482
1483                                                         for (i = vert_to_refelem_map_src[nearest.index].count; i--;) {
1484                                                                 const int index_src = vert_to_refelem_map_src[nearest.index].indices[i];
1485                                                                 BLI_assert(index_src != -1);
1486                                                                 const float dot = dot_v3v3(nors_src[index_src], *nor_dst);
1487
1488                                                                 pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ?
1489                                                                                loop_to_poly_map_src[index_src] : index_src;
1490                                                                 /* WARNING! This is not the *real* lidx_src in case of POLYNOR, we only use it
1491                                                                  *          to check we stay on current island (all loops from a given poly are
1492                                                                  *          on same island!). */
1493                                                                 lidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ?
1494                                                                                index_src : polys_src[pidx_src].loopstart;
1495
1496                                                                 /* A same vert may be at the boundary of several islands! Hence, we have to ensure
1497                                                                  * poly/loop we are currently considering *belongs* to current island! */
1498                                                                 if (use_islands && island_store.items_to_islands[lidx_src] != tindex) {
1499                                                                         continue;
1500                                                                 }
1501
1502                                                                 if (dot > best_nor_dot - 1e-6f) {
1503                                                                         /* We need something as fallback decision in case dest normal matches several
1504                                                                          * source normals (see T44522), using distance between polys' centers here. */
1505                                                                         float *pcent_src;
1506                                                                         float sqdist;
1507
1508                                                                         mp_src = &polys_src[pidx_src];
1509                                                                         ml_src = &loops_src[mp_src->loopstart];
1510
1511                                                                         if (!pcent_dst_valid) {
1512                                                                                 BKE_mesh_calc_poly_center(
1513                                                                                             mp_dst, &loops_dst[mp_dst->loopstart], verts_dst, pcent_dst);
1514                                                                                 pcent_dst_valid = true;
1515                                                                         }
1516                                                                         pcent_src = poly_cents_src[pidx_src];
1517                                                                         sqdist = len_squared_v3v3(pcent_dst, pcent_src);
1518
1519                                                                         if ((dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) {
1520                                                                                 best_nor_dot = dot;
1521                                                                                 best_sqdist_fallback = sqdist;
1522                                                                                 best_index_src = index_src;
1523                                                                         }
1524                                                                 }
1525                                                         }
1526                                                         if (best_index_src == -1) {
1527                                                                 /* We found no item to map back from closest vertex... */
1528                                                                 best_nor_dot = -1.0f;
1529                                                                 hit_dist = FLT_MAX;
1530                                                         }
1531                                                         else if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
1532                                                                 /* Our best_index_src is a poly one for now!
1533                                                                  * Have to find its loop matching our closest vertex. */
1534                                                                 mp_src = &polys_src[best_index_src];
1535                                                                 ml_src = &loops_src[mp_src->loopstart];
1536                                                                 for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++, ml_src++) {
1537                                                                         if ((int)ml_src->v == nearest.index) {
1538                                                                                 best_index_src = plidx_src + mp_src->loopstart;
1539                                                                                 break;
1540                                                                         }
1541                                                                 }
1542                                                         }
1543                                                         best_nor_dot = (best_nor_dot + 1.0f) * 0.5f;
1544                                                         islands_res[tindex][plidx_dst].factor = hit_dist ? (best_nor_dot / hit_dist) : 1e18f;
1545                                                         islands_res[tindex][plidx_dst].hit_dist = hit_dist;
1546                                                         islands_res[tindex][plidx_dst].index_src = best_index_src;
1547                                                 }
1548                                                 else {
1549                                                         /* No source for this dest loop! */
1550                                                         islands_res[tindex][plidx_dst].factor = 0.0f;
1551                                                         islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
1552                                                         islands_res[tindex][plidx_dst].index_src = -1;
1553                                                 }
1554                                         }
1555                                         else if (mode & MREMAP_USE_NORPROJ) {
1556                                                 int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
1557                                                 float w = 1.0f;
1558
1559                                                 copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
1560                                                 copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]);
1561
1562                                                 /* We do our transform here, since we may do several raycast/nearest queries. */
1563                                                 if (space_transform) {
1564                                                         BLI_space_transform_apply(space_transform, tmp_co);
1565                                                         BLI_space_transform_apply_normal(space_transform, tmp_no);
1566                                                 }
1567
1568                                                 while (n--) {
1569                                                         if (mesh_remap_bvhtree_query_raycast(
1570                                                                 tdata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
1571                                                         {
1572                                                                 islands_res[tindex][plidx_dst].factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) * w;
1573                                                                 islands_res[tindex][plidx_dst].hit_dist = hit_dist;
1574                                                                 islands_res[tindex][plidx_dst].index_src = (int)tdata->looptri[rayhit.index].poly;
1575                                                                 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.co);
1576                                                                 break;
1577                                                         }
1578                                                         /* Next iteration will get bigger radius but smaller weight! */
1579                                                         w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
1580                                                 }
1581                                                 if (n == -1) {
1582                                                         /* Fallback to 'nearest' hit here, loops usually comes in 'face group', not good to
1583                                                          * have only part of one dest face's loops to map to source.
1584                                                          * Note that since we give this a null weight, if whole weight for a given face
1585                                                          * is null, it means none of its loop mapped to this source island, hence we can skip it
1586                                                          * later.
1587                                                          */
1588                                                         copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
1589                                                         nearest.index = -1;
1590
1591                                                         /* Convert the vertex to tree coordinates, if needed. */
1592                                                         if (space_transform) {
1593                                                                 BLI_space_transform_apply(space_transform, tmp_co);
1594                                                         }
1595
1596                                                         /* In any case, this fallback nearest hit should have no weight at all
1597                                                          * in 'best island' decision! */
1598                                                         islands_res[tindex][plidx_dst].factor = 0.0f;
1599
1600                                                         if (mesh_remap_bvhtree_query_nearest(tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
1601                                                                 islands_res[tindex][plidx_dst].hit_dist = hit_dist;
1602                                                                 islands_res[tindex][plidx_dst].index_src = (int)tdata->looptri[nearest.index].poly;
1603                                                                 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
1604                                                         }
1605                                                         else {
1606                                                                 /* No source for this dest loop! */
1607                                                                 islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
1608                                                                 islands_res[tindex][plidx_dst].index_src = -1;
1609                                                         }
1610                                                 }
1611                                         }
1612                                         else {  /* Nearest poly either to use all its loops/verts or just closest one. */
1613                                                 copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
1614                                                 nearest.index = -1;
1615
1616                                                 /* Convert the vertex to tree coordinates, if needed. */
1617                                                 if (space_transform) {
1618                                                         BLI_space_transform_apply(space_transform, tmp_co);
1619                                                 }
1620
1621                                                 if (mesh_remap_bvhtree_query_nearest(tdata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
1622                                                         islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist) : 1e18f;
1623                                                         islands_res[tindex][plidx_dst].hit_dist = hit_dist;
1624                                                         islands_res[tindex][plidx_dst].index_src = (int)tdata->looptri[nearest.index].poly;
1625                                                         copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
1626                                                 }
1627                                                 else {
1628                                                         /* No source for this dest loop! */
1629                                                         islands_res[tindex][plidx_dst].factor = 0.0f;
1630                                                         islands_res[tindex][plidx_dst].hit_dist = FLT_MAX;
1631                                                         islands_res[tindex][plidx_dst].index_src = -1;
1632                                                 }
1633                                         }
1634                                 }
1635                         }
1636
1637                         /* And now, find best island to use! */
1638                         /* We have to first select the 'best source island' for given dst poly and its loops.
1639                          * Then, we have to check that poly does not 'spread' across some island's limits
1640                          * (like inner seams for UVs, etc.).
1641                          * Note we only still partially support that kind of situation here, i.e. polys spreading over actual cracks
1642                          * (like a narrow space without faces on src, splitting a 'tube-like' geometry). That kind of situation
1643                          * should be relatively rare, though.
1644                          */
1645                         /* XXX This block in itself is big and complex enough to be a separate function but... it uses a bunch
1646                          *     of locale vars. Not worth sending all that through parameters (for now at least). */
1647                         {
1648                                 BLI_AStarGraph *as_graph = NULL;
1649                                 int *poly_island_index_map = NULL;
1650                                 int pidx_src_prev = -1;
1651
1652                                 MeshElemMap *best_island = NULL;
1653                                 float best_island_fac = 0.0f;
1654                                 int best_island_index = -1;
1655
1656                                 for (tindex = 0; tindex < num_trees; tindex++) {
1657                                         float island_fac = 0.0f;
1658
1659                                         for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) {
1660                                                 island_fac += islands_res[tindex][plidx_dst].factor;
1661                                         }
1662                                         island_fac /= (float)mp_dst->totloop;
1663
1664                                         if (island_fac > best_island_fac) {
1665                                                 best_island_fac = island_fac;
1666                                                 best_island_index = tindex;
1667                                         }
1668                                 }
1669
1670                                 if (best_island_index != -1 && isld_steps_src) {
1671                                         best_island = use_islands ? island_store.islands[best_island_index] : NULL;
1672                                         as_graph = &as_graphdata[best_island_index];
1673                                         poly_island_index_map = (int *)as_graph->custom_data;
1674                                         BLI_astar_solution_init(as_graph, &as_solution, NULL);
1675                                 }
1676
1677                                 for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) {
1678                                         IslandResult *isld_res;
1679                                         lidx_dst = plidx_dst + mp_dst->loopstart;
1680
1681                                         if (best_island_index == -1) {
1682                                                 /* No source for any loops of our dest poly in any source islands. */
1683                                                 BKE_mesh_remap_item_define_invalid(r_map, lidx_dst);
1684                                                 continue;
1685                                         }
1686
1687                                         as_solution.custom_data = SET_INT_IN_POINTER(false);
1688
1689                                         isld_res = &islands_res[best_island_index][plidx_dst];
1690                                         if (use_from_vert) {
1691                                                 /* Indices stored in islands_res are those of loops, one per dest loop. */
1692                                                 lidx_src = isld_res->index_src;
1693                                                 if (lidx_src >= 0) {
1694                                                         pidx_src = loop_to_poly_map_src[lidx_src];
1695                                                         /* If prev and curr poly are the same, no need to do anything more!!! */
1696                                                         if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1697                                                                 int pidx_isld_src, pidx_isld_src_prev;
1698                                                                 if (poly_island_index_map) {
1699                                                                         pidx_isld_src = poly_island_index_map[pidx_src];
1700                                                                         pidx_isld_src_prev = poly_island_index_map[pidx_src_prev];
1701                                                                 }
1702                                                                 else {
1703                                                                         pidx_isld_src = pidx_src;
1704                                                                         pidx_isld_src_prev = pidx_src_prev;
1705                                                                 }
1706
1707                                                                 BLI_astar_graph_solve(
1708                                                                         as_graph, pidx_isld_src_prev, pidx_isld_src,
1709                                                                         mesh_remap_calc_loops_astar_f_cost, &as_solution, isld_steps_src);
1710                                                                 if (GET_INT_FROM_POINTER(as_solution.custom_data) && (as_solution.steps > 0)) {
1711                                                                         /* Find first 'cutting edge' on path, and bring back lidx_src on poly just
1712                                                                          * before that edge.
1713                                                                          * Note we could try to be much smarter (like e.g. storing a whole poly's indices,
1714                                                                          * and making decision (on which side of cutting edge(s!) to be) on the end,
1715                                                                          * but this is one more level of complexity, better to first see if
1716                                                                          * simple solution works!
1717                                                                          */
1718                                                                         int last_valid_pidx_isld_src = -1;
1719                                                                         /* Note we go backward here, from dest to src poly. */
1720                                                                         for (i = as_solution.steps - 1; i--;) {
1721                                                                                 BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
1722                                                                                 const int eidx = GET_INT_FROM_POINTER(as_link->custom_data);
1723                                                                                 pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
1724                                                                                 BLI_assert(pidx_isld_src != -1);
1725                                                                                 if (eidx != -1) {
1726                                                                                         /* we are 'crossing' a cutting edge. */
1727                                                                                         last_valid_pidx_isld_src = pidx_isld_src;
1728                                                                                 }
1729                                                                         }
1730                                                                         if (last_valid_pidx_isld_src != -1) {
1731                                                                                 /* Find a new valid loop in that new poly (nearest one for now).
1732                                                                                  * Note we could be much more subtle here, again that's for later... */
1733                                                                                 int j;
1734                                                                                 float best_dist_sq = FLT_MAX;
1735
1736                                                                                 ml_dst = &loops_dst[lidx_dst];
1737                                                                                 copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
1738
1739                                                                                 /* We do our transform here, since we may do several raycast/nearest queries. */
1740                                                                                 if (space_transform) {
1741                                                                                         BLI_space_transform_apply(space_transform, tmp_co);
1742                                                                                 }
1743
1744                                                                                 pidx_src = use_islands ? best_island->indices[last_valid_pidx_isld_src] :
1745                                                                                                          last_valid_pidx_isld_src;
1746                                                                                 mp_src = &polys_src[pidx_src];
1747                                                                                 ml_src = &loops_src[mp_src->loopstart];
1748                                                                                 for (j = 0; j < mp_src->totloop; j++, ml_src++) {
1749                                                                                         const float dist_sq = len_squared_v3v3(verts_src[ml_src->v].co, tmp_co);
1750                                                                                         if (dist_sq < best_dist_sq) {
1751                                                                                                 best_dist_sq = dist_sq;
1752                                                                                                 lidx_src = mp_src->loopstart + j;
1753                                                                                         }
1754                                                                                 }
1755                                                                         }
1756                                                                 }
1757                                                         }
1758                                                         mesh_remap_item_define(
1759                                                                 r_map, lidx_dst, isld_res->hit_dist,
1760                                                                 best_island_index, 1, &lidx_src, &full_weight);
1761                                                         pidx_src_prev = pidx_src;
1762                                                 }
1763                                                 else {
1764                                                         /* No source for this loop in this island. */
1765                                                         /* TODO: would probably be better to get a source at all cost in best island anyway? */
1766                                                         mesh_remap_item_define(
1767                                                                 r_map, lidx_dst, FLT_MAX,
1768                                                                 best_island_index, 0, NULL, NULL);
1769                                                 }
1770                                         }
1771                                         else {
1772                                                 /* Else, we use source poly, indices stored in islands_res are those of polygons. */
1773                                                 pidx_src = isld_res->index_src;
1774                                                 if (pidx_src >= 0) {
1775                                                         float *hit_co = isld_res->hit_point;
1776                                                         int best_loop_index_src;
1777
1778                                                         mp_src = &polys_src[pidx_src];
1779                                                         /* If prev and curr poly are the same, no need to do anything more!!! */
1780                                                         if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1781                                                                 int pidx_isld_src, pidx_isld_src_prev;
1782                                                                 if (poly_island_index_map) {
1783                                                                         pidx_isld_src = poly_island_index_map[pidx_src];
1784                                                                         pidx_isld_src_prev = poly_island_index_map[pidx_src_prev];
1785                                                                 }
1786                                                                 else {
1787                                                                         pidx_isld_src = pidx_src;
1788                                                                         pidx_isld_src_prev = pidx_src_prev;
1789                                                                 }
1790
1791                                                                 BLI_astar_graph_solve(
1792                                                                         as_graph, pidx_isld_src_prev, pidx_isld_src,
1793                                                                         mesh_remap_calc_loops_astar_f_cost, &as_solution, isld_steps_src);
1794                                                                 if (GET_INT_FROM_POINTER(as_solution.custom_data) && (as_solution.steps > 0)) {
1795                                                                         /* Find first 'cutting edge' on path, and bring back lidx_src on poly just
1796                                                                          * before that edge.
1797                                                                          * Note we could try to be much smarter (like e.g. storing a whole poly's indices,
1798                                                                          * and making decision (one which side of cutting edge(s!) to be on the end,
1799                                                                          * but this is one more level of complexity, better to first see if
1800                                                                          * simple solution works!
1801                                                                          */
1802                                                                         int last_valid_pidx_isld_src = -1;
1803                                                                         /* Note we go backward here, from dest to src poly. */
1804                                                                         for (i = as_solution.steps - 1; i--;) {
1805                                                                                 BLI_AStarGNLink *as_link = as_solution.prev_links[pidx_isld_src];
1806                                                                                 int eidx = GET_INT_FROM_POINTER(as_link->custom_data);
1807
1808                                                                                 pidx_isld_src = as_solution.prev_nodes[pidx_isld_src];
1809                                                                                 BLI_assert(pidx_isld_src != -1);
1810                                                                                 if (eidx != -1) {
1811                                                                                         /* we are 'crossing' a cutting edge. */
1812                                                                                         last_valid_pidx_isld_src = pidx_isld_src;
1813                                                                                 }
1814                                                                         }
1815                                                                         if (last_valid_pidx_isld_src != -1) {
1816                                                                                 /* Find a new valid loop in that new poly (nearest point on poly for now).
1817                                                                                  * Note we could be much more subtle here, again that's for later... */
1818                                                                                 float best_dist_sq = FLT_MAX;
1819                                                                                 int j;
1820
1821                                                                                 ml_dst = &loops_dst[lidx_dst];
1822                                                                                 copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
1823
1824                                                                                 /* We do our transform here, since we may do several raycast/nearest queries. */
1825                                                                                 if (space_transform) {
1826                                                                                         BLI_space_transform_apply(space_transform, tmp_co);
1827                                                                                 }
1828
1829                                                                                 pidx_src = use_islands ? best_island->indices[last_valid_pidx_isld_src] :
1830                                                                                                          last_valid_pidx_isld_src;
1831                                                                                 mp_src = &polys_src[pidx_src];
1832
1833                                                                                 /* Create that one on demand. */
1834                                                                                 if (poly_to_looptri_map_src == NULL) {
1835                                                                                         BKE_mesh_origindex_map_create_looptri(
1836                                                                                                 &poly_to_looptri_map_src, &poly_to_looptri_map_src_buff,
1837                                                                                                 polys_src, num_polys_src,
1838                                                                                                 looptri_src, num_looptri_src);
1839                                                                                 }
1840
1841                                                                                 for (j = poly_to_looptri_map_src[pidx_src].count; j--;) {
1842                                                                                         float h[3];
1843                                                                                         const MLoopTri *lt = &looptri_src[poly_to_looptri_map_src[pidx_src].indices[j]];
1844                                                                                         float dist_sq;
1845
1846                                                                                         closest_on_tri_to_point_v3(
1847                                                                                                 h, tmp_co,
1848                                                                                                 vcos_src[loops_src[lt->tri[0]].v],
1849                                                                                                 vcos_src[loops_src[lt->tri[1]].v],
1850                                                                                                 vcos_src[loops_src[lt->tri[2]].v]);
1851                                                                                         dist_sq = len_squared_v3v3(tmp_co, h);
1852                                                                                         if (dist_sq < best_dist_sq) {
1853                                                                                                 copy_v3_v3(hit_co, h);
1854                                                                                                 best_dist_sq = dist_sq;
1855                                                                                         }
1856                                                                                 }
1857                                                                         }
1858                                                                 }
1859                                                         }
1860
1861                                                         if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) {
1862                                                                 mesh_remap_interp_poly_data_get(
1863                                                                         mp_src, loops_src, (const float (*)[3])vcos_src, hit_co,
1864                                                                         &buff_size_interp, &vcos_interp, true, &indices_interp,
1865                                                                         &weights_interp, false, &best_loop_index_src);
1866
1867                                                                 mesh_remap_item_define(
1868                                                                         r_map, lidx_dst, isld_res->hit_dist,
1869                                                                         best_island_index, 1, &best_loop_index_src, &full_weight);
1870                                                         }
1871                                                         else {
1872                                                                 const int sources_num = mesh_remap_interp_poly_data_get(
1873                                                                         mp_src, loops_src, (const float (*)[3])vcos_src, hit_co,
1874                                                                         &buff_size_interp, &vcos_interp, true, &indices_interp,
1875                                                                         &weights_interp, true, NULL);
1876
1877                                                                 mesh_remap_item_define(
1878                                                                         r_map, lidx_dst,
1879                                                                         isld_res->hit_dist, best_island_index,
1880                                                                         sources_num, indices_interp, weights_interp);
1881                                                         }
1882
1883                                                         pidx_src_prev = pidx_src;
1884                                                 }
1885                                                 else {
1886                                                         /* No source for this loop in this island. */
1887                                                         /* TODO: would probably be better to get a source at all cost in best island anyway? */
1888                                                         mesh_remap_item_define(r_map, lidx_dst, FLT_MAX, best_island_index, 0, NULL, NULL);
1889                                                 }
1890                                         }
1891                                 }
1892
1893                                 BLI_astar_solution_clear(&as_solution);
1894                         }
1895                 }
1896
1897                 for (tindex = 0; tindex < num_trees; tindex++) {
1898                         MEM_freeN(islands_res[tindex]);
1899                         free_bvhtree_from_mesh(&treedata[tindex]);
1900                         if (isld_steps_src) {
1901                                 BLI_astar_graph_free(&as_graphdata[tindex]);
1902                         }
1903                 }
1904                 MEM_freeN(islands_res);
1905                 BKE_mesh_loop_islands_free(&island_store);
1906                 MEM_freeN(treedata);
1907                 if (isld_steps_src) {
1908                         MEM_freeN(as_graphdata);
1909                         BLI_astar_solution_free(&as_solution);
1910                 }
1911
1912                 if (verts_allocated_src) {
1913                         MEM_freeN(verts_src);
1914                 }
1915                 if (vcos_src) {
1916                         MEM_freeN(vcos_src);
1917                 }
1918                 if (edges_allocated_src) {
1919                         MEM_freeN(edges_src);
1920                 }
1921                 if (loops_allocated_src) {
1922                         MEM_freeN(loops_src);
1923                 }
1924                 if (polys_allocated_src) {
1925                         MEM_freeN(polys_src);
1926                 }
1927                 if (vert_to_loop_map_src) {
1928                         MEM_freeN(vert_to_loop_map_src);
1929                 }
1930                 if (vert_to_loop_map_src_buff) {
1931                         MEM_freeN(vert_to_loop_map_src_buff);
1932                 }
1933                 if (vert_to_poly_map_src) {
1934                         MEM_freeN(vert_to_poly_map_src);
1935                 }
1936                 if (vert_to_poly_map_src_buff) {
1937                         MEM_freeN(vert_to_poly_map_src_buff);
1938                 }
1939                 if (edge_to_poly_map_src) {
1940                         MEM_freeN(edge_to_poly_map_src);
1941                 }
1942                 if (edge_to_poly_map_src_buff) {
1943                         MEM_freeN(edge_to_poly_map_src_buff);
1944                 }
1945                 if (poly_to_looptri_map_src) {
1946                         MEM_freeN(poly_to_looptri_map_src);
1947                 }
1948                 if (poly_to_looptri_map_src_buff) {
1949                         MEM_freeN(poly_to_looptri_map_src_buff);
1950                 }
1951                 if (loop_to_poly_map_src) {
1952                         MEM_freeN(loop_to_poly_map_src);
1953                 }
1954                 if (poly_cents_src) {
1955                         MEM_freeN(poly_cents_src);
1956                 }
1957                 if (vcos_interp) {
1958                         MEM_freeN(vcos_interp);
1959                 }
1960                 if (indices_interp) {
1961                         MEM_freeN(indices_interp);
1962                 }
1963                 if (weights_interp) {
1964                         MEM_freeN(weights_interp);
1965                 }
1966         }
1967 }
1968
1969 void BKE_mesh_remap_calc_polys_from_dm(
1970         const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius,
1971         MVert *verts_dst, const int numverts_dst, MLoop *loops_dst, const int numloops_dst,
1972         MPoly *polys_dst, const int numpolys_dst, CustomData *pdata_dst, const bool dirty_nors_dst,
1973         DerivedMesh *dm_src, MeshPairRemap *r_map)
1974 {
1975         const float full_weight = 1.0f;
1976         const float max_dist_sq = max_dist * max_dist;
1977         float (*poly_nors_dst)[3] = NULL;
1978         float tmp_co[3], tmp_no[3];
1979         int i;
1980
1981         BLI_assert(mode & MREMAP_MODE_POLY);
1982
1983         if (mode & (MREMAP_USE_NORMAL | MREMAP_USE_NORPROJ)) {
1984                 /* Cache poly nors into a temp CDLayer. */
1985                 poly_nors_dst = CustomData_get_layer(pdata_dst, CD_NORMAL);
1986                 if (!poly_nors_dst) {
1987                         poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, numpolys_dst);
1988                         CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
1989                 }
1990                 if (dirty_nors_dst) {
1991                         BKE_mesh_calc_normals_poly(verts_dst, NULL, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst,
1992                                                    poly_nors_dst, true);
1993                 }
1994         }
1995
1996         BKE_mesh_remap_init(r_map, numpolys_dst);
1997
1998         if (mode == MREMAP_MODE_TOPOLOGY) {
1999                 BLI_assert(numpolys_dst == dm_src->getNumPolys(dm_src));
2000                 for (i = 0; i < numpolys_dst; i++) {
2001                         mesh_remap_item_define(r_map, i, FLT_MAX, 0, 1, &i, &full_weight);
2002                 }
2003         }
2004         else {
2005                 BVHTreeFromMesh treedata = {NULL};
2006                 BVHTreeNearest nearest = {0};
2007                 BVHTreeRayHit rayhit = {0};
2008                 float hit_dist;
2009
2010                 bvhtree_from_mesh_looptri(
2011                         &treedata, dm_src,
2012                         (mode & MREMAP_USE_NORPROJ) ? MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON(ray_radius) : 0.0f,
2013                         2, 6);
2014
2015                 if (mode == MREMAP_MODE_POLY_NEAREST) {
2016                         nearest.index = -1;
2017
2018                         for (i = 0; i < numpolys_dst; i++) {
2019                                 MPoly *mp = &polys_dst[i];
2020
2021                                 BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
2022
2023                                 /* Convert the vertex to tree coordinates, if needed. */
2024                                 if (space_transform) {
2025                                         BLI_space_transform_apply(space_transform, tmp_co);
2026                                 }
2027
2028                                 if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) {
2029                                         const MLoopTri *lt = &treedata.looptri[nearest.index];
2030                                         const int poly_index = (int)lt->poly;
2031                                         mesh_remap_item_define(
2032                                                 r_map, i, hit_dist, 0,
2033                                                 1, &poly_index, &full_weight);
2034                                 }
2035                                 else {
2036                                         /* No source for this dest poly! */
2037                                         BKE_mesh_remap_item_define_invalid(r_map, i);
2038                                 }
2039                         }
2040                 }
2041                 else if (mode == MREMAP_MODE_POLY_NOR) {
2042                         BLI_assert(poly_nors_dst);
2043
2044                         for (i = 0; i < numpolys_dst; i++) {
2045                                 MPoly *mp = &polys_dst[i];
2046
2047                                 BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
2048                                 copy_v3_v3(tmp_no, poly_nors_dst[i]);
2049
2050                                 /* Convert the vertex to tree coordinates, if needed. */
2051                                 if (space_transform) {
2052                                         BLI_space_transform_apply(space_transform, tmp_co);
2053                                         BLI_space_transform_apply_normal(space_transform, tmp_no);
2054                                 }
2055
2056                                 if (mesh_remap_bvhtree_query_raycast(
2057                                         &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
2058                                 {
2059                                         const MLoopTri *lt = &treedata.looptri[rayhit.index];
2060                                         const int poly_index = (int)lt->poly;
2061
2062                                         mesh_remap_item_define(
2063                                                 r_map, i, hit_dist, 0,
2064                                                 1, &poly_index, &full_weight);
2065                                 }
2066                                 else {
2067                                         /* No source for this dest poly! */
2068                                         BKE_mesh_remap_item_define_invalid(r_map, i);
2069                                 }
2070                         }
2071                 }
2072                 else if (mode == MREMAP_MODE_POLY_POLYINTERP_PNORPROJ) {
2073                         /* We cast our rays randomly, with a pseudo-even distribution (since we spread across tessellated tris,
2074                          * with additional weighting based on each tri's relative area).
2075                          */
2076                         RNG *rng = BLI_rng_new(0);
2077
2078                         const size_t numpolys_src = (size_t)dm_src->getNumPolys(dm_src);
2079
2080                         /* Here it's simpler to just allocate for all polys :/ */
2081                         int *indices = MEM_mallocN(sizeof(*indices) * numpolys_src, __func__);
2082                         float *weights = MEM_mallocN(sizeof(*weights) * numpolys_src, __func__);
2083
2084                         size_t tmp_poly_size = MREMAP_DEFAULT_BUFSIZE;
2085                         float (*poly_vcos_2d)[2] = MEM_mallocN(sizeof(*poly_vcos_2d) * tmp_poly_size, __func__);
2086                         /* Tessellated 2D poly, always (num_loops - 2) triangles. */
2087                         int (*tri_vidx_2d)[3] = MEM_mallocN(sizeof(*tri_vidx_2d) * (tmp_poly_size - 2), __func__);
2088
2089                         for (i = 0; i < numpolys_dst; i++) {
2090                                 /* For each dst poly, we sample some rays from it (2D grid in pnor space)
2091                                  * and use their hits to interpolate from source polys. */
2092                                 /* Note: dst poly is early-converted into src space! */
2093                                 MPoly *mp = &polys_dst[i];
2094
2095                                 int tot_rays, done_rays = 0;
2096                                 float poly_area_2d_inv, done_area = 0.0f;
2097
2098                                 float pcent_dst[3];
2099                                 float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
2100                                 float poly_dst_2d_min[2], poly_dst_2d_max[2], poly_dst_2d_z;
2101                                 float poly_dst_2d_size[2];
2102
2103                                 float totweights = 0.0f;
2104                                 float hit_dist_accum = 0.0f;
2105                                 int sources_num = 0;
2106                                 const int tris_num = mp->totloop - 2;
2107                                 int j;
2108
2109                                 BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, pcent_dst);
2110                                 copy_v3_v3(tmp_no, poly_nors_dst[i]);
2111
2112                                 /* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */
2113                                 if (space_transform) {
2114                                         BLI_space_transform_apply(space_transform, pcent_dst);
2115                                         BLI_space_transform_apply_normal(space_transform, tmp_no);
2116                                 }
2117
2118                                 copy_vn_fl(weights, (int)numpolys_src, 0.0f);
2119
2120                                 if (UNLIKELY((size_t)mp->totloop > tmp_poly_size)) {
2121                                         tmp_poly_size = (size_t)mp->totloop;
2122                                         poly_vcos_2d = MEM_reallocN(poly_vcos_2d, sizeof(*poly_vcos_2d) * tmp_poly_size);
2123                                         tri_vidx_2d = MEM_reallocN(tri_vidx_2d, sizeof(*tri_vidx_2d) * (tmp_poly_size - 2));
2124                                 }
2125
2126                                 axis_dominant_v3_to_m3(to_pnor_2d_mat, tmp_no);
2127                                 invert_m3_m3(from_pnor_2d_mat, to_pnor_2d_mat);
2128
2129                                 mul_m3_v3(to_pnor_2d_mat, pcent_dst);
2130                                 poly_dst_2d_z = pcent_dst[2];
2131
2132                                 /* Get (2D) bounding square of our poly. */
2133                                 INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max);
2134
2135                                 for (j = 0; j < mp->totloop; j++) {
2136                                         MLoop *ml = &loops_dst[j + mp->loopstart];
2137                                         copy_v3_v3(tmp_co, verts_dst[ml->v].co);
2138                                         if (space_transform) {
2139                                                 BLI_space_transform_apply(space_transform, tmp_co);
2140                                         }
2141                                         mul_v2_m3v3(poly_vcos_2d[j], to_pnor_2d_mat, tmp_co);
2142                                         minmax_v2v2_v2(poly_dst_2d_min, poly_dst_2d_max, poly_vcos_2d[j]);
2143                                 }
2144
2145                                 /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast),
2146                                  * with lower/upper bounds. */
2147                                 sub_v2_v2v2(poly_dst_2d_size, poly_dst_2d_max, poly_dst_2d_min);
2148
2149                                 if (ray_radius) {
2150                                         tot_rays = (int)((max_ff(poly_dst_2d_size[0], poly_dst_2d_size[1]) / ray_radius) + 0.5f);
2151                                         CLAMP(tot_rays, MREMAP_RAYCAST_TRI_SAMPLES_MIN, MREMAP_RAYCAST_TRI_SAMPLES_MAX);
2152                                 }
2153                                 else {
2154                                         /* If no radius (pure rays), give max number of rays! */
2155                                         tot_rays = MREMAP_RAYCAST_TRI_SAMPLES_MIN;
2156                                 }
2157                                 tot_rays *= tot_rays;
2158
2159                                 poly_area_2d_inv = area_poly_v2((const float(*)[2])poly_vcos_2d, (unsigned int)mp->totloop);
2160                                 /* In case we have a null-area degenerated poly... */
2161                                 poly_area_2d_inv = 1.0f / max_ff(poly_area_2d_inv, 1e-9f);
2162
2163                                 /* Tessellate our poly. */
2164                                 if (mp->totloop == 3) {
2165                                         tri_vidx_2d[0][0] = 0;
2166                                         tri_vidx_2d[0][1] = 1;
2167                                         tri_vidx_2d[0][2] = 2;
2168                                 }
2169                                 if (mp->totloop == 4) {
2170                                         tri_vidx_2d[0][0] = 0;
2171                                         tri_vidx_2d[0][1] = 1;
2172                                         tri_vidx_2d[0][2] = 2;
2173                                         tri_vidx_2d[1][0] = 0;
2174                                         tri_vidx_2d[1][1] = 2;
2175                                         tri_vidx_2d[1][2] = 3;
2176                                 }
2177                                 else {
2178                                         BLI_polyfill_calc(poly_vcos_2d, (unsigned int)mp->totloop, -1,
2179                                                           (unsigned int (*)[3])tri_vidx_2d);
2180                                 }
2181
2182                                 for (j = 0; j < tris_num; j++) {
2183                                         float *v1 = poly_vcos_2d[tri_vidx_2d[j][0]];
2184                                         float *v2 = poly_vcos_2d[tri_vidx_2d[j][1]];
2185                                         float *v3 = poly_vcos_2d[tri_vidx_2d[j][2]];
2186                                         int rays_num;
2187
2188                                         /* All this allows us to get 'absolute' number of rays for each tri, avoiding accumulating
2189                                          * errors over iterations, and helping better even distribution. */
2190                                         done_area += area_tri_v2(v1, v2, v3);
2191                                         rays_num = max_ii((int)((float)tot_rays * done_area * poly_area_2d_inv + 0.5f) - done_rays, 0);
2192                                         done_rays += rays_num;
2193
2194                                         while (rays_num--) {
2195                                                 int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
2196                                                 float w = 1.0f;
2197
2198                                                 BLI_rng_get_tri_sample_float_v2(rng, v1, v2, v3, tmp_co);
2199
2200                                                 tmp_co[2] = poly_dst_2d_z;
2201                                                 mul_m3_v3(from_pnor_2d_mat, tmp_co);
2202
2203                                                 /* At this point, tmp_co is a point on our poly surface, in mesh_src space! */
2204                                                 while (n--) {
2205                                                         if (mesh_remap_bvhtree_query_raycast(
2206                                                                 &treedata, &rayhit, tmp_co, tmp_no, ray_radius / w, max_dist, &hit_dist))
2207                                                         {
2208                                                                 const MLoopTri *lt = &treedata.looptri[rayhit.index];
2209
2210                                                                 weights[lt->poly] += w;
2211                                                                 totweights += w;
2212                                                                 hit_dist_accum += hit_dist;
2213                                                                 break;
2214                                                         }
2215                                                         /* Next iteration will get bigger radius but smaller weight! */
2216                                                         w /= MREMAP_RAYCAST_APPROXIMATE_FAC;
2217                                                 }
2218                                         }
2219                                 }
2220
2221                                 if (totweights > 0.0f) {
2222                                         for (j = 0; j < (int)numpolys_src; j++) {
2223                                                 if (!weights[j]) {
2224                                                         continue;
2225                                                 }
2226                                                 /* Note: sources_num is always <= j! */
2227                                                 weights[sources_num] = weights[j] / totweights;
2228                                                 indices[sources_num] = j;
2229                                                 sources_num++;
2230                                         }
2231                                         mesh_remap_item_define(r_map, i, hit_dist_accum / totweights, 0, sources_num, indices, weights);
2232                                 }
2233                                 else {
2234                                         /* No source for this dest poly! */
2235                                         BKE_mesh_remap_item_define_invalid(r_map, i);
2236                                 }
2237                         }
2238
2239                         MEM_freeN(tri_vidx_2d);
2240                         MEM_freeN(poly_vcos_2d);
2241                         MEM_freeN(indices);
2242                         MEM_freeN(weights);
2243                         BLI_rng_free(rng);
2244                 }
2245                 else {
2246                         printf("WARNING! Unsupported mesh-to-mesh poly mapping mode (%d)!\n", mode);
2247                         memset(r_map->items, 0, sizeof(*r_map->items) * (size_t)numpolys_dst);
2248                 }
2249
2250                 free_bvhtree_from_mesh(&treedata);
2251         }
2252 }
2253
2254 #undef MREMAP_RAYCAST_APPROXIMATE_NR
2255 #undef MREMAP_RAYCAST_APPROXIMATE_FAC
2256 #undef MREMAP_RAYCAST_APPROXIMATE_BVHEPSILON
2257 #undef MREMAP_RAYCAST_TRI_SAMPLES_MIN
2258 #undef MREMAP_RAYCAST_TRI_SAMPLES_MAX
2259 #undef MREMAP_DEFAULT_BUFSIZE
2260
2261 /** \} */