48 const float max_dist_sq,
52 if (nearest->
index != -1) {
54 if (nearest->
dist_sq > max_dist_sq) {
66 if ((nearest->
index != -1) && (nearest->
dist_sq <= max_dist_sq)) {
86 rayhit->
dist = max_dist;
95 if (rayhit_tmp.
dist < rayhit->
dist) {
99 if ((rayhit->
index != -1) && (rayhit->
dist <= max_dist)) {
100 *r_hit_dist = rayhit->
dist;
116 const float (*vert_positions_dst)[3],
117 const int numverts_dst,
129 for (
i = 0;
i < numverts_dst;
i++) {
135 if (space_transform) {
140 result += 1.0f / (hit_dist + 1.0f);
151 printf(
"%s: Computed difference between meshes (the lower the better): %f\n", __func__,
result);
170 const float (*vcos)[3],
174 float center[3], covmat[3][3];
175 float eigen_val[3], eigen_vec[3][3];
176 float(*
cos)[3] =
nullptr;
183 memcpy(
cos, positions,
sizeof(
float[3]) *
size_t(numverts));
188 vcos =
static_cast<const float(*)[3]
>((
void *)
cos);
228 for (
i = 0;
i < 3;
i++) {
229 float evi = eigen_val[
i];
236 evi = (evi < 1e-6f && evi > -1e-6f) ? ((evi < 0.0f) ? -1e-3f : 1e-3f) :
sqrtf_signed(evi);
245 const int numverts_dst,
251 const float mirrors[][3] = {
261 const float(*mirr)[3];
263 float mat_src[4][4], mat_dst[4][4], best_mat_dst[4][4];
264 float best_match =
FLT_MAX, match;
266 const int numverts_src = me_src->
verts_num;
269 nullptr,
reinterpret_cast<const float(*)[3]
>(positions_src.
data()), numverts_src, mat_src);
274 r_space_transform, vert_positions_dst, numverts_dst, me_src);
279 for (mirr = mirrors; (*mirr)[0]; mirr++) {
286 r_space_transform, vert_positions_dst, numverts_dst, me_src);
287 if (match < best_match) {
322 map->
items =
nullptr;
330 const int sources_num,
331 const int *indices_src,
332 const float *weights_src)
363 const float point[3],
366 const bool use_loops,
369 const bool do_weights,
370 int *r_closest_index)
375 const int sources_num = int(face.
size());
378 if (
size_t(sources_num) > *buff_size) {
379 *buff_size = size_t(sources_num);
380 *vcos =
static_cast<float(*)[3]
>(
MEM_reallocN(*vcos,
sizeof(**vcos) * *buff_size));
383 *weights =
static_cast<float *
>(
MEM_reallocN(*weights,
sizeof(**weights) * *buff_size));
387 for (
i = 0, vco = *vcos, index = *
indices;
i < sources_num;
i++, vco++, index++) {
388 const int vert = corner_verts[face[
i]];
389 *index = use_loops ? int(face[
i]) : vert;
391 if (r_closest_index) {
394 if (dist_sq < ref_dist_sq) {
395 ref_dist_sq = dist_sq;
396 *r_closest_index = *index;
437#define MREMAP_RAYCAST_APPROXIMATE_NR 3
439#define MREMAP_RAYCAST_APPROXIMATE_FAC 5.0f
442#define MREMAP_RAYCAST_TRI_SAMPLES_MIN 4
443#define MREMAP_RAYCAST_TRI_SAMPLES_MAX 20
446#define MREMAP_DEFAULT_BUFSIZE 32
450 const float max_dist,
451 const float ray_radius,
452 const float (*vert_positions_dst)[3],
453 const int numverts_dst,
458 const float full_weight = 1.0f;
459 const float max_dist_sq = max_dist * max_dist;
468 for (
i = 0;
i < numverts_dst;
i++) {
477 float tmp_co[3], tmp_no[3];
480 treedata = me_src->bvh_verts();
483 for (
i = 0;
i < numverts_dst;
i++) {
487 if (space_transform) {
505 treedata = me_src->bvh_edges();
508 for (
i = 0;
i < numverts_dst;
i++) {
512 if (space_transform) {
519 const float *v1cos = positions_src[edge[0]];
520 const float *v2cos = positions_src[edge[1]];
525 const int index = (dist_v1 > dist_v2) ? edge[1] : edge[0];
537 CLAMP(weights[0], 0.0f, 1.0f);
538 weights[1] = 1.0f - weights[0];
565 treedata = me_src->bvh_corner_tris();
568 for (
i = 0;
i < numverts_dst;
i++) {
573 if (space_transform) {
579 &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
581 const int face_index = tri_faces[rayhit.
index];
605 for (
i = 0;
i < numverts_dst;
i++) {
609 if (space_transform) {
614 &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
616 const int face_index = tri_faces[nearest.
index];
662 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh vertex mapping mode (%d)!", mode);
663 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(numverts_dst));
670 const float max_dist,
671 const float ray_radius,
672 const float (*vert_positions_dst)[3],
673 const int numverts_dst,
675 const int numedges_dst,
681 const float full_weight = 1.0f;
682 const float max_dist_sq = max_dist * max_dist;
691 for (
i = 0;
i < numedges_dst;
i++) {
700 float tmp_co[3], tmp_no[3];
703 const int num_verts_src = me_src->
verts_num;
713 for (
i = 0;
i < numverts_dst;
i++) {
714 v_dst_to_src_map[
i].hit_dist = -1.0f;
720 edges_src, num_verts_src, vert_to_edge_src_offsets, vert_to_edge_src_indices);
722 treedata = me_src->bvh_verts();
725 for (
i = 0;
i < numedges_dst;
i++) {
728 int best_eidx_src = -1;
732 const int vidx_dst = j ? e_dst[0] : e_dst[1];
735 if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
736 copy_v3_v3(tmp_co, vert_positions_dst[vidx_dst]);
739 if (space_transform) {
744 &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
746 v_dst_to_src_map[vidx_dst].hit_dist = hit_dist;
747 v_dst_to_src_map[vidx_dst].index = nearest.
index;
751 v_dst_to_src_map[vidx_dst].hit_dist =
FLT_MAX;
759 const int vidx_dst = j ? e_dst[0] : e_dst[1];
760 const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist;
761 const int vidx_src = v_dst_to_src_map[vidx_dst].index;
769 eidx_src = vert_to_edge_src_map[vidx_src].
data();
770 k = int(vert_to_edge_src_map[vidx_src].
size());
772 for (; k--; eidx_src++) {
774 const float *other_co_src =
776 const float *other_co_dst =
778 const float totdist = first_dist +
len_v3v3(other_co_src, other_co_dst);
780 if (totdist < best_totdist) {
781 best_totdist = totdist;
782 best_eidx_src = *eidx_src;
787 if (best_eidx_src >= 0) {
788 const float *co1_src = positions_src[edges_src[best_eidx_src][0]];
789 const float *co2_src = positions_src[edges_src[best_eidx_src][1]];
790 const float *co1_dst = vert_positions_dst[e_dst[0]];
791 const float *co2_dst = vert_positions_dst[e_dst[1]];
792 float co_src[3], co_dst[3];
796 co1_src, co2_src, co1_dst, co2_dst, co_src, co_dst);
797 if (isect_type != 0) {
800 if (fac_src < 0.0f) {
803 else if (fac_src > 1.0f) {
806 if (fac_dst < 0.0f) {
809 else if (fac_dst > 1.0f) {
813 hit_dist =
len_v3v3(co_dst, co_src);
825 treedata = me_src->bvh_edges();
828 for (
i = 0;
i < numedges_dst;
i++) {
830 vert_positions_dst[edges_dst[
i][0]],
831 vert_positions_dst[edges_dst[
i][1]],
835 if (space_transform) {
856 treedata = me_src->bvh_corner_tris();
858 for (
i = 0;
i < numedges_dst;
i++) {
860 vert_positions_dst[edges_dst[
i][0]],
861 vert_positions_dst[edges_dst[
i][1]],
865 if (space_transform) {
871 const int face_index = tri_faces[nearest.
index];
873 const int *corner_edge_src = &corner_edges_src[face_src.
start()];
874 int nloops = int(face_src.
size());
876 int best_eidx_src = -1;
878 for (; nloops--; corner_edge_src++) {
880 const float *co1_src = positions_src[edge_src[0]];
881 const float *co2_src = positions_src[edge_src[1]];
887 if (dist_sq < best_dist_sq) {
888 best_dist_sq = dist_sq;
889 best_eidx_src = *corner_edge_src;
892 if (best_eidx_src >= 0) {
903 const int num_rays_min = 5, num_rays_max = 100;
904 const int numedges_src = me_src->
edges_num;
911 treedata = me_src->bvh_edges();
915 for (
i = 0;
i < numedges_dst;
i++) {
919 float v1_co[3], v2_co[3];
920 float v1_no[3], v2_no[3];
926 float totweights = 0.0f;
927 float hit_dist_accum = 0.0f;
931 copy_v3_v3(v1_co, vert_positions_dst[edge[0]]);
932 copy_v3_v3(v2_co, vert_positions_dst[edge[1]]);
938 if (space_transform) {
949 edge_dst_len =
len_v3v3(v1_co, v2_co);
951 grid_size = int((edge_dst_len / ray_radius) + 0.5f);
952 CLAMP(grid_size, num_rays_min, num_rays_max);
955 grid_step = 1.0f / float(grid_size);
958 for (j = 0; j < grid_size; j++) {
959 const float fac = grid_step * float(j);
969 &treedata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
971 weights[rayhit.
index] +=
w;
973 hit_dist_accum += hit_dist;
982 if (totweights > (
float(grid_size) / 2.0f)) {
983 for (j = 0; j < int(numedges_src); j++) {
988 weights[sources_num] = weights[j] / totweights;
993 r_map,
i, hit_dist_accum / totweights, 0, sources_num,
indices, weights);
1005 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh edge mapping mode (%d)!", mode);
1006 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(numedges_dst));
1012#define POLY_CENTER_INIT 1
1013#define POLY_COMPLETE 2
1017 const int island_index,
1025 const bool is_edge_innercut,
1026 const int *face_island_index_map,
1027 float (*face_centers)[3],
1033 for (
i = 0;
i < edge_to_face_map[edge_idx].
size();
i++) {
1034 const int pidx = edge_to_face_map[edge_idx][
i];
1036 const int pidx_isld = islands ? face_island_index_map[pidx] : pidx;
1041 face_island_indices[
i] = -1;
1046 face_island_indices[
i] = pidx_isld;
1059 const int pidx_isld_other = face_island_indices[j];
1061 if (pidx_isld_other == -1 || face_status[pidx_isld_other] ==
POLY_COMPLETE) {
1065 dist_cost =
len_v3v3(face_centers[pidx_isld_other], face_centers[pidx_isld]);
1069 face_island_indices[
i] = pidx_isld;
1076 const int island_index,
1088 int *face_island_index_map =
nullptr;
1091 const int node_num = islands ? island_face_map->
count : int(
faces.size());
1093 float(*face_centers)[3];
1100 face_centers =
static_cast<float(*)[3]
>(
1106 r_as_graph->
mem,
sizeof(*face_island_index_map) *
size_t(
faces.size())));
1107 for (
i = island_face_map->
count;
i--;) {
1108 face_island_index_map[island_face_map->
indices[
i]] =
i;
1113 for (
i = island_einnercut_map->
count;
i--;) {
1124 face_island_index_map,
1130 for (pidx_isld = node_num; pidx_isld--;) {
1131 const int pidx = islands ? island_face_map->
indices[pidx_isld] : pidx_isld;
1137 for (
const int edge : corner_edges.
slice(
faces[pidx])) {
1152 face_island_index_map,
1164#undef POLY_CENTER_INIT
1173 const int node_idx_curr,
1174 const int node_idx_next,
1175 const int node_idx_dst)
1177 float *co_next, *co_dest;
1193 return (link ? (as_solution->
g_costs[node_idx_curr] + link->
cost) : 0.0f) +
1197#define ASTAR_STEPS_MAX 64
1201 const float max_dist,
1202 const float ray_radius,
1203 const Mesh *mesh_dst,
1204 const float (*vert_positions_dst)[3],
1205 const int numverts_dst,
1206 const int *corner_verts_dst,
1207 const int numloops_dst,
1211 const float islands_precision_src,
1215 const float full_weight = 1.0f;
1216 const float max_dist_sq = max_dist * max_dist;
1219 BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
1226 for (
int i = 0;
i < numloops_dst;
i++) {
1236 float tmp_co[3], tmp_no[3];
1241 bool use_islands =
false;
1245 const int isld_steps_src = (islands_precision_src ?
1265 MeshElemMap *face_to_corner_tri_map_src =
nullptr;
1266 int *face_to_corner_tri_map_src_buff =
nullptr;
1272 const int num_verts_src = me_src->
verts_num;
1281 float(*vcos_interp)[3] =
nullptr;
1282 int *indices_interp =
nullptr;
1283 float *weights_interp =
nullptr;
1285 int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
1290 if (!use_from_vert) {
1299 const bool need_pnors_src = need_lnors_src ||
1301 const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
1303 if (need_pnors_dst) {
1304 face_normals_dst = mesh_dst->face_normals();
1306 if (need_lnors_dst) {
1307 loop_normals_dst = mesh_dst->corner_normals();
1309 if (need_pnors_src) {
1310 face_normals_src = me_src->face_normals();
1312 if (need_lnors_src) {
1313 loop_normals_src = me_src->corner_normals();
1317 if (use_from_vert) {
1318 vert_to_corner_map_src = me_src->vert_to_corner_map();
1320 vert_to_face_map_src = me_src->vert_to_face_map();
1327 int(edges_src.
size()),
1328 edge_to_face_src_offsets,
1329 edge_to_face_src_indices);
1331 if (use_from_vert) {
1332 loop_to_face_map_src = me_src->corner_to_face_map();
1336 positions_src, corner_verts_src.
slice(faces_src[
i]));
1348 if (gen_islands_src) {
1349 const bool *uv_seams =
static_cast<const bool *
>(
1351 use_islands = gen_islands_src(
reinterpret_cast<const float(*)[3]
>(positions_src.
data()),
1354 int(edges_src.
size()),
1357 corner_verts_src.
data(),
1358 corner_edges_src.
data(),
1359 int(corner_verts_src.
size()),
1362 num_trees = use_islands ? island_store.
islands_num : 1;
1364 if (isld_steps_src) {
1380 if (isld_steps_src) {
1386 if (isld_steps_src) {
1387 for (tindex = 0; tindex < num_trees; tindex++) {
1391 edge_to_face_map_src,
1392 int(edges_src.
size()),
1396 &as_graphdata[tindex]);
1401 if (use_from_vert) {
1405 for (tindex = 0; tindex < num_trees; tindex++) {
1407 verts_active.
fill(
false);
1408 for (
int i = 0;
i < isld->
count;
i++) {
1409 for (
const int vidx_src : corner_verts_src.
slice(faces_src[isld->
indices[
i]])) {
1410 if (!verts_active[vidx_src]) {
1411 verts_active[vidx_src].set();
1422 treedata[0] = me_src->bvh_verts();
1427 corner_tris_src = me_src->corner_tris();
1428 tri_faces_src = me_src->corner_tri_faces();
1431 for (tindex = 0; tindex < num_trees; tindex++) {
1432 faces_active.
fill(
false);
1436 faces_active[
i].set();
1450 treedata[0] = me_src->bvh_corner_tris();
1456 for (tindex = 0; tindex < num_trees; tindex++) {
1461 for (pidx_dst = 0; pidx_dst < faces_dst.
size(); pidx_dst++) {
1468 bool pcent_dst_valid =
false;
1471 copy_v3_v3(pnor_dst, face_normals_dst[pidx_dst]);
1472 if (space_transform) {
1477 if (
size_t(face_dst.
size()) > islands_res_buff_size) {
1479 for (tindex = 0; tindex < num_trees; tindex++) {
1481 MEM_reallocN(islands_res[tindex],
sizeof(**islands_res) * islands_res_buff_size));
1485 for (tindex = 0; tindex < num_trees; tindex++) {
1488 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1489 const int vert_dst = corner_verts_dst[face_dst.
start() + plidx_dst];
1490 if (use_from_vert) {
1493 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1497 if (space_transform) {
1505 float best_nor_dot = -2.0f;
1506 float best_sqdist_fallback =
FLT_MAX;
1507 int best_index_src = -1;
1511 if (space_transform) {
1515 nors_src = loop_normals_src;
1516 vert_to_refelem_map_src = vert_to_corner_map_src[nearest.
index];
1519 nor_dst = &pnor_dst;
1520 nors_src = face_normals_src;
1521 vert_to_refelem_map_src = vert_to_face_map_src[nearest.
index];
1524 for (
const int index_src : vert_to_refelem_map_src) {
1526 const float dot =
dot_v3v3(nors_src[index_src], *nor_dst);
1529 loop_to_face_map_src[index_src] :
1536 int(faces_src[pidx_src].start()));
1544 if (
dot > best_nor_dot - 1e-6f) {
1550 if (!pcent_dst_valid) {
1555 pcent_dst_valid =
true;
1557 pcent_src = face_cents_src[pidx_src];
1560 if ((
dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) {
1562 best_sqdist_fallback = sqdist;
1563 best_index_src = index_src;
1567 if (best_index_src == -1) {
1569 best_nor_dot = -1.0f;
1576 for (plidx_src = 0; plidx_src < face_src.
size(); plidx_src++) {
1577 const int vert_src = corner_verts_src[face_src.
start() + plidx_src];
1578 if (vert_src == nearest.
index) {
1579 best_index_src = plidx_src + int(face_src.
start());
1584 best_nor_dot = (best_nor_dot + 1.0f) * 0.5f;
1585 islands_res[tindex][plidx_dst].
factor = hit_dist ? (best_nor_dot / hit_dist) : 1e18f;
1586 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1587 islands_res[tindex][plidx_dst].
index_src = best_index_src;
1591 islands_res[tindex][plidx_dst].
factor = 0.0f;
1593 islands_res[tindex][plidx_dst].
index_src = -1;
1600 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1604 if (space_transform) {
1611 tdata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
1613 islands_res[tindex][plidx_dst].
factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) *
w;
1614 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1615 islands_res[tindex][plidx_dst].
index_src = tri_faces[rayhit.
index];
1616 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.
co);
1629 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1633 if (space_transform) {
1639 islands_res[tindex][plidx_dst].
factor = 0.0f;
1642 tdata, &nearest, tmp_co, max_dist_sq, &hit_dist))
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);
1651 islands_res[tindex][plidx_dst].
index_src = -1;
1656 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1660 if (space_transform) {
1666 islands_res[tindex][plidx_dst].
factor = hit_dist ? (1.0f / hit_dist) : 1e18f;
1667 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1668 islands_res[tindex][plidx_dst].
index_src = tri_faces[nearest.
index];
1669 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.
co);
1673 islands_res[tindex][plidx_dst].
factor = 0.0f;
1675 islands_res[tindex][plidx_dst].
index_src = -1;
1695 int *face_island_index_map =
nullptr;
1696 int pidx_src_prev = -1;
1699 float best_island_fac = 0.0f;
1700 int best_island_index = -1;
1702 for (tindex = 0; tindex < num_trees; tindex++) {
1703 float island_fac = 0.0f;
1705 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1706 island_fac += islands_res[tindex][plidx_dst].
factor;
1708 island_fac /= float(face_dst.
size());
1710 if (island_fac > best_island_fac) {
1711 best_island_fac = island_fac;
1712 best_island_index = tindex;
1716 if (best_island_index != -1 && isld_steps_src) {
1717 best_island = use_islands ? island_store.
islands[best_island_index] :
nullptr;
1718 as_graph = &as_graphdata[best_island_index];
1719 face_island_index_map = (
int *)as_graph->
custom_data;
1723 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1725 lidx_dst = plidx_dst + int(face_dst.
start());
1727 if (best_island_index == -1) {
1735 isld_res = &islands_res[best_island_index][plidx_dst];
1736 if (use_from_vert) {
1739 if (lidx_src >= 0) {
1740 pidx_src = loop_to_face_map_src[lidx_src];
1742 if (!
ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1743 int pidx_isld_src, pidx_isld_src_prev;
1744 if (face_island_index_map) {
1745 pidx_isld_src = face_island_index_map[pidx_src];
1746 pidx_isld_src_prev = face_island_index_map[pidx_src_prev];
1749 pidx_isld_src = pidx_src;
1750 pidx_isld_src_prev = pidx_src_prev;
1767 int last_valid_pidx_isld_src = -1;
1769 for (
int i = as_solution.
steps - 1;
i--;) {
1772 pidx_isld_src = as_solution.
prev_nodes[pidx_isld_src];
1776 last_valid_pidx_isld_src = pidx_isld_src;
1779 if (last_valid_pidx_isld_src != -1) {
1784 copy_v3_v3(tmp_co, vert_positions_dst[corner_verts_dst[lidx_dst]]);
1788 if (space_transform) {
1792 pidx_src = (use_islands ? best_island->
indices[last_valid_pidx_isld_src] :
1793 last_valid_pidx_isld_src);
1795 for (
const int64_t corner : face_src) {
1796 const int vert_src = corner_verts_src[corner];
1798 if (dist_sq < best_dist_sq) {
1799 best_dist_sq = dist_sq;
1800 lidx_src = int(corner);
1813 pidx_src_prev = pidx_src;
1820 r_map, lidx_dst,
FLT_MAX, best_island_index, 0,
nullptr,
nullptr);
1826 if (pidx_src >= 0) {
1828 int best_loop_index_src;
1832 if (!
ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1833 int pidx_isld_src, pidx_isld_src_prev;
1834 if (face_island_index_map) {
1835 pidx_isld_src = face_island_index_map[pidx_src];
1836 pidx_isld_src_prev = face_island_index_map[pidx_src_prev];
1839 pidx_isld_src = pidx_src;
1840 pidx_isld_src_prev = pidx_src_prev;
1857 int last_valid_pidx_isld_src = -1;
1859 for (
int i = as_solution.
steps - 1;
i--;) {
1863 pidx_isld_src = as_solution.
prev_nodes[pidx_isld_src];
1867 last_valid_pidx_isld_src = pidx_isld_src;
1870 if (last_valid_pidx_isld_src != -1) {
1876 const int vert_dst = corner_verts_dst[lidx_dst];
1877 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1881 if (space_transform) {
1885 pidx_src = (use_islands ? best_island->
indices[last_valid_pidx_isld_src] :
1886 last_valid_pidx_isld_src);
1889 if (face_to_corner_tri_map_src ==
nullptr) {
1891 &face_to_corner_tri_map_src_buff,
1893 tri_faces_src.
data(),
1894 int(tri_faces_src.
size()));
1897 for (j = face_to_corner_tri_map_src[pidx_src].
count; j--;) {
1900 corner_tris_src[face_to_corner_tri_map_src[pidx_src].
indices[j]];
1905 positions_src[corner_verts_src[tri[0]]],
1906 positions_src[corner_verts_src[tri[1]]],
1907 positions_src[corner_verts_src[tri[2]]]);
1909 if (dist_sq < best_dist_sq) {
1911 best_dist_sq = dist_sq;
1929 &best_loop_index_src);
1936 &best_loop_index_src,
1961 pidx_src_prev = pidx_src;
1968 r_map, lidx_dst,
FLT_MAX, best_island_index, 0,
nullptr,
nullptr);
1977 for (tindex = 0; tindex < num_trees; tindex++) {
1979 if (isld_steps_src) {
1985 if (isld_steps_src) {
1990 if (face_to_corner_tri_map_src) {
1993 if (face_to_corner_tri_map_src_buff) {
1994 MEM_freeN(face_to_corner_tri_map_src_buff);
1999 if (indices_interp) {
2002 if (weights_interp) {
2010 const float max_dist,
2011 const float ray_radius,
2012 const Mesh *mesh_dst,
2013 const float (*vert_positions_dst)[3],
2014 const int numverts_dst,
2015 const int *corner_verts_dst,
2020 const float full_weight = 1.0f;
2021 const float max_dist_sq = max_dist * max_dist;
2028 face_normals_dst = mesh_dst->face_normals();
2036 const int index = int(
i);
2054 {
reinterpret_cast<const blender::float3 *
>(vert_positions_dst), numverts_dst},
2055 {&corner_verts_dst[face.
start()], face.
size()});
2058 if (space_transform) {
2064 const int face_index = tri_faces[nearest.
index];
2078 {
reinterpret_cast<const blender::float3 *
>(vert_positions_dst), numverts_dst},
2079 {&corner_verts_dst[face.
start()], face.
size()});
2083 if (space_transform) {
2089 &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
2091 const int face_index = tri_faces[rayhit.
index];
2106 const size_t numfaces_src = size_t(me_src->
faces_num);
2123 int tot_rays, done_rays = 0;
2124 float face_area_2d_inv, done_area = 0.0f;
2127 float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
2128 float faces_dst_2d_min[2], faces_dst_2d_max[2], faces_dst_2d_z;
2129 float faces_dst_2d_size[2];
2131 float totweights = 0.0f;
2132 float hit_dist_accum = 0.0f;
2133 int sources_num = 0;
2134 const int tris_num = int(face.
size()) - 2;
2138 {
reinterpret_cast<const blender::float3 *
>(vert_positions_dst), numverts_dst},
2139 {&corner_verts_dst[face.
start()], face.
size()});
2144 if (space_transform) {
2149 copy_vn_fl(weights,
int(numfaces_src), 0.0f);
2152 tmp_face_size = size_t(face.
size());
2153 face_vcos_2d =
static_cast<float(*)[2]
>(
2154 MEM_reallocN(face_vcos_2d,
sizeof(*face_vcos_2d) * tmp_face_size));
2155 tri_vidx_2d =
static_cast<int(*)[3]
>(
2156 MEM_reallocN(tri_vidx_2d,
sizeof(*tri_vidx_2d) * (tmp_face_size - 2)));
2163 faces_dst_2d_z = pcent_dst[2];
2168 for (j = 0; j < face.
size(); j++) {
2169 const int vert = corner_verts_dst[face[j]];
2170 copy_v3_v3(tmp_co, vert_positions_dst[vert]);
2171 if (space_transform) {
2174 mul_v2_m3v3(face_vcos_2d[j], to_pnor_2d_mat, tmp_co);
2175 minmax_v2v2_v2(faces_dst_2d_min, faces_dst_2d_max, face_vcos_2d[j]);
2180 sub_v2_v2v2(faces_dst_2d_size, faces_dst_2d_max, faces_dst_2d_min);
2183 tot_rays = int((
max_ff(faces_dst_2d_size[0], faces_dst_2d_size[1]) / ray_radius) + 0.5f);
2190 tot_rays *= tot_rays;
2194 face_area_2d_inv = 1.0f /
max_ff(face_area_2d_inv, 1e-9f);
2197 if (face.
size() == 3) {
2198 tri_vidx_2d[0][0] = 0;
2199 tri_vidx_2d[0][1] = 1;
2200 tri_vidx_2d[0][2] = 2;
2202 if (face.
size() == 4) {
2203 tri_vidx_2d[0][0] = 0;
2204 tri_vidx_2d[0][1] = 1;
2205 tri_vidx_2d[0][2] = 2;
2206 tri_vidx_2d[1][0] = 0;
2207 tri_vidx_2d[1][1] = 2;
2208 tri_vidx_2d[1][2] = 3;
2214 for (j = 0; j < tris_num; j++) {
2215 float *v1 = face_vcos_2d[tri_vidx_2d[j][0]];
2216 float *
v2 = face_vcos_2d[tri_vidx_2d[j][1]];
2217 float *v3 = face_vcos_2d[tri_vidx_2d[j][2]];
2223 rays_num =
max_ii(
int(
float(tot_rays) * done_area * face_area_2d_inv + 0.5f) - done_rays,
2225 done_rays += rays_num;
2227 while (rays_num--) {
2233 tmp_co[2] = faces_dst_2d_z;
2239 &treedata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
2241 const int face_index = tri_faces[rayhit.
index];
2242 weights[face_index] +=
w;
2244 hit_dist_accum += hit_dist;
2253 if (totweights > 0.0f) {
2254 for (j = 0; j < int(numfaces_src); j++) {
2259 weights[sources_num] = weights[j] / totweights;
2264 r_map,
int(
i), hit_dist_accum / totweights, 0, sources_num,
indices, weights);
2279 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh face mapping mode (%d)!", mode);
2280 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(faces_dst.
size()));
2285#undef MREMAP_RAYCAST_APPROXIMATE_NR
2286#undef MREMAP_RAYCAST_APPROXIMATE_FAC
2287#undef MREMAP_RAYCAST_TRI_SAMPLES_MIN
2288#undef MREMAP_RAYCAST_TRI_SAMPLES_MAX
2289#undef MREMAP_DEFAULT_BUFSIZE
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool(*)(const float(*vert_positions)[3], int totvert, const blender::int2 *edges, int totedge, const bool *uv_seams, blender::OffsetIndices< int > faces, const int *corner_verts, const int *corner_edges, int corners_num, 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.
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)
IndexRange index_range() const
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define MEM_reallocN(vmemh, len)
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)
#define MREMAP_RAYCAST_TRI_SAMPLES_MIN
#define MREMAP_RAYCAST_TRI_SAMPLES_MAX
static void mesh_calc_eigen_matrix(const float(*positions)[3], const float(*vcos)[3], const int numverts, float r_mat[4][4])
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 float(*vert_positions_dst)[3], const int numverts_dst, const int *corner_verts_dst, const int numloops_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)
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_free(MeshPairRemap *map)
#define MREMAP_RAYCAST_APPROXIMATE_NR
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)
#define MREMAP_RAYCAST_APPROXIMATE_FAC
void BKE_mesh_remap_find_best_match_from_mesh(const float(*vert_positions_dst)[3], const int numverts_dst, const Mesh *me_src, SpaceTransform *r_space_transform)
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)
void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius, const float(*vert_positions_dst)[3], const int numverts_dst, const blender::int2 *edges_dst, const int numedges_dst, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map)
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 float(*vert_positions_dst)[3], const int numverts_dst, const int *corner_verts_dst, const blender::OffsetIndices< int > faces_dst, const Mesh *me_src, MeshPairRemap *r_map)
void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num)
float BKE_mesh_remap_calc_difference_from_mesh(const SpaceTransform *space_transform, const float(*vert_positions_dst)[3], const int numverts_dst, const Mesh *me_src)
void BKE_mesh_remap_calc_verts_from_mesh(const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius, const float(*vert_positions_dst)[3], const int numverts_dst, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map)
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