52 const float max_dist_sq,
56 if (nearest->
index != -1) {
58 if (nearest->
dist_sq > max_dist_sq) {
70 if ((nearest->
index != -1) && (nearest->
dist_sq <= max_dist_sq)) {
90 rayhit->
dist = max_dist;
99 if (rayhit_tmp.
dist < rayhit->
dist) {
100 *rayhit = rayhit_tmp;
103 if ((rayhit->
index != -1) && (rayhit->
dist <= max_dist)) {
104 *r_hit_dist = rayhit->
dist;
132 for (
i = 0;
i < vert_positions_dst.
size();
i++) {
138 if (space_transform) {
143 result += 1.0f / (hit_dist + 1.0f);
154 printf(
"%s: Computed difference between meshes (the lower the better): %f\n", __func__,
result);
174 float center[3], covmat[3][3];
175 float eigen_val[3], eigen_vec[3][3];
185 int(positions.
size()),
218 for (
i = 0;
i < 3;
i++) {
219 float evi = eigen_val[
i];
226 evi = (evi < 1e-6f && evi > -1e-6f) ? ((evi < 0.0f) ? -1e-3f : 1e-3f) :
sqrtf_signed(evi);
240 const float mirrors[][3] = {
250 const float (*mirr)[3];
252 float mat_src[4][4], mat_dst[4][4], best_mat_dst[4][4];
253 float best_match =
FLT_MAX, match;
255 const Span<float3> positions_src = me_src->vert_positions();
265 for (mirr = mirrors; (*mirr)[0]; mirr++) {
272 r_space_transform, vert_positions_dst, me_src);
273 if (match < best_match) {
308 map->
items =
nullptr;
316 const int sources_num,
317 const int *indices_src,
318 const float *weights_src)
349 const float point[3],
352 const bool use_loops,
355 const bool do_weights,
356 int *r_closest_index)
361 const int sources_num = int(face.
size());
364 if (
size_t(sources_num) > *buff_size) {
365 *buff_size = size_t(sources_num);
366 *vcos =
static_cast<float (*)[3]
>(
MEM_reallocN(*vcos,
sizeof(**vcos) * *buff_size));
369 *weights =
static_cast<float *
>(
MEM_reallocN(*weights,
sizeof(**weights) * *buff_size));
373 for (
i = 0, vco = *vcos, index = *
indices;
i < sources_num;
i++, vco++, index++) {
374 const int vert = corner_verts[face[
i]];
375 *index = use_loops ? int(face[
i]) : vert;
377 if (r_closest_index) {
380 if (dist_sq < ref_dist_sq) {
381 ref_dist_sq = dist_sq;
382 *r_closest_index = *index;
423#define MREMAP_RAYCAST_APPROXIMATE_NR 3
425#define MREMAP_RAYCAST_APPROXIMATE_FAC 5.0f
428#define MREMAP_RAYCAST_TRI_SAMPLES_MIN 4
429#define MREMAP_RAYCAST_TRI_SAMPLES_MAX 20
432#define MREMAP_DEFAULT_BUFSIZE 32
436 const float max_dist,
437 const float ray_radius,
443 const float full_weight = 1.0f;
444 const float max_dist_sq = max_dist * max_dist;
453 for (
i = 0;
i < vert_positions_dst.
size();
i++) {
462 float tmp_co[3], tmp_no[3];
465 treedata = me_src->bvh_verts();
468 for (
i = 0;
i < vert_positions_dst.
size();
i++) {
472 if (space_transform) {
490 treedata = me_src->bvh_edges();
493 for (
i = 0;
i < vert_positions_dst.
size();
i++) {
497 if (space_transform) {
504 const float *v1cos = positions_src[edge[0]];
505 const float *v2cos = positions_src[edge[1]];
510 const int index = (dist_v1 > dist_v2) ? edge[1] : edge[0];
522 CLAMP(weights[0], 0.0f, 1.0f);
523 weights[1] = 1.0f - weights[0];
550 treedata = me_src->bvh_corner_tris();
553 for (
i = 0;
i < vert_positions_dst.
size();
i++) {
558 if (space_transform) {
564 &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
566 const int face_index = tri_faces[rayhit.
index];
590 for (
i = 0;
i < vert_positions_dst.
size();
i++) {
594 if (space_transform) {
599 &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
601 const int face_index = tri_faces[nearest.
index];
647 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh vertex mapping mode (%d)!", mode);
648 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(vert_positions_dst.
size()));
655 const float max_dist,
656 const float ray_radius,
664 const float full_weight = 1.0f;
665 const float max_dist_sq = max_dist * max_dist;
674 for (
i = 0;
i < edges_dst.
size();
i++) {
683 float tmp_co[3], tmp_no[3];
686 const int num_verts_src = me_src->
verts_num;
697 for (
i = 0;
i < vert_positions_dst.
size();
i++) {
698 v_dst_to_src_map[
i].hit_dist = -1.0f;
704 edges_src, num_verts_src, vert_to_edge_src_offsets, vert_to_edge_src_indices);
706 treedata = me_src->bvh_verts();
709 for (
i = 0;
i < edges_dst.
size();
i++) {
712 int best_eidx_src = -1;
716 const int vidx_dst = j ? e_dst[0] : e_dst[1];
719 if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
720 copy_v3_v3(tmp_co, vert_positions_dst[vidx_dst]);
723 if (space_transform) {
728 &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
730 v_dst_to_src_map[vidx_dst].hit_dist = hit_dist;
731 v_dst_to_src_map[vidx_dst].index = nearest.
index;
735 v_dst_to_src_map[vidx_dst].hit_dist =
FLT_MAX;
743 const int vidx_dst = j ? e_dst[0] : e_dst[1];
744 const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist;
745 const int vidx_src = v_dst_to_src_map[vidx_dst].index;
753 eidx_src = vert_to_edge_src_map[vidx_src].
data();
754 k = int(vert_to_edge_src_map[vidx_src].
size());
756 for (; k--; eidx_src++) {
758 const float *other_co_src =
760 const float *other_co_dst =
762 const float totdist = first_dist +
len_v3v3(other_co_src, other_co_dst);
764 if (totdist < best_totdist) {
765 best_totdist = totdist;
766 best_eidx_src = *eidx_src;
771 if (best_eidx_src >= 0) {
772 const float *co1_src = positions_src[edges_src[best_eidx_src][0]];
773 const float *co2_src = positions_src[edges_src[best_eidx_src][1]];
774 const float *co1_dst = vert_positions_dst[e_dst[0]];
775 const float *co2_dst = vert_positions_dst[e_dst[1]];
776 float co_src[3], co_dst[3];
780 co1_src, co2_src, co1_dst, co2_dst, co_src, co_dst);
781 if (isect_type != 0) {
784 if (fac_src < 0.0f) {
787 else if (fac_src > 1.0f) {
790 if (fac_dst < 0.0f) {
793 else if (fac_dst > 1.0f) {
797 hit_dist =
len_v3v3(co_dst, co_src);
809 treedata = me_src->bvh_edges();
812 for (
i = 0;
i < edges_dst.
size();
i++) {
814 vert_positions_dst[edges_dst[
i][0]],
815 vert_positions_dst[edges_dst[
i][1]],
819 if (space_transform) {
840 treedata = me_src->bvh_corner_tris();
842 for (
i = 0;
i < edges_dst.
size();
i++) {
844 vert_positions_dst[edges_dst[
i][0]],
845 vert_positions_dst[edges_dst[
i][1]],
849 if (space_transform) {
855 const int face_index = tri_faces[nearest.
index];
857 const int *corner_edge_src = &corner_edges_src[face_src.
start()];
858 int nloops = int(face_src.
size());
860 int best_eidx_src = -1;
862 for (; nloops--; corner_edge_src++) {
864 const float *co1_src = positions_src[edge_src[0]];
865 const float *co2_src = positions_src[edge_src[1]];
871 if (dist_sq < best_dist_sq) {
872 best_dist_sq = dist_sq;
873 best_eidx_src = *corner_edge_src;
876 if (best_eidx_src >= 0) {
887 const int num_rays_min = 5, num_rays_max = 100;
888 const int numedges_src = me_src->
edges_num;
895 treedata = me_src->bvh_edges();
899 for (
i = 0;
i < edges_dst.
size();
i++) {
903 float v1_co[3], v2_co[3];
904 float v1_no[3], v2_no[3];
910 float totweights = 0.0f;
911 float hit_dist_accum = 0.0f;
915 copy_v3_v3(v1_co, vert_positions_dst[edge[0]]);
916 copy_v3_v3(v2_co, vert_positions_dst[edge[1]]);
922 if (space_transform) {
933 edge_dst_len =
len_v3v3(v1_co, v2_co);
935 grid_size = int((edge_dst_len / ray_radius) + 0.5f);
936 CLAMP(grid_size, num_rays_min, num_rays_max);
939 grid_step = 1.0f /
float(grid_size);
942 for (j = 0; j < grid_size; j++) {
943 const float fac = grid_step *
float(j);
953 &treedata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
955 weights[rayhit.
index] +=
w;
957 hit_dist_accum += hit_dist;
966 if (totweights > (
float(grid_size) / 2.0f)) {
967 for (j = 0; j < int(numedges_src); j++) {
972 weights[sources_num] = weights[j] / totweights;
977 r_map,
i, hit_dist_accum / totweights, 0, sources_num,
indices, weights);
989 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh edge mapping mode (%d)!", mode);
990 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(edges_dst.
size()));
996#define POLY_CENTER_INIT 1
997#define POLY_COMPLETE 2
1001 const int island_index,
1009 const bool is_edge_innercut,
1010 const int *face_island_index_map,
1011 float (*face_centers)[3],
1017 for (
i = 0;
i < edge_to_face_map[edge_idx].
size();
i++) {
1018 const int pidx = edge_to_face_map[edge_idx][
i];
1020 const int pidx_isld = islands ? face_island_index_map[pidx] : pidx;
1025 face_island_indices[
i] = -1;
1030 face_island_indices[
i] = pidx_isld;
1043 const int pidx_isld_other = face_island_indices[j];
1045 if (pidx_isld_other == -1 || face_status[pidx_isld_other] ==
POLY_COMPLETE) {
1049 dist_cost =
len_v3v3(face_centers[pidx_isld_other], face_centers[pidx_isld]);
1053 face_island_indices[
i] = pidx_isld;
1060 const int island_index,
1072 int *face_island_index_map =
nullptr;
1075 const int node_num = islands ? island_face_map->
count : int(
faces.size());
1077 float (*face_centers)[3];
1084 face_centers =
static_cast<float (*)[3]
>(
1090 r_as_graph->
mem,
sizeof(*face_island_index_map) *
size_t(
faces.size())));
1091 for (
i = island_face_map->
count;
i--;) {
1092 face_island_index_map[island_face_map->
indices[
i]] =
i;
1097 for (
i = island_einnercut_map->
count;
i--;) {
1108 face_island_index_map,
1114 for (pidx_isld = node_num; pidx_isld--;) {
1115 const int pidx = islands ? island_face_map->
indices[pidx_isld] : pidx_isld;
1121 for (
const int edge : corner_edges.
slice(
faces[pidx])) {
1136 face_island_index_map,
1148#undef POLY_CENTER_INIT
1157 const int node_idx_curr,
1158 const int node_idx_next,
1159 const int node_idx_dst)
1161 float *co_next, *co_dest;
1177 return (link ? (as_solution->
g_costs[node_idx_curr] + link->
cost) : 0.0f) +
1181#define ASTAR_STEPS_MAX 64
1185 const float max_dist,
1186 const float ray_radius,
1187 const Mesh *mesh_dst,
1193 const float islands_precision_src,
1197 const float full_weight = 1.0f;
1198 const float max_dist_sq = max_dist * max_dist;
1201 BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
1208 for (
int i = 0;
i < corner_verts_dst.
size();
i++) {
1218 float tmp_co[3], tmp_no[3];
1223 bool use_islands =
false;
1227 const int isld_steps_src = (islands_precision_src ?
1247 MeshElemMap *face_to_corner_tri_map_src =
nullptr;
1248 int *face_to_corner_tri_map_src_buff =
nullptr;
1254 const int num_verts_src = me_src->
verts_num;
1263 float (*vcos_interp)[3] =
nullptr;
1264 int *indices_interp =
nullptr;
1265 float *weights_interp =
nullptr;
1267 int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
1272 if (!use_from_vert) {
1281 const bool need_pnors_src = need_lnors_src ||
1283 const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
1285 if (need_pnors_dst) {
1286 face_normals_dst = mesh_dst->face_normals();
1288 if (need_lnors_dst) {
1289 loop_normals_dst = mesh_dst->corner_normals();
1291 if (need_pnors_src) {
1292 face_normals_src = me_src->face_normals();
1294 if (need_lnors_src) {
1295 loop_normals_src = me_src->corner_normals();
1299 if (use_from_vert) {
1300 vert_to_corner_map_src = me_src->vert_to_corner_map();
1302 vert_to_face_map_src = me_src->vert_to_face_map();
1309 int(edges_src.
size()),
1310 edge_to_face_src_offsets,
1311 edge_to_face_src_indices);
1313 if (use_from_vert) {
1314 loop_to_face_map_src = me_src->corner_to_face_map();
1318 positions_src, corner_verts_src.
slice(faces_src[
i]));
1330 if (gen_islands_src) {
1333 use_islands = gen_islands_src(positions_src,
1341 num_trees = use_islands ? island_store.
islands_num : 1;
1343 if (isld_steps_src) {
1359 if (isld_steps_src) {
1365 if (isld_steps_src) {
1366 for (tindex = 0; tindex < num_trees; tindex++) {
1370 edge_to_face_map_src,
1371 int(edges_src.
size()),
1375 &as_graphdata[tindex]);
1380 if (use_from_vert) {
1384 for (tindex = 0; tindex < num_trees; tindex++) {
1386 verts_active.
fill(
false);
1387 for (
int i = 0;
i < isld->
count;
i++) {
1388 for (
const int vidx_src : corner_verts_src.
slice(faces_src[isld->
indices[
i]])) {
1389 if (!verts_active[vidx_src]) {
1390 verts_active[vidx_src].set();
1401 treedata[0] = me_src->bvh_verts();
1406 corner_tris_src = me_src->corner_tris();
1407 tri_faces_src = me_src->corner_tri_faces();
1410 for (tindex = 0; tindex < num_trees; tindex++) {
1411 faces_active.
fill(
false);
1415 faces_active[
i].set();
1429 treedata[0] = me_src->bvh_corner_tris();
1435 for (tindex = 0; tindex < num_trees; tindex++) {
1440 for (pidx_dst = 0; pidx_dst < faces_dst.
size(); pidx_dst++) {
1447 bool pcent_dst_valid =
false;
1450 copy_v3_v3(pnor_dst, face_normals_dst[pidx_dst]);
1451 if (space_transform) {
1456 if (
size_t(face_dst.
size()) > islands_res_buff_size) {
1458 for (tindex = 0; tindex < num_trees; tindex++) {
1460 MEM_reallocN(islands_res[tindex],
sizeof(**islands_res) * islands_res_buff_size));
1464 for (tindex = 0; tindex < num_trees; tindex++) {
1467 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1468 const int vert_dst = corner_verts_dst[face_dst.
start() + plidx_dst];
1469 if (use_from_vert) {
1472 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1476 if (space_transform) {
1482 float (*nor_dst)[3];
1484 float best_nor_dot = -2.0f;
1485 float best_sqdist_fallback =
FLT_MAX;
1486 int best_index_src = -1;
1490 if (space_transform) {
1494 nors_src = loop_normals_src;
1495 vert_to_refelem_map_src = vert_to_corner_map_src[nearest.
index];
1498 nor_dst = &pnor_dst;
1499 nors_src = face_normals_src;
1500 vert_to_refelem_map_src = vert_to_face_map_src[nearest.
index];
1503 for (
const int index_src : vert_to_refelem_map_src) {
1505 const float dot =
dot_v3v3(nors_src[index_src], *nor_dst);
1508 loop_to_face_map_src[index_src] :
1515 int(faces_src[pidx_src].start()));
1523 if (
dot > best_nor_dot - 1e-6f) {
1529 if (!pcent_dst_valid) {
1531 vert_positions_dst, corner_verts_dst.
slice(face_dst));
1532 pcent_dst_valid =
true;
1534 pcent_src = face_cents_src[pidx_src];
1537 if ((
dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) {
1539 best_sqdist_fallback = sqdist;
1540 best_index_src = index_src;
1544 if (best_index_src == -1) {
1546 best_nor_dot = -1.0f;
1553 for (plidx_src = 0; plidx_src < face_src.
size(); plidx_src++) {
1554 const int vert_src = corner_verts_src[face_src.
start() + plidx_src];
1555 if (vert_src == nearest.
index) {
1556 best_index_src = plidx_src + int(face_src.
start());
1561 best_nor_dot = (best_nor_dot + 1.0f) * 0.5f;
1562 islands_res[tindex][plidx_dst].
factor = hit_dist ? (best_nor_dot / hit_dist) : 1e18f;
1563 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1564 islands_res[tindex][plidx_dst].
index_src = best_index_src;
1568 islands_res[tindex][plidx_dst].
factor = 0.0f;
1570 islands_res[tindex][plidx_dst].
index_src = -1;
1577 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1581 if (space_transform) {
1588 tdata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
1590 islands_res[tindex][plidx_dst].
factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) *
w;
1591 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1592 islands_res[tindex][plidx_dst].
index_src = tri_faces[rayhit.
index];
1593 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.
co);
1606 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1610 if (space_transform) {
1616 islands_res[tindex][plidx_dst].
factor = 0.0f;
1619 tdata, &nearest, tmp_co, max_dist_sq, &hit_dist))
1621 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1622 islands_res[tindex][plidx_dst].
index_src = tri_faces[nearest.
index];
1623 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.
co);
1628 islands_res[tindex][plidx_dst].
index_src = -1;
1633 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1637 if (space_transform) {
1643 islands_res[tindex][plidx_dst].
factor = hit_dist ? (1.0f / hit_dist) : 1e18f;
1644 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1645 islands_res[tindex][plidx_dst].
index_src = tri_faces[nearest.
index];
1646 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.
co);
1650 islands_res[tindex][plidx_dst].
factor = 0.0f;
1652 islands_res[tindex][plidx_dst].
index_src = -1;
1672 int *face_island_index_map =
nullptr;
1673 int pidx_src_prev = -1;
1676 float best_island_fac = 0.0f;
1677 int best_island_index = -1;
1679 for (tindex = 0; tindex < num_trees; tindex++) {
1680 float island_fac = 0.0f;
1682 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1683 island_fac += islands_res[tindex][plidx_dst].
factor;
1687 if (island_fac > best_island_fac) {
1688 best_island_fac = island_fac;
1689 best_island_index = tindex;
1693 if (best_island_index != -1 && isld_steps_src) {
1694 best_island = use_islands ? island_store.
islands[best_island_index] :
nullptr;
1695 as_graph = &as_graphdata[best_island_index];
1696 face_island_index_map = (
int *)as_graph->
custom_data;
1700 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1702 lidx_dst = plidx_dst + int(face_dst.
start());
1704 if (best_island_index == -1) {
1712 isld_res = &islands_res[best_island_index][plidx_dst];
1713 if (use_from_vert) {
1716 if (lidx_src >= 0) {
1717 pidx_src = loop_to_face_map_src[lidx_src];
1719 if (!
ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1720 int pidx_isld_src, pidx_isld_src_prev;
1721 if (face_island_index_map) {
1722 pidx_isld_src = face_island_index_map[pidx_src];
1723 pidx_isld_src_prev = face_island_index_map[pidx_src_prev];
1726 pidx_isld_src = pidx_src;
1727 pidx_isld_src_prev = pidx_src_prev;
1744 int last_valid_pidx_isld_src = -1;
1746 for (
int i = as_solution.
steps - 1;
i--;) {
1749 pidx_isld_src = as_solution.
prev_nodes[pidx_isld_src];
1753 last_valid_pidx_isld_src = pidx_isld_src;
1756 if (last_valid_pidx_isld_src != -1) {
1761 copy_v3_v3(tmp_co, vert_positions_dst[corner_verts_dst[lidx_dst]]);
1765 if (space_transform) {
1769 pidx_src = (use_islands ? best_island->
indices[last_valid_pidx_isld_src] :
1770 last_valid_pidx_isld_src);
1772 for (
const int64_t corner : face_src) {
1773 const int vert_src = corner_verts_src[corner];
1775 if (dist_sq < best_dist_sq) {
1776 best_dist_sq = dist_sq;
1777 lidx_src = int(corner);
1790 pidx_src_prev = pidx_src;
1797 r_map, lidx_dst,
FLT_MAX, best_island_index, 0,
nullptr,
nullptr);
1803 if (pidx_src >= 0) {
1805 int best_loop_index_src;
1809 if (!
ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1810 int pidx_isld_src, pidx_isld_src_prev;
1811 if (face_island_index_map) {
1812 pidx_isld_src = face_island_index_map[pidx_src];
1813 pidx_isld_src_prev = face_island_index_map[pidx_src_prev];
1816 pidx_isld_src = pidx_src;
1817 pidx_isld_src_prev = pidx_src_prev;
1834 int last_valid_pidx_isld_src = -1;
1836 for (
int i = as_solution.
steps - 1;
i--;) {
1840 pidx_isld_src = as_solution.
prev_nodes[pidx_isld_src];
1844 last_valid_pidx_isld_src = pidx_isld_src;
1847 if (last_valid_pidx_isld_src != -1) {
1853 const int vert_dst = corner_verts_dst[lidx_dst];
1854 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1858 if (space_transform) {
1862 pidx_src = (use_islands ? best_island->
indices[last_valid_pidx_isld_src] :
1863 last_valid_pidx_isld_src);
1866 if (face_to_corner_tri_map_src ==
nullptr) {
1868 &face_to_corner_tri_map_src_buff,
1870 tri_faces_src.
data(),
1871 int(tri_faces_src.
size()));
1874 for (j = face_to_corner_tri_map_src[pidx_src].
count; j--;) {
1877 corner_tris_src[face_to_corner_tri_map_src[pidx_src].
indices[j]];
1882 positions_src[corner_verts_src[tri[0]]],
1883 positions_src[corner_verts_src[tri[1]]],
1884 positions_src[corner_verts_src[tri[2]]]);
1886 if (dist_sq < best_dist_sq) {
1888 best_dist_sq = dist_sq;
1906 &best_loop_index_src);
1913 &best_loop_index_src,
1938 pidx_src_prev = pidx_src;
1945 r_map, lidx_dst,
FLT_MAX, best_island_index, 0,
nullptr,
nullptr);
1954 for (tindex = 0; tindex < num_trees; tindex++) {
1956 if (isld_steps_src) {
1962 if (isld_steps_src) {
1967 if (face_to_corner_tri_map_src) {
1970 if (face_to_corner_tri_map_src_buff) {
1971 MEM_freeN(face_to_corner_tri_map_src_buff);
1976 if (indices_interp) {
1979 if (weights_interp) {
1987 const float max_dist,
1988 const float ray_radius,
1989 const Mesh *mesh_dst,
1996 const float full_weight = 1.0f;
1997 const float max_dist_sq = max_dist * max_dist;
2004 face_normals_dst = mesh_dst->face_normals();
2012 const int index = int(
i);
2030 corner_verts_dst.
slice(face));
2033 if (space_transform) {
2039 const int face_index = tri_faces[nearest.
index];
2053 corner_verts_dst.
slice(face));
2057 if (space_transform) {
2063 &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
2065 const int face_index = tri_faces[rayhit.
index];
2080 const size_t numfaces_src = size_t(me_src->
faces_num);
2097 int tot_rays, done_rays = 0;
2098 float face_area_2d_inv, done_area = 0.0f;
2101 float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
2102 float faces_dst_2d_min[2], faces_dst_2d_max[2], faces_dst_2d_z;
2103 float faces_dst_2d_size[2];
2105 float totweights = 0.0f;
2106 float hit_dist_accum = 0.0f;
2107 int sources_num = 0;
2108 const int tris_num = int(face.
size()) - 2;
2112 corner_verts_dst.
slice(face));
2117 if (space_transform) {
2122 copy_vn_fl(weights,
int(numfaces_src), 0.0f);
2125 tmp_face_size = size_t(face.
size());
2126 face_vcos_2d =
static_cast<float (*)[2]
>(
2127 MEM_reallocN(face_vcos_2d,
sizeof(*face_vcos_2d) * tmp_face_size));
2128 tri_vidx_2d =
static_cast<int (*)[3]
>(
2129 MEM_reallocN(tri_vidx_2d,
sizeof(*tri_vidx_2d) * (tmp_face_size - 2)));
2136 faces_dst_2d_z = pcent_dst[2];
2141 for (j = 0; j < face.
size(); j++) {
2142 const int vert = corner_verts_dst[face[j]];
2143 copy_v3_v3(tmp_co, vert_positions_dst[vert]);
2144 if (space_transform) {
2147 mul_v2_m3v3(face_vcos_2d[j], to_pnor_2d_mat, tmp_co);
2148 minmax_v2v2_v2(faces_dst_2d_min, faces_dst_2d_max, face_vcos_2d[j]);
2153 sub_v2_v2v2(faces_dst_2d_size, faces_dst_2d_max, faces_dst_2d_min);
2156 tot_rays = int((
max_ff(faces_dst_2d_size[0], faces_dst_2d_size[1]) / ray_radius) + 0.5f);
2163 tot_rays *= tot_rays;
2167 face_area_2d_inv = 1.0f /
max_ff(face_area_2d_inv, 1e-9f);
2170 if (face.
size() == 3) {
2171 tri_vidx_2d[0][0] = 0;
2172 tri_vidx_2d[0][1] = 1;
2173 tri_vidx_2d[0][2] = 2;
2175 if (face.
size() == 4) {
2176 tri_vidx_2d[0][0] = 0;
2177 tri_vidx_2d[0][1] = 1;
2178 tri_vidx_2d[0][2] = 2;
2179 tri_vidx_2d[1][0] = 0;
2180 tri_vidx_2d[1][1] = 2;
2181 tri_vidx_2d[1][2] = 3;
2187 for (j = 0; j < tris_num; j++) {
2188 float *v1 = face_vcos_2d[tri_vidx_2d[j][0]];
2189 float *
v2 = face_vcos_2d[tri_vidx_2d[j][1]];
2190 float *v3 = face_vcos_2d[tri_vidx_2d[j][2]];
2196 rays_num =
max_ii(
int(
float(tot_rays) * done_area * face_area_2d_inv + 0.5f) - done_rays,
2198 done_rays += rays_num;
2200 while (rays_num--) {
2206 tmp_co[2] = faces_dst_2d_z;
2212 &treedata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
2214 const int face_index = tri_faces[rayhit.
index];
2215 weights[face_index] +=
w;
2217 hit_dist_accum += hit_dist;
2226 if (totweights > 0.0f) {
2227 for (j = 0; j < int(numfaces_src); j++) {
2232 weights[sources_num] = weights[j] / totweights;
2237 r_map,
int(
i), hit_dist_accum / totweights, 0, sources_num,
indices, weights);
2252 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh face mapping mode (%d)!", mode);
2253 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(faces_dst.
size()));
2258#undef MREMAP_RAYCAST_APPROXIMATE_NR
2259#undef MREMAP_RAYCAST_APPROXIMATE_FAC
2260#undef MREMAP_RAYCAST_TRI_SAMPLES_MIN
2261#undef MREMAP_RAYCAST_TRI_SAMPLES_MAX
2262#undef MREMAP_DEFAULT_BUFSIZE
CustomData interface, see also DNA_customdata_types.h.
bool(*)(blender::Span< blender::float3 > vert_positions, blender::Span< blender::int2 > edges, blender::Span< bool > uv_seams, blender::OffsetIndices< int > faces, blender::Span< int > corner_verts, blender::Span< int > corner_edges, MeshIslandStore *r_island_store) MeshRemapIslandsCalc
void BKE_mesh_loop_islands_free(MeshIslandStore *island_store)
void BKE_mesh_origindex_map_create_corner_tri(MeshElemMap **r_map, int **r_mem, blender::OffsetIndices< int > faces, const int *corner_tri_faces, int corner_tris_num)
An implementation of the A* (AStar) algorithm to solve shortest path problem.
bool BLI_astar_graph_solve(BLI_AStarGraph *as_graph, int node_index_src, int node_index_dst, astar_f_cost f_cost_cb, BLI_AStarSolution *r_solution, int max_steps)
void BLI_astar_solution_clear(BLI_AStarSolution *as_solution)
void BLI_astar_node_init(BLI_AStarGraph *as_graph, int node_index, void *custom_data)
void BLI_astar_node_link_add(BLI_AStarGraph *as_graph, int node1_index, int node2_index, float cost, void *custom_data)
void BLI_astar_solution_init(BLI_AStarGraph *as_graph, BLI_AStarSolution *as_solution, void *custom_data)
void BLI_astar_graph_init(BLI_AStarGraph *as_graph, int node_num, void *custom_data)
void BLI_astar_solution_free(BLI_AStarSolution *as_solution)
void BLI_astar_graph_free(BLI_AStarGraph *as_graph)
#define BLI_BITMAP_NEW(_num, _alloc_string)
#define BLI_BITMAP_TEST(_bitmap, _index)
#define BLI_BITMAP_ENABLE(_bitmap, _index)
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
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, float max_diff, 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])
MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2])
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])
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
float area_poly_v2(const float verts[][2], unsigned int nr)
void interp_weights_poly_v3(float w[], float v[][3], int n, const float co[3])
void mul_m3_v3(const float M[3][3], float r[3])
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])
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void unit_m4(float m[4][4])
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.
void BLI_covariance_m3_v3n(const float(*cos_v3)[3], int cos_v3_num, bool use_sample_correction, float r_covmat[3][3], float r_center[3])
Compute the covariance matrix of given set of 3D coordinates.
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 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 copy_vn_fl(float *array_tar, int size, float val)
void interp_v3_v3v3_slerp_safe(float target[3], const float a[3], const float b[3], float t)
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
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])
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void * BLI_memarena_calloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_polyfill_calc(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3])
struct RNG * BLI_rng_new(unsigned int seed)
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
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()
#define INIT_MINMAX2(min, max)
#define POINTER_FROM_INT(i)
#define UNUSED_VARS_NDEBUG(...)
#define POINTER_AS_INT(i)
#define CLOG_WARN(clg_ref,...)
@ MREMAP_MODE_VERT_EDGE_NEAREST
@ MREMAP_MODE_VERT_POLYINTERP_VNORPROJ
@ MREMAP_MODE_VERT_FACE_NEAREST
@ MREMAP_MODE_EDGE_POLY_NEAREST
@ MREMAP_MODE_VERT_EDGEINTERP_NEAREST
@ MREMAP_MODE_VERT_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_POLYNOR
@ MREMAP_MODE_EDGE_VERT_NEAREST
@ MREMAP_MODE_EDGE_NEAREST
@ MREMAP_MODE_LOOP_NEAREST_LOOPNOR
@ MREMAP_MODE_LOOP_POLY_NEAREST
@ MREMAP_MODE_EDGE_EDGEINTERP_VNORPROJ
@ MREMAP_MODE_POLY_POLYINTERP_PNORPROJ
@ MREMAP_MODE_POLY_NEAREST
@ MREMAP_MODE_VERT_POLYINTERP_NEAREST
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void reinitialize(const int64_t new_size)
static IndexMask from_bits(BitSpan bits, IndexMaskMemory &memory)
void reinitialize(const int64_t new_size)
constexpr int64_t size() const
constexpr int64_t start() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T * data() const
constexpr int64_t size() const
void fill(const bool value)
GAttributeReader lookup(const StringRef attribute_id) const
IndexRange index_range() const
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius, const Span< float3 > vert_positions_dst, const Span< blender::int2 > edges_dst, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map)
#define MREMAP_RAYCAST_TRI_SAMPLES_MIN
#define MREMAP_RAYCAST_TRI_SAMPLES_MAX
void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius, const Mesh *mesh_dst, const Span< float3 > vert_positions_dst, const Span< int > corner_verts_dst, const blender::OffsetIndices< int > faces_dst, const Mesh *me_src, MeshRemapIslandsCalc gen_islands_src, const float islands_precision_src, MeshPairRemap *r_map)
static bool mesh_remap_bvhtree_query_nearest(blender::bke::BVHTreeFromMesh *treedata, BVHTreeNearest *nearest, const float co[3], const float max_dist_sq, float *r_hit_dist)
void BKE_mesh_remap_find_best_match_from_mesh(const Span< float3 > vert_positions_dst, const Mesh *me_src, SpaceTransform *r_space_transform)
static bool mesh_remap_bvhtree_query_raycast(blender::bke::BVHTreeFromMesh *treedata, BVHTreeRayHit *rayhit, const float co[3], const float no[3], const float radius, const float max_dist, float *r_hit_dist)
void BKE_mesh_remap_calc_faces_from_mesh(const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius, const Mesh *mesh_dst, const Span< float3 > vert_positions_dst, const Span< int > corner_verts_dst, const blender::OffsetIndices< int > faces_dst, const Mesh *me_src, MeshPairRemap *r_map)
void BKE_mesh_remap_free(MeshPairRemap *map)
#define MREMAP_RAYCAST_APPROXIMATE_NR
static void mesh_calc_eigen_matrix(const Span< float3 > positions, float r_mat[4][4])
void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index)
static void mesh_island_to_astar_graph(MeshIslandStore *islands, const int island_index, const blender::Span< blender::float3 > positions, const blender::GroupedSpan< int > edge_to_face_map, const int numedges, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_verts, const blender::Span< int > corner_edges, BLI_AStarGraph *r_as_graph)
void BKE_mesh_remap_calc_verts_from_mesh(const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius, const Span< float3 > vert_positions_dst, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map)
#define MREMAP_RAYCAST_APPROXIMATE_FAC
static int mesh_remap_interp_face_data_get(const blender::IndexRange face, const blender::Span< int > corner_verts, const blender::Span< blender::float3 > positions_src, 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)
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)
#define MREMAP_DEFAULT_BUFSIZE
static void mesh_remap_item_define(MeshPairRemap *map, const int index, const float, const int island, const int sources_num, const int *indices_src, const float *weights_src)
static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, const int island_index, BLI_AStarGraph *as_graph, const blender::Span< blender::float3 > positions, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_verts, const int edge_idx, BLI_bitmap *done_edges, const blender::GroupedSpan< int > edge_to_face_map, const bool is_edge_innercut, const int *face_island_index_map, float(*face_centers)[3], uchar *face_status)
float BKE_mesh_remap_calc_difference_from_mesh(const SpaceTransform *space_transform, const Span< float3 > vert_positions_dst, const Mesh *me_src)
void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num)
int edge_other_vert(const int2 edge, const int vert)
GroupedSpan< int > build_edge_to_face_map(OffsetIndices< int > faces, Span< int > corner_edges, int edges_num, Array< int > &r_offsets, Array< int > &r_indices)
float3 face_center_calc(Span< float3 > vert_positions, Span< int > face_verts)
GroupedSpan< int > build_vert_to_edge_map(Span< int2 > edges, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
BVHTreeFromMesh bvhtree_from_mesh_corner_tris_ex(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, Span< int3 > corner_tris, const IndexMask &faces_mask)
BVHTreeFromMesh bvhtree_from_mesh_verts_ex(Span< float3 > vert_positions, const IndexMask &verts_mask)
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
BLI_AStarGNLink ** prev_links
MeshPairRemapItem * items
BVHTree_NearestPointCallback nearest_callback
BVHTree_RayCastCallback raycast_callback