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