48 const float max_dist_sq,
52 if (nearest->index != -1) {
54 if (nearest->dist_sq > max_dist_sq) {
56 nearest->dist_sq = max_dist_sq;
61 nearest->dist_sq = max_dist_sq;
66 if ((nearest->index != -1) && (nearest->dist_sq <= max_dist_sq)) {
67 *r_hit_dist =
sqrtf(nearest->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,
130 for (i = 0; i < numverts_dst; i++) {
136 if (space_transform) {
141 result += 1.0f / (hit_dist + 1.0f);
152 printf(
"%s: Computed difference between meshes (the lower the better): %f\n", __func__, result);
171 const float (*vcos)[3],
175 float center[3], covmat[3][3];
176 float eigen_val[3], eigen_vec[3][3];
183 cos =
static_cast<float(*)[3]
>(
MEM_mallocN(
sizeof(*
cos) *
size_t(numverts), __func__));
184 memcpy(
cos, positions,
sizeof(
float[3]) *
size_t(numverts));
189 vcos =
static_cast<const float(*)[3]
>((
void *)
cos);
229 for (i = 0; i < 3; i++) {
230 float evi = eigen_val[i];
237 evi = (evi < 1e-6f && evi > -1e-6f) ? ((evi < 0.0f) ? -1e-3f : 1e-3f) :
sqrtf_signed(evi);
246 const int numverts_dst,
252 const float mirrors[][3] = {
262 const float(*mirr)[3];
264 float mat_src[4][4], mat_dst[4][4], best_mat_dst[4][4];
265 float best_match =
FLT_MAX, match;
267 const int numverts_src = me_src->
verts_num;
270 nullptr,
reinterpret_cast<const float(*)[3]
>(positions_src.
data()), numverts_src, mat_src);
275 r_space_transform, vert_positions_dst, numverts_dst, me_src);
280 for (mirr = mirrors; (*mirr)[0]; mirr++) {
287 r_space_transform, vert_positions_dst, numverts_dst, me_src);
288 if (match < best_match) {
311 map->items_num = items_num;
323 map->items =
nullptr;
331 const int sources_num,
332 const int *indices_src,
333 const float *weights_src)
364 const float point[3],
367 const bool use_loops,
370 const bool do_weights,
371 int *r_closest_index)
376 const int sources_num =
int(face.size());
379 if (
size_t(sources_num) > *buff_size) {
380 *buff_size = size_t(sources_num);
381 *vcos =
static_cast<float(*)[3]
>(
MEM_reallocN(*vcos,
sizeof(**vcos) * *buff_size));
382 *indices =
static_cast<int *
>(
MEM_reallocN(*indices,
sizeof(**indices) * *buff_size));
384 *weights =
static_cast<float *
>(
MEM_reallocN(*weights,
sizeof(**weights) * *buff_size));
388 for (i = 0, vco = *vcos, index = *indices; i < sources_num; i++, vco++, index++) {
389 const int vert = corner_verts[face[i]];
390 *index = use_loops ?
int(face[i]) : vert;
392 if (r_closest_index) {
395 if (dist_sq < ref_dist_sq) {
396 ref_dist_sq = dist_sq;
397 *r_closest_index = *index;
438#define MREMAP_RAYCAST_APPROXIMATE_NR 3
440#define MREMAP_RAYCAST_APPROXIMATE_FAC 5.0f
443#define MREMAP_RAYCAST_TRI_SAMPLES_MIN 4
444#define MREMAP_RAYCAST_TRI_SAMPLES_MAX 20
447#define MREMAP_DEFAULT_BUFSIZE 32
451 const float max_dist,
452 const float ray_radius,
453 const float (*vert_positions_dst)[3],
454 const int numverts_dst,
459 const float full_weight = 1.0f;
460 const float max_dist_sq = max_dist * max_dist;
469 for (i = 0; i < numverts_dst; i++) {
478 float tmp_co[3], tmp_no[3];
484 for (i = 0; i < numverts_dst; i++) {
488 if (space_transform) {
509 for (i = 0; i < numverts_dst; i++) {
513 if (space_transform) {
520 const float *v1cos = positions_src[edge[0]];
521 const float *v2cos = positions_src[edge[1]];
526 const int index = (dist_v1 > dist_v2) ? edge[1] : edge[0];
533 indices[0] = edge[0];
534 indices[1] = edge[1];
538 CLAMP(weights[0], 0.0f, 1.0f);
539 weights[1] = 1.0f - weights[0];
562 float(*vcos)[3] =
static_cast<float(*)[3]
>(
563 MEM_mallocN(
sizeof(*vcos) * tmp_buff_size, __func__));
564 int *indices =
static_cast<int *
>(
MEM_mallocN(
sizeof(*indices) * tmp_buff_size, __func__));
565 float *weights =
static_cast<float *
>(
566 MEM_mallocN(
sizeof(*weights) * tmp_buff_size, __func__));
571 for (i = 0; i < numverts_dst; i++) {
576 if (space_transform) {
582 &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
584 const int face_index = tri_faces[rayhit.
index];
608 for (i = 0; i < numverts_dst; i++) {
612 if (space_transform) {
617 &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
619 const int face_index = tri_faces[nearest.index];
665 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh vertex mapping mode (%d)!", mode);
666 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(numverts_dst));
675 const float max_dist,
676 const float ray_radius,
677 const float (*vert_positions_dst)[3],
678 const int numverts_dst,
680 const int numedges_dst,
686 const float full_weight = 1.0f;
687 const float max_dist_sq = max_dist * max_dist;
696 for (i = 0; i < numedges_dst; i++) {
705 float tmp_co[3], tmp_no[3];
708 const int num_verts_src = me_src->
verts_num;
716 HitData *v_dst_to_src_map =
static_cast<HitData *
>(
717 MEM_mallocN(
sizeof(*v_dst_to_src_map) *
size_t(numverts_dst), __func__));
719 for (i = 0; i < numverts_dst; i++) {
720 v_dst_to_src_map[i].hit_dist = -1.0f;
725 const GroupedSpan<int> vert_to_edge_src_map = bke::mesh::build_vert_to_edge_map(
726 edges_src, num_verts_src, vert_to_edge_src_offsets, vert_to_edge_src_indices);
731 for (i = 0; i < numedges_dst; i++) {
734 int best_eidx_src = -1;
738 const int vidx_dst = j ? e_dst[0] : e_dst[1];
741 if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
742 copy_v3_v3(tmp_co, vert_positions_dst[vidx_dst]);
745 if (space_transform) {
750 &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist))
752 v_dst_to_src_map[vidx_dst].hit_dist = hit_dist;
753 v_dst_to_src_map[vidx_dst].index = nearest.index;
757 v_dst_to_src_map[vidx_dst].hit_dist =
FLT_MAX;
765 const int vidx_dst = j ? e_dst[0] : e_dst[1];
766 const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist;
767 const int vidx_src = v_dst_to_src_map[vidx_dst].index;
775 eidx_src = vert_to_edge_src_map[vidx_src].
data();
776 k =
int(vert_to_edge_src_map[vidx_src].
size());
778 for (; k--; eidx_src++) {
780 const float *other_co_src =
782 const float *other_co_dst =
784 const float totdist = first_dist +
len_v3v3(other_co_src, other_co_dst);
786 if (totdist < best_totdist) {
787 best_totdist = totdist;
788 best_eidx_src = *eidx_src;
793 if (best_eidx_src >= 0) {
794 const float *co1_src = positions_src[edges_src[best_eidx_src][0]];
795 const float *co2_src = positions_src[edges_src[best_eidx_src][1]];
796 const float *co1_dst = vert_positions_dst[e_dst[0]];
797 const float *co2_dst = vert_positions_dst[e_dst[1]];
798 float co_src[3], co_dst[3];
802 co1_src, co2_src, co1_dst, co2_dst, co_src, co_dst);
803 if (isect_type != 0) {
806 if (fac_src < 0.0f) {
809 else if (fac_src > 1.0f) {
812 if (fac_dst < 0.0f) {
815 else if (fac_dst > 1.0f) {
819 hit_dist =
len_v3v3(co_dst, co_src);
834 for (i = 0; i < numedges_dst; i++) {
836 vert_positions_dst[edges_dst[i][0]],
837 vert_positions_dst[edges_dst[i][1]],
841 if (space_transform) {
864 for (i = 0; i < numedges_dst; i++) {
866 vert_positions_dst[edges_dst[i][0]],
867 vert_positions_dst[edges_dst[i][1]],
871 if (space_transform) {
877 const int face_index = tri_faces[nearest.index];
879 const int *corner_edge_src = &corner_edges_src[face_src.
start()];
880 int nloops =
int(face_src.
size());
882 int best_eidx_src = -1;
884 for (; nloops--; corner_edge_src++) {
886 const float *co1_src = positions_src[edge_src[0]];
887 const float *co2_src = positions_src[edge_src[1]];
893 if (dist_sq < best_dist_sq) {
894 best_dist_sq = dist_sq;
895 best_eidx_src = *corner_edge_src;
898 if (best_eidx_src >= 0) {
909 const int num_rays_min = 5, num_rays_max = 100;
910 const int numedges_src = me_src->
edges_num;
913 int *indices =
static_cast<int *
>(
914 MEM_mallocN(
sizeof(*indices) *
size_t(
min_ii(numedges_src, num_rays_max)), __func__));
916 float *weights =
static_cast<float *
>(
917 MEM_mallocN(
sizeof(*weights) *
size_t(numedges_src), __func__));
923 for (i = 0; i < numedges_dst; i++) {
927 float v1_co[3], v2_co[3];
928 float v1_no[3], v2_no[3];
934 float totweights = 0.0f;
935 float hit_dist_accum = 0.0f;
939 copy_v3_v3(v1_co, vert_positions_dst[edge[0]]);
940 copy_v3_v3(v2_co, vert_positions_dst[edge[1]]);
946 if (space_transform) {
957 edge_dst_len =
len_v3v3(v1_co, v2_co);
959 grid_size =
int((edge_dst_len / ray_radius) + 0.5f);
960 CLAMP(grid_size, num_rays_min, num_rays_max);
963 grid_step = 1.0f /
float(grid_size);
966 for (j = 0; j < grid_size; j++) {
967 const float fac = grid_step *
float(j);
977 &treedata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
979 weights[rayhit.
index] +=
w;
981 hit_dist_accum += hit_dist;
990 if (totweights > (
float(grid_size) / 2.0f)) {
991 for (j = 0; j <
int(numedges_src); j++) {
996 weights[sources_num] = weights[j] / totweights;
997 indices[sources_num] = j;
1001 r_map, i, hit_dist_accum / totweights, 0, sources_num, indices, weights);
1013 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh edge mapping mode (%d)!", mode);
1014 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(numedges_dst));
1022#define POLY_CENTER_INIT 1
1023#define POLY_COMPLETE 2
1027 const int island_index,
1035 const bool is_edge_innercut,
1036 const int *face_island_index_map,
1037 float (*face_centers)[3],
1043 for (i = 0; i < edge_to_face_map[edge_idx].
size(); i++) {
1044 const int pidx = edge_to_face_map[edge_idx][i];
1046 const int pidx_isld = islands ? face_island_index_map[pidx] : pidx;
1049 if (
UNLIKELY(islands && (islands->items_to_islands[face.start()] != island_index))) {
1051 face_island_indices[i] = -1;
1056 face_island_indices[i] = pidx_isld;
1069 const int pidx_isld_other = face_island_indices[j];
1071 if (pidx_isld_other == -1 || face_status[pidx_isld_other] ==
POLY_COMPLETE) {
1075 dist_cost =
len_v3v3(face_centers[pidx_isld_other], face_centers[pidx_isld]);
1079 face_island_indices[i] = pidx_isld;
1086 const int island_index,
1095 MeshElemMap *island_face_map = islands ? islands->islands[island_index] :
nullptr;
1096 MeshElemMap *island_einnercut_map = islands ? islands->innercuts[island_index] :
nullptr;
1098 int *face_island_index_map =
nullptr;
1101 const int node_num = islands ? island_face_map->
count :
int(faces.size());
1103 MEM_callocN(
sizeof(*face_status) *
size_t(node_num), __func__));
1104 float(*face_centers)[3];
1111 face_centers =
static_cast<float(*)[3]
>(
1117 r_as_graph->
mem,
sizeof(*face_island_index_map) *
size_t(faces.size())));
1118 for (i = island_face_map->
count; i--;) {
1119 face_island_index_map[island_face_map->
indices[i]] = i;
1124 for (i = island_einnercut_map->
count; i--;) {
1131 island_einnercut_map->
indices[i],
1135 face_island_index_map,
1141 for (pidx_isld = node_num; pidx_isld--;) {
1142 const int pidx = islands ? island_face_map->
indices[pidx_isld] : pidx_isld;
1148 for (
const int edge : corner_edges.
slice(faces[pidx])) {
1163 face_island_index_map,
1175#undef POLY_CENTER_INIT
1184 const int node_idx_curr,
1185 const int node_idx_next,
1186 const int node_idx_dst)
1188 float *co_next, *co_dest;
1204 return (link ? (as_solution->
g_costs[node_idx_curr] + link->
cost) : 0.0f) +
1208#define ASTAR_STEPS_MAX 64
1212 const float max_dist,
1213 const float ray_radius,
1214 const Mesh *mesh_dst,
1215 const float (*vert_positions_dst)[3],
1216 const int numverts_dst,
1217 const int *corner_verts_dst,
1218 const int numloops_dst,
1222 const float islands_precision_src,
1226 const float full_weight = 1.0f;
1227 const float max_dist_sq = max_dist * max_dist;
1230 BLI_assert((islands_precision_src >= 0.0f) && (islands_precision_src <= 1.0f));
1237 for (
int i = 0; i < numloops_dst; i++) {
1247 float tmp_co[3], tmp_no[3];
1252 bool use_islands =
false;
1256 const int isld_steps_src = (islands_precision_src ?
1276 MeshElemMap *face_to_corner_tri_map_src =
nullptr;
1277 int *face_to_corner_tri_map_src_buff =
nullptr;
1283 const int num_verts_src = me_src->
verts_num;
1292 float(*vcos_interp)[3] =
nullptr;
1293 int *indices_interp =
nullptr;
1294 float *weights_interp =
nullptr;
1296 int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
1301 if (!use_from_vert) {
1302 vcos_interp =
static_cast<float(*)[3]
>(
1303 MEM_mallocN(
sizeof(*vcos_interp) * buff_size_interp, __func__));
1304 indices_interp =
static_cast<int *
>(
1305 MEM_mallocN(
sizeof(*indices_interp) * buff_size_interp, __func__));
1306 weights_interp =
static_cast<float *
>(
1307 MEM_mallocN(
sizeof(*weights_interp) * buff_size_interp, __func__));
1313 const bool need_pnors_src = need_lnors_src ||
1315 const bool need_pnors_dst = need_lnors_dst || need_pnors_src;
1317 if (need_pnors_dst) {
1318 face_normals_dst = mesh_dst->face_normals();
1320 if (need_lnors_dst) {
1321 loop_normals_dst = mesh_dst->corner_normals();
1323 if (need_pnors_src) {
1324 face_normals_src = me_src->face_normals();
1326 if (need_lnors_src) {
1327 loop_normals_src = me_src->corner_normals();
1331 if (use_from_vert) {
1332 vert_to_loop_map_src = me_src->vert_to_corner_map();
1334 vert_to_face_map_src = me_src->vert_to_face_map();
1339 edge_to_face_map_src = bke::mesh::build_edge_to_face_map(faces_src,
1341 int(edges_src.
size()),
1342 edge_to_face_src_offsets,
1343 edge_to_face_src_indices);
1345 if (use_from_vert) {
1346 loop_to_face_map_src = me_src->corner_to_face_map();
1350 positions_src, corner_verts_src.
slice(faces_src[i]));
1362 if (gen_islands_src) {
1363 const bool *uv_seams =
static_cast<const bool *
>(
1365 use_islands = gen_islands_src(
reinterpret_cast<const float(*)[3]
>(positions_src.
data()),
1368 int(edges_src.
size()),
1371 corner_verts_src.
data(),
1372 corner_edges_src.
data(),
1373 int(corner_verts_src.
size()),
1376 num_trees = use_islands ? island_store.
islands_num : 1;
1378 MEM_callocN(
sizeof(*treedata) *
size_t(num_trees), __func__));
1379 if (isld_steps_src) {
1381 MEM_callocN(
sizeof(*as_graphdata) *
size_t(num_trees), __func__));
1396 if (isld_steps_src) {
1402 if (isld_steps_src) {
1403 for (tindex = 0; tindex < num_trees; tindex++) {
1407 edge_to_face_map_src,
1412 &as_graphdata[tindex]);
1417 if (use_from_vert) {
1421 for (tindex = 0; tindex < num_trees; tindex++) {
1423 int num_verts_active = 0;
1424 verts_active.
fill(
false);
1425 for (
int i = 0; i < isld->
count; i++) {
1426 for (
const int vidx_src : corner_verts_src.
slice(faces_src[isld->
indices[i]])) {
1427 if (!verts_active[vidx_src]) {
1428 verts_active[vidx_src].set();
1434 &treedata[tindex], positions_src, verts_active, num_verts_active, 0.0, 2, 6);
1444 corner_tris_src = me_src->corner_tris();
1445 tri_faces_src = me_src->corner_tri_faces();
1448 for (tindex = 0; tindex < num_trees; tindex++) {
1449 int corner_tris_num_active = 0;
1450 corner_tris_active.
fill(
false);
1454 corner_tris_active[i].set();
1455 corner_tris_num_active++;
1463 corner_tris_num_active,
1477 MEM_mallocN(
sizeof(*islands_res) *
size_t(num_trees), __func__));
1478 for (tindex = 0; tindex < num_trees; tindex++) {
1480 MEM_mallocN(
sizeof(**islands_res) * islands_res_buff_size, __func__));
1484 for (pidx_dst = 0; pidx_dst < faces_dst.
size(); pidx_dst++) {
1491 bool pcent_dst_valid =
false;
1494 copy_v3_v3(pnor_dst, face_normals_dst[pidx_dst]);
1495 if (space_transform) {
1500 if (
size_t(face_dst.
size()) > islands_res_buff_size) {
1502 for (tindex = 0; tindex < num_trees; tindex++) {
1504 MEM_reallocN(islands_res[tindex],
sizeof(**islands_res) * islands_res_buff_size));
1508 for (tindex = 0; tindex < num_trees; tindex++) {
1511 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1512 const int vert_dst = corner_verts_dst[face_dst.
start() + plidx_dst];
1513 if (use_from_vert) {
1516 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1520 if (space_transform) {
1528 float best_nor_dot = -2.0f;
1529 float best_sqdist_fallback =
FLT_MAX;
1530 int best_index_src = -1;
1534 if (space_transform) {
1538 nors_src = loop_normals_src;
1539 vert_to_refelem_map_src = vert_to_loop_map_src[nearest.index];
1542 nor_dst = &pnor_dst;
1543 nors_src = face_normals_src;
1544 vert_to_refelem_map_src = vert_to_face_map_src[nearest.index];
1547 for (
const int index_src : vert_to_refelem_map_src) {
1549 const float dot =
dot_v3v3(nors_src[index_src], *nor_dst);
1552 loop_to_face_map_src[index_src] :
1559 int(faces_src[pidx_src].start()));
1567 if (
dot > best_nor_dot - 1e-6f) {
1573 if (!pcent_dst_valid) {
1578 pcent_dst_valid =
true;
1580 pcent_src = face_cents_src[pidx_src];
1583 if ((
dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) {
1585 best_sqdist_fallback = sqdist;
1586 best_index_src = index_src;
1590 if (best_index_src == -1) {
1592 best_nor_dot = -1.0f;
1599 for (plidx_src = 0; plidx_src < face_src.
size(); plidx_src++) {
1600 const int vert_src = corner_verts_src[face_src.
start() + plidx_src];
1601 if (vert_src == nearest.index) {
1602 best_index_src = plidx_src +
int(face_src.
start());
1607 best_nor_dot = (best_nor_dot + 1.0f) * 0.5f;
1608 islands_res[tindex][plidx_dst].
factor = hit_dist ? (best_nor_dot / hit_dist) : 1e18f;
1609 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1610 islands_res[tindex][plidx_dst].
index_src = best_index_src;
1614 islands_res[tindex][plidx_dst].
factor = 0.0f;
1616 islands_res[tindex][plidx_dst].
index_src = -1;
1623 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1627 if (space_transform) {
1634 tdata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
1636 islands_res[tindex][plidx_dst].
factor = (hit_dist ? (1.0f / hit_dist) : 1e18f) *
w;
1637 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1638 islands_res[tindex][plidx_dst].
index_src = tri_faces[rayhit.
index];
1639 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, rayhit.
co);
1652 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1656 if (space_transform) {
1662 islands_res[tindex][plidx_dst].
factor = 0.0f;
1665 tdata, &nearest, tmp_co, max_dist_sq, &hit_dist))
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);
1674 islands_res[tindex][plidx_dst].
index_src = -1;
1679 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1683 if (space_transform) {
1689 islands_res[tindex][plidx_dst].
factor = hit_dist ? (1.0f / hit_dist) : 1e18f;
1690 islands_res[tindex][plidx_dst].
hit_dist = hit_dist;
1691 islands_res[tindex][plidx_dst].
index_src = tri_faces[nearest.index];
1692 copy_v3_v3(islands_res[tindex][plidx_dst].hit_point, nearest.co);
1696 islands_res[tindex][plidx_dst].
factor = 0.0f;
1698 islands_res[tindex][plidx_dst].
index_src = -1;
1718 int *face_island_index_map =
nullptr;
1719 int pidx_src_prev = -1;
1722 float best_island_fac = 0.0f;
1723 int best_island_index = -1;
1725 for (tindex = 0; tindex < num_trees; tindex++) {
1726 float island_fac = 0.0f;
1728 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1729 island_fac += islands_res[tindex][plidx_dst].
factor;
1733 if (island_fac > best_island_fac) {
1734 best_island_fac = island_fac;
1735 best_island_index = tindex;
1739 if (best_island_index != -1 && isld_steps_src) {
1740 best_island = use_islands ? island_store.
islands[best_island_index] :
nullptr;
1741 as_graph = &as_graphdata[best_island_index];
1742 face_island_index_map = (
int *)as_graph->
custom_data;
1746 for (plidx_dst = 0; plidx_dst < face_dst.
size(); plidx_dst++) {
1748 lidx_dst = plidx_dst +
int(face_dst.
start());
1750 if (best_island_index == -1) {
1758 isld_res = &islands_res[best_island_index][plidx_dst];
1759 if (use_from_vert) {
1762 if (lidx_src >= 0) {
1763 pidx_src = loop_to_face_map_src[lidx_src];
1765 if (!
ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1766 int pidx_isld_src, pidx_isld_src_prev;
1767 if (face_island_index_map) {
1768 pidx_isld_src = face_island_index_map[pidx_src];
1769 pidx_isld_src_prev = face_island_index_map[pidx_src_prev];
1772 pidx_isld_src = pidx_src;
1773 pidx_isld_src_prev = pidx_src_prev;
1790 int last_valid_pidx_isld_src = -1;
1792 for (
int i = as_solution.
steps - 1; i--;) {
1795 pidx_isld_src = as_solution.
prev_nodes[pidx_isld_src];
1799 last_valid_pidx_isld_src = pidx_isld_src;
1802 if (last_valid_pidx_isld_src != -1) {
1807 copy_v3_v3(tmp_co, vert_positions_dst[corner_verts_dst[lidx_dst]]);
1811 if (space_transform) {
1815 pidx_src = (use_islands ? best_island->
indices[last_valid_pidx_isld_src] :
1816 last_valid_pidx_isld_src);
1818 for (
const int64_t corner : face_src) {
1819 const int vert_src = corner_verts_src[corner];
1821 if (dist_sq < best_dist_sq) {
1822 best_dist_sq = dist_sq;
1823 lidx_src =
int(corner);
1836 pidx_src_prev = pidx_src;
1843 r_map, lidx_dst,
FLT_MAX, best_island_index, 0,
nullptr,
nullptr);
1849 if (pidx_src >= 0) {
1851 int best_loop_index_src;
1855 if (!
ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
1856 int pidx_isld_src, pidx_isld_src_prev;
1857 if (face_island_index_map) {
1858 pidx_isld_src = face_island_index_map[pidx_src];
1859 pidx_isld_src_prev = face_island_index_map[pidx_src_prev];
1862 pidx_isld_src = pidx_src;
1863 pidx_isld_src_prev = pidx_src_prev;
1880 int last_valid_pidx_isld_src = -1;
1882 for (
int i = as_solution.
steps - 1; i--;) {
1886 pidx_isld_src = as_solution.
prev_nodes[pidx_isld_src];
1890 last_valid_pidx_isld_src = pidx_isld_src;
1893 if (last_valid_pidx_isld_src != -1) {
1899 const int vert_dst = corner_verts_dst[lidx_dst];
1900 copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]);
1904 if (space_transform) {
1908 pidx_src = (use_islands ? best_island->
indices[last_valid_pidx_isld_src] :
1909 last_valid_pidx_isld_src);
1912 if (face_to_corner_tri_map_src ==
nullptr) {
1914 &face_to_corner_tri_map_src_buff,
1916 tri_faces_src.
data(),
1917 int(tri_faces_src.
size()));
1920 for (j = face_to_corner_tri_map_src[pidx_src].
count; j--;) {
1923 corner_tris_src[face_to_corner_tri_map_src[pidx_src].
indices[j]];
1928 positions_src[corner_verts_src[tri[0]]],
1929 positions_src[corner_verts_src[tri[1]]],
1930 positions_src[corner_verts_src[tri[2]]]);
1932 if (dist_sq < best_dist_sq) {
1934 best_dist_sq = dist_sq;
1952 &best_loop_index_src);
1959 &best_loop_index_src,
1984 pidx_src_prev = pidx_src;
1991 r_map, lidx_dst,
FLT_MAX, best_island_index, 0,
nullptr,
nullptr);
2000 for (tindex = 0; tindex < num_trees; tindex++) {
2003 if (isld_steps_src) {
2010 if (isld_steps_src) {
2015 if (face_to_corner_tri_map_src) {
2018 if (face_to_corner_tri_map_src_buff) {
2019 MEM_freeN(face_to_corner_tri_map_src_buff);
2024 if (indices_interp) {
2027 if (weights_interp) {
2035 const float max_dist,
2036 const float ray_radius,
2037 const Mesh *mesh_dst,
2038 const float (*vert_positions_dst)[3],
2039 const int numverts_dst,
2040 const int *corner_verts_dst,
2045 const float full_weight = 1.0f;
2046 const float max_dist_sq = max_dist * max_dist;
2053 face_normals_dst = mesh_dst->face_normals();
2061 const int index =
int(i);
2080 {
reinterpret_cast<const blender::float3 *
>(vert_positions_dst), numverts_dst},
2081 {&corner_verts_dst[face.start()], face.size()});
2084 if (space_transform) {
2090 const int face_index = tri_faces[nearest.index];
2104 {
reinterpret_cast<const blender::float3 *
>(vert_positions_dst), numverts_dst},
2105 {&corner_verts_dst[face.start()], face.size()});
2109 if (space_transform) {
2115 &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist))
2117 const int face_index = tri_faces[rayhit.
index];
2132 const size_t numfaces_src = size_t(me_src->
faces_num);
2135 int *indices =
static_cast<int *
>(
MEM_mallocN(
sizeof(*indices) * numfaces_src, __func__));
2136 float *weights =
static_cast<float *
>(
2137 MEM_mallocN(
sizeof(*weights) * numfaces_src, __func__));
2140 float(*face_vcos_2d)[2] =
static_cast<float(*)[2]
>(
2141 MEM_mallocN(
sizeof(*face_vcos_2d) * tmp_face_size, __func__));
2143 int(*tri_vidx_2d)[3] =
static_cast<int(*)[3]
>(
2144 MEM_mallocN(
sizeof(*tri_vidx_2d) * (tmp_face_size - 2), __func__));
2152 int tot_rays, done_rays = 0;
2153 float face_area_2d_inv, done_area = 0.0f;
2156 float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
2157 float faces_dst_2d_min[2], faces_dst_2d_max[2], faces_dst_2d_z;
2158 float faces_dst_2d_size[2];
2160 float totweights = 0.0f;
2161 float hit_dist_accum = 0.0f;
2162 int sources_num = 0;
2163 const int tris_num =
int(face.size()) - 2;
2167 {
reinterpret_cast<const blender::float3 *
>(vert_positions_dst), numverts_dst},
2168 {&corner_verts_dst[face.start()], face.size()});
2173 if (space_transform) {
2178 copy_vn_fl(weights,
int(numfaces_src), 0.0f);
2180 if (
UNLIKELY(
size_t(face.size()) > tmp_face_size)) {
2181 tmp_face_size = size_t(face.size());
2182 face_vcos_2d =
static_cast<float(*)[2]
>(
2183 MEM_reallocN(face_vcos_2d,
sizeof(*face_vcos_2d) * tmp_face_size));
2184 tri_vidx_2d =
static_cast<int(*)[3]
>(
2185 MEM_reallocN(tri_vidx_2d,
sizeof(*tri_vidx_2d) * (tmp_face_size - 2)));
2192 faces_dst_2d_z = pcent_dst[2];
2197 for (j = 0; j < face.size(); j++) {
2198 const int vert = corner_verts_dst[face[j]];
2199 copy_v3_v3(tmp_co, vert_positions_dst[vert]);
2200 if (space_transform) {
2203 mul_v2_m3v3(face_vcos_2d[j], to_pnor_2d_mat, tmp_co);
2204 minmax_v2v2_v2(faces_dst_2d_min, faces_dst_2d_max, face_vcos_2d[j]);
2209 sub_v2_v2v2(faces_dst_2d_size, faces_dst_2d_max, faces_dst_2d_min);
2212 tot_rays =
int((
max_ff(faces_dst_2d_size[0], faces_dst_2d_size[1]) / ray_radius) + 0.5f);
2219 tot_rays *= tot_rays;
2223 face_area_2d_inv = 1.0f /
max_ff(face_area_2d_inv, 1e-9f);
2226 if (face.size() == 3) {
2227 tri_vidx_2d[0][0] = 0;
2228 tri_vidx_2d[0][1] = 1;
2229 tri_vidx_2d[0][2] = 2;
2231 if (face.size() == 4) {
2232 tri_vidx_2d[0][0] = 0;
2233 tri_vidx_2d[0][1] = 1;
2234 tri_vidx_2d[0][2] = 2;
2235 tri_vidx_2d[1][0] = 0;
2236 tri_vidx_2d[1][1] = 2;
2237 tri_vidx_2d[1][2] = 3;
2243 for (j = 0; j < tris_num; j++) {
2244 float *v1 = face_vcos_2d[tri_vidx_2d[j][0]];
2245 float *
v2 = face_vcos_2d[tri_vidx_2d[j][1]];
2246 float *v3 = face_vcos_2d[tri_vidx_2d[j][2]];
2252 rays_num =
max_ii(
int(
float(tot_rays) * done_area * face_area_2d_inv + 0.5f) - done_rays,
2254 done_rays += rays_num;
2256 while (rays_num--) {
2262 tmp_co[2] = faces_dst_2d_z;
2268 &treedata, &rayhit, tmp_co, tmp_no, ray_radius /
w, max_dist, &hit_dist))
2270 const int face_index = tri_faces[rayhit.
index];
2271 weights[face_index] +=
w;
2273 hit_dist_accum += hit_dist;
2282 if (totweights > 0.0f) {
2283 for (j = 0; j <
int(numfaces_src); j++) {
2288 weights[sources_num] = weights[j] / totweights;
2289 indices[sources_num] = j;
2293 r_map,
int(i), hit_dist_accum / totweights, 0, sources_num, indices, weights);
2308 CLOG_WARN(&
LOG,
"Unsupported mesh-to-mesh face mapping mode (%d)!", mode);
2309 memset(r_map->
items, 0,
sizeof(*r_map->
items) *
size_t(faces_dst.
size()));
2316#undef MREMAP_RAYCAST_APPROXIMATE_NR
2317#undef MREMAP_RAYCAST_APPROXIMATE_FAC
2318#undef MREMAP_RAYCAST_TRI_SAMPLES_MIN
2319#undef MREMAP_RAYCAST_TRI_SAMPLES_MAX
2320#undef MREMAP_DEFAULT_BUFSIZE
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
BVHTree * bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, blender::Span< blender::float3 > vert_positions, blender::BitSpan verts_mask, int verts_num_active, float epsilon, int tree_type, int axis)
BVHTree * bvhtree_from_mesh_corner_tris_ex(BVHTreeFromMesh *data, blender::Span< blender::float3 > vert_positions, blender::Span< int > corner_verts, blender::Span< blender::int3 > corner_tris, blender::BitSpan corner_tris_mask, int corner_tris_num_active, float epsilon, int tree_type, int axis)
@ BVHTREE_FROM_CORNER_TRIS
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)
@ 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
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 unit_m4(float m[4][4])
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])
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])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void * BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
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 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()
#define INIT_MINMAX2(min, max)
#define POINTER_FROM_INT(i)
#define UNUSED_VARS_NDEBUG(...)
#define POINTER_AS_INT(i)
#define CLOG_WARN(clg_ref,...)
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)
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
constexpr IndexRange index_range() const
void fill(const bool value)
IndexRange index_range() const
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
ccl_device_inline float3 cos(float3 v)
#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)
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)
static bool mesh_remap_bvhtree_query_nearest(BVHTreeFromMesh *treedata, BVHTreeNearest *nearest, const float co[3], const float max_dist_sq, float *r_hit_dist)
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)
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)
float3 face_center_calc(Span< float3 > vert_positions, Span< int > face_verts)
BLI_AStarGNLink ** prev_links
BVHTree_RayCastCallback raycast_callback
BVHTree_NearestPointCallback nearest_callback
MeshPairRemapItem * items