Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_remap.cc
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index) | void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, const int index) | ||||
| { | { | ||||
| mesh_remap_item_define(map, index, FLT_MAX, 0, 0, nullptr, nullptr); | mesh_remap_item_define(map, index, FLT_MAX, 0, 0, nullptr, nullptr); | ||||
| } | } | ||||
| static int mesh_remap_interp_poly_data_get(const MPoly *mp, | static int mesh_remap_interp_poly_data_get(const MPoly *mp, | ||||
| const MLoop *mloops, | const int *corner_verts, | ||||
| const float (*vcos_src)[3], | const float (*vcos_src)[3], | ||||
| const float point[3], | const float point[3], | ||||
| size_t *buff_size, | size_t *buff_size, | ||||
| float (**vcos)[3], | float (**vcos)[3], | ||||
| const bool use_loops, | const bool use_loops, | ||||
| int **indices, | int **indices, | ||||
| float **weights, | float **weights, | ||||
| const bool do_weights, | const bool do_weights, | ||||
| int *r_closest_index) | int *r_closest_index) | ||||
| { | { | ||||
| const MLoop *ml; | |||||
| float(*vco)[3]; | float(*vco)[3]; | ||||
| float ref_dist_sq = FLT_MAX; | float ref_dist_sq = FLT_MAX; | ||||
| int *index; | int *index; | ||||
| const int sources_num = mp->totloop; | const int sources_num = mp->totloop; | ||||
| int i; | int i; | ||||
| if (size_t(sources_num) > *buff_size) { | if (size_t(sources_num) > *buff_size) { | ||||
| *buff_size = size_t(sources_num); | *buff_size = size_t(sources_num); | ||||
| *vcos = static_cast<float(*)[3]>(MEM_reallocN(*vcos, sizeof(**vcos) * *buff_size)); | *vcos = static_cast<float(*)[3]>(MEM_reallocN(*vcos, sizeof(**vcos) * *buff_size)); | ||||
| *indices = static_cast<int *>(MEM_reallocN(*indices, sizeof(**indices) * *buff_size)); | *indices = static_cast<int *>(MEM_reallocN(*indices, sizeof(**indices) * *buff_size)); | ||||
| if (do_weights) { | if (do_weights) { | ||||
| *weights = static_cast<float *>(MEM_reallocN(*weights, sizeof(**weights) * *buff_size)); | *weights = static_cast<float *>(MEM_reallocN(*weights, sizeof(**weights) * *buff_size)); | ||||
| } | } | ||||
| } | } | ||||
| for (i = 0, ml = &mloops[mp->loopstart], vco = *vcos, index = *indices; i < sources_num; | for (i = 0, vco = *vcos, index = *indices; i < sources_num; i++, vco++, index++) { | ||||
| i++, ml++, vco++, index++) { | const int vert = corner_verts[mp->loopstart + i]; | ||||
| *index = use_loops ? int(mp->loopstart) + i : int(ml->v); | *index = use_loops ? int(mp->loopstart) + i : vert; | ||||
| copy_v3_v3(*vco, vcos_src[ml->v]); | copy_v3_v3(*vco, vcos_src[vert]); | ||||
| if (r_closest_index) { | if (r_closest_index) { | ||||
| /* Find closest vert/loop in this case. */ | /* Find closest vert/loop in this case. */ | ||||
| const float dist_sq = len_squared_v3v3(point, *vco); | const float dist_sq = len_squared_v3v3(point, *vco); | ||||
| if (dist_sq < ref_dist_sq) { | if (dist_sq < ref_dist_sq) { | ||||
| ref_dist_sq = dist_sq; | ref_dist_sq = dist_sq; | ||||
| *r_closest_index = *index; | *r_closest_index = *index; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | |||||
| MEM_freeN(vcos_src); | MEM_freeN(vcos_src); | ||||
| } | } | ||||
| else if (ELEM(mode, | else if (ELEM(mode, | ||||
| MREMAP_MODE_VERT_POLY_NEAREST, | MREMAP_MODE_VERT_POLY_NEAREST, | ||||
| MREMAP_MODE_VERT_POLYINTERP_NEAREST, | MREMAP_MODE_VERT_POLYINTERP_NEAREST, | ||||
| MREMAP_MODE_VERT_POLYINTERP_VNORPROJ)) { | MREMAP_MODE_VERT_POLYINTERP_VNORPROJ)) { | ||||
| const MPoly *polys_src = BKE_mesh_polys(me_src); | const MPoly *polys_src = BKE_mesh_polys(me_src); | ||||
| const MLoop *loops_src = BKE_mesh_loops(me_src); | const blender::Span<int> corner_verts_src = me_src->corner_verts(); | ||||
| float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); | float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); | ||||
| const float(*vert_normals_dst)[3] = BKE_mesh_vertex_normals_ensure(me_dst); | const float(*vert_normals_dst)[3] = BKE_mesh_vertex_normals_ensure(me_dst); | ||||
| size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE; | size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE; | ||||
| float(*vcos)[3] = static_cast<float(*)[3]>( | float(*vcos)[3] = static_cast<float(*)[3]>( | ||||
| MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__)); | MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__)); | ||||
| int *indices = static_cast<int *>(MEM_mallocN(sizeof(*indices) * tmp_buff_size, __func__)); | int *indices = static_cast<int *>(MEM_mallocN(sizeof(*indices) * tmp_buff_size, __func__)); | ||||
| float *weights = static_cast<float *>( | float *weights = static_cast<float *>( | ||||
| Show All 12 Lines | |||||
| BLI_space_transform_apply_normal(space_transform, tmp_no); | BLI_space_transform_apply_normal(space_transform, tmp_no); | ||||
| } | } | ||||
| if (mesh_remap_bvhtree_query_raycast( | if (mesh_remap_bvhtree_query_raycast( | ||||
| &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist)) { | &treedata, &rayhit, tmp_co, tmp_no, ray_radius, max_dist, &hit_dist)) { | ||||
| const MLoopTri *lt = &treedata.looptri[rayhit.index]; | const MLoopTri *lt = &treedata.looptri[rayhit.index]; | ||||
| const MPoly *mp_src = &polys_src[lt->poly]; | const MPoly *mp_src = &polys_src[lt->poly]; | ||||
| const int sources_num = mesh_remap_interp_poly_data_get(mp_src, | const int sources_num = mesh_remap_interp_poly_data_get(mp_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| (const float(*)[3])vcos_src, | (const float(*)[3])vcos_src, | ||||
| rayhit.co, | rayhit.co, | ||||
| &tmp_buff_size, | &tmp_buff_size, | ||||
| &vcos, | &vcos, | ||||
| false, | false, | ||||
| &indices, | &indices, | ||||
| &weights, | &weights, | ||||
| true, | true, | ||||
| Show All 21 Lines | |||||
| if (mesh_remap_bvhtree_query_nearest( | if (mesh_remap_bvhtree_query_nearest( | ||||
| &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { | &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { | ||||
| const MLoopTri *lt = &treedata.looptri[nearest.index]; | const MLoopTri *lt = &treedata.looptri[nearest.index]; | ||||
| const MPoly *mp = &polys_src[lt->poly]; | const MPoly *mp = &polys_src[lt->poly]; | ||||
| if (mode == MREMAP_MODE_VERT_POLY_NEAREST) { | if (mode == MREMAP_MODE_VERT_POLY_NEAREST) { | ||||
| int index; | int index; | ||||
| mesh_remap_interp_poly_data_get(mp, | mesh_remap_interp_poly_data_get(mp, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| (const float(*)[3])vcos_src, | (const float(*)[3])vcos_src, | ||||
| nearest.co, | nearest.co, | ||||
| &tmp_buff_size, | &tmp_buff_size, | ||||
| &vcos, | &vcos, | ||||
| false, | false, | ||||
| &indices, | &indices, | ||||
| &weights, | &weights, | ||||
| false, | false, | ||||
| &index); | &index); | ||||
| mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight); | mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &index, &full_weight); | ||||
| } | } | ||||
| else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) { | else if (mode == MREMAP_MODE_VERT_POLYINTERP_NEAREST) { | ||||
| const int sources_num = mesh_remap_interp_poly_data_get(mp, | const int sources_num = mesh_remap_interp_poly_data_get(mp, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| (const float(*)[3])vcos_src, | (const float(*)[3])vcos_src, | ||||
| nearest.co, | nearest.co, | ||||
| &tmp_buff_size, | &tmp_buff_size, | ||||
| &vcos, | &vcos, | ||||
| false, | false, | ||||
| &indices, | &indices, | ||||
| &weights, | &weights, | ||||
| true, | true, | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| /* No source for this dest edge! */ | /* No source for this dest edge! */ | ||||
| BKE_mesh_remap_item_define_invalid(r_map, i); | BKE_mesh_remap_item_define_invalid(r_map, i); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) { | else if (mode == MREMAP_MODE_EDGE_POLY_NEAREST) { | ||||
| const MEdge *edges_src = BKE_mesh_edges(me_src); | const MEdge *edges_src = BKE_mesh_edges(me_src); | ||||
| const MPoly *polys_src = BKE_mesh_polys(me_src); | const MPoly *polys_src = BKE_mesh_polys(me_src); | ||||
| const MLoop *loops_src = BKE_mesh_loops(me_src); | const blender::Span<int> corner_edges_src = me_src->corner_edges(); | ||||
| float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); | float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, nullptr); | ||||
| BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); | BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); | ||||
| for (i = 0; i < numedges_dst; i++) { | for (i = 0; i < numedges_dst; i++) { | ||||
| interp_v3_v3v3(tmp_co, | interp_v3_v3v3(tmp_co, | ||||
| vert_positions_dst[edges_dst[i].v1], | vert_positions_dst[edges_dst[i].v1], | ||||
| vert_positions_dst[edges_dst[i].v2], | vert_positions_dst[edges_dst[i].v2], | ||||
| 0.5f); | 0.5f); | ||||
| /* Convert the vertex to tree coordinates, if needed. */ | /* Convert the vertex to tree coordinates, if needed. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| if (mesh_remap_bvhtree_query_nearest( | if (mesh_remap_bvhtree_query_nearest( | ||||
| &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { | &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { | ||||
| const MLoopTri *lt = &treedata.looptri[nearest.index]; | const MLoopTri *lt = &treedata.looptri[nearest.index]; | ||||
| const MPoly *mp_src = &polys_src[lt->poly]; | const MPoly *mp_src = &polys_src[lt->poly]; | ||||
| const MLoop *ml_src = &loops_src[mp_src->loopstart]; | const int *corner_edge_src = &corner_edges_src[mp_src->loopstart]; | ||||
| int nloops = mp_src->totloop; | int nloops = mp_src->totloop; | ||||
| float best_dist_sq = FLT_MAX; | float best_dist_sq = FLT_MAX; | ||||
| int best_eidx_src = -1; | int best_eidx_src = -1; | ||||
| for (; nloops--; ml_src++) { | for (; nloops--; corner_edge_src++) { | ||||
| const MEdge *med_src = &edges_src[ml_src->e]; | const MEdge *med_src = &edges_src[*corner_edge_src]; | ||||
| float *co1_src = vcos_src[med_src->v1]; | float *co1_src = vcos_src[med_src->v1]; | ||||
| float *co2_src = vcos_src[med_src->v2]; | float *co2_src = vcos_src[med_src->v2]; | ||||
| float co_src[3]; | float co_src[3]; | ||||
| float dist_sq; | float dist_sq; | ||||
| interp_v3_v3v3(co_src, co1_src, co2_src, 0.5f); | interp_v3_v3v3(co_src, co1_src, co2_src, 0.5f); | ||||
| dist_sq = len_squared_v3v3(tmp_co, co_src); | dist_sq = len_squared_v3v3(tmp_co, co_src); | ||||
| if (dist_sq < best_dist_sq) { | if (dist_sq < best_dist_sq) { | ||||
| best_dist_sq = dist_sq; | best_dist_sq = dist_sq; | ||||
| best_eidx_src = int(ml_src->e); | best_eidx_src = *corner_edge_src; | ||||
| } | } | ||||
| } | } | ||||
| if (best_eidx_src >= 0) { | if (best_eidx_src >= 0) { | ||||
| mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight); | mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &best_eidx_src, &full_weight); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* No source for this dest edge! */ | /* No source for this dest edge! */ | ||||
| ▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | |||||
| #define POLY_CENTER_INIT 1 | #define POLY_CENTER_INIT 1 | ||||
| #define POLY_COMPLETE 2 | #define POLY_COMPLETE 2 | ||||
| static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, | static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, | ||||
| const int island_index, | const int island_index, | ||||
| BLI_AStarGraph *as_graph, | BLI_AStarGraph *as_graph, | ||||
| const float (*positions)[3], | const float (*positions)[3], | ||||
| const MPoly *polys, | const MPoly *polys, | ||||
| const MLoop *loops, | const int *corner_verts, | ||||
| const int edge_idx, | const int edge_idx, | ||||
| BLI_bitmap *done_edges, | BLI_bitmap *done_edges, | ||||
| MeshElemMap *edge_to_poly_map, | MeshElemMap *edge_to_poly_map, | ||||
| const bool is_edge_innercut, | const bool is_edge_innercut, | ||||
| const int *poly_island_index_map, | const int *poly_island_index_map, | ||||
| float (*poly_centers)[3], | float (*poly_centers)[3], | ||||
| uchar *poly_status) | uchar *poly_status) | ||||
| { | { | ||||
| Show All 13 Lines | |||||
| } | } | ||||
| if (poly_status[pidx_isld] == POLY_COMPLETE) { | if (poly_status[pidx_isld] == POLY_COMPLETE) { | ||||
| poly_island_indices[i] = pidx_isld; | poly_island_indices[i] = pidx_isld; | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (poly_status[pidx_isld] == POLY_UNSET) { | if (poly_status[pidx_isld] == POLY_UNSET) { | ||||
| BKE_mesh_calc_poly_center(mp, &loops[mp->loopstart], positions, poly_centers[pidx_isld]); | BKE_mesh_calc_poly_center( | ||||
| mp, &corner_verts[mp->loopstart], positions, poly_centers[pidx_isld]); | |||||
| BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]); | BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]); | ||||
| poly_status[pidx_isld] = POLY_CENTER_INIT; | poly_status[pidx_isld] = POLY_CENTER_INIT; | ||||
| } | } | ||||
| for (j = i; j--;) { | for (j = i; j--;) { | ||||
| float dist_cost; | float dist_cost; | ||||
| const int pidx_isld_other = poly_island_indices[j]; | const int pidx_isld_other = poly_island_indices[j]; | ||||
| Show All 11 Lines | |||||
| BLI_BITMAP_ENABLE(done_edges, edge_idx); | BLI_BITMAP_ENABLE(done_edges, edge_idx); | ||||
| } | } | ||||
| static void mesh_island_to_astar_graph(MeshIslandStore *islands, | static void mesh_island_to_astar_graph(MeshIslandStore *islands, | ||||
| const int island_index, | const int island_index, | ||||
| const float (*positions)[3], | const float (*positions)[3], | ||||
| MeshElemMap *edge_to_poly_map, | MeshElemMap *edge_to_poly_map, | ||||
| const int numedges, | const int numedges, | ||||
| const MLoop *loops, | const int *corner_verts, | ||||
| const int *corner_edges, | |||||
| const MPoly *polys, | const MPoly *polys, | ||||
| const int numpolys, | const int numpolys, | ||||
| BLI_AStarGraph *r_as_graph) | BLI_AStarGraph *r_as_graph) | ||||
| { | { | ||||
| MeshElemMap *island_poly_map = islands ? islands->islands[island_index] : nullptr; | MeshElemMap *island_poly_map = islands ? islands->islands[island_index] : nullptr; | ||||
| MeshElemMap *island_einnercut_map = islands ? islands->innercuts[island_index] : nullptr; | MeshElemMap *island_einnercut_map = islands ? islands->innercuts[island_index] : nullptr; | ||||
| int *poly_island_index_map = nullptr; | int *poly_island_index_map = nullptr; | ||||
| Show All 23 Lines | |||||
| r_as_graph->custom_data = poly_island_index_map; | r_as_graph->custom_data = poly_island_index_map; | ||||
| for (i = island_einnercut_map->count; i--;) { | for (i = island_einnercut_map->count; i--;) { | ||||
| mesh_island_to_astar_graph_edge_process(islands, | mesh_island_to_astar_graph_edge_process(islands, | ||||
| island_index, | island_index, | ||||
| r_as_graph, | r_as_graph, | ||||
| positions, | positions, | ||||
| polys, | polys, | ||||
| loops, | corner_verts, | ||||
| island_einnercut_map->indices[i], | island_einnercut_map->indices[i], | ||||
| done_edges, | done_edges, | ||||
| edge_to_poly_map, | edge_to_poly_map, | ||||
| true, | true, | ||||
| poly_island_index_map, | poly_island_index_map, | ||||
| poly_centers, | poly_centers, | ||||
| poly_status); | poly_status); | ||||
| } | } | ||||
| } | } | ||||
| for (pidx_isld = node_num; pidx_isld--;) { | for (pidx_isld = node_num; pidx_isld--;) { | ||||
| const int pidx = islands ? island_poly_map->indices[pidx_isld] : pidx_isld; | const int pidx = islands ? island_poly_map->indices[pidx_isld] : pidx_isld; | ||||
| const MPoly *mp = &polys[pidx]; | const MPoly *mp = &polys[pidx]; | ||||
| int pl_idx, l_idx; | int pl_idx, l_idx; | ||||
| if (poly_status[pidx_isld] == POLY_COMPLETE) { | if (poly_status[pidx_isld] == POLY_COMPLETE) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| for (pl_idx = 0, l_idx = mp->loopstart; pl_idx < mp->totloop; pl_idx++, l_idx++) { | for (pl_idx = 0, l_idx = mp->loopstart; pl_idx < mp->totloop; pl_idx++, l_idx++) { | ||||
| const MLoop *ml = &loops[l_idx]; | const int edge = corner_edges[l_idx]; | ||||
| if (BLI_BITMAP_TEST(done_edges, ml->e)) { | if (BLI_BITMAP_TEST(done_edges, edge)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| mesh_island_to_astar_graph_edge_process(islands, | mesh_island_to_astar_graph_edge_process(islands, | ||||
| island_index, | island_index, | ||||
| r_as_graph, | r_as_graph, | ||||
| positions, | positions, | ||||
| polys, | polys, | ||||
| loops, | corner_verts, | ||||
| int(ml->e), | edge, | ||||
| done_edges, | done_edges, | ||||
| edge_to_poly_map, | edge_to_poly_map, | ||||
| false, | false, | ||||
| poly_island_index_map, | poly_island_index_map, | ||||
| poly_centers, | poly_centers, | ||||
| poly_status); | poly_status); | ||||
| } | } | ||||
| poly_status[pidx_isld] = POLY_COMPLETE; | poly_status[pidx_isld] = POLY_COMPLETE; | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
| const SpaceTransform *space_transform, | const SpaceTransform *space_transform, | ||||
| const float max_dist, | const float max_dist, | ||||
| const float ray_radius, | const float ray_radius, | ||||
| Mesh *mesh_dst, | Mesh *mesh_dst, | ||||
| const float (*vert_positions_dst)[3], | const float (*vert_positions_dst)[3], | ||||
| const int numverts_dst, | const int numverts_dst, | ||||
| const MEdge *edges_dst, | const MEdge *edges_dst, | ||||
| const int numedges_dst, | const int numedges_dst, | ||||
| const MLoop *loops_dst, | const int *corner_verts_dst, | ||||
| const int *corner_edges_dst, | |||||
| const int numloops_dst, | const int numloops_dst, | ||||
| const MPoly *polys_dst, | const MPoly *polys_dst, | ||||
| const int numpolys_dst, | const int numpolys_dst, | ||||
| CustomData *ldata_dst, | CustomData *ldata_dst, | ||||
| const bool use_split_nors_dst, | const bool use_split_nors_dst, | ||||
| const float split_angle_dst, | const float split_angle_dst, | ||||
| const bool dirty_nors_dst, | const bool dirty_nors_dst, | ||||
| Mesh *me_src, | Mesh *me_src, | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
| /* Unlike above, those are one-to-one mappings, simpler! */ | /* Unlike above, those are one-to-one mappings, simpler! */ | ||||
| int *loop_to_poly_map_src = nullptr; | int *loop_to_poly_map_src = nullptr; | ||||
| const float(*positions_src)[3] = BKE_mesh_vert_positions(me_src); | const float(*positions_src)[3] = BKE_mesh_vert_positions(me_src); | ||||
| const int num_verts_src = me_src->totvert; | const int num_verts_src = me_src->totvert; | ||||
| float(*vcos_src)[3] = nullptr; | float(*vcos_src)[3] = nullptr; | ||||
| const MEdge *edges_src = BKE_mesh_edges(me_src); | const MEdge *edges_src = BKE_mesh_edges(me_src); | ||||
| const int num_edges_src = me_src->totedge; | const int num_edges_src = me_src->totedge; | ||||
| const MLoop *loops_src = BKE_mesh_loops(me_src); | const blender::Span<int> corner_verts_src = me_src->corner_verts(); | ||||
| const blender::Span<int> corner_edges_src = me_src->corner_edges(); | |||||
| const int num_loops_src = me_src->totloop; | const int num_loops_src = me_src->totloop; | ||||
| const MPoly *polys_src = BKE_mesh_polys(me_src); | const MPoly *polys_src = BKE_mesh_polys(me_src); | ||||
| const int num_polys_src = me_src->totpoly; | const int num_polys_src = me_src->totpoly; | ||||
| const MLoopTri *looptri_src = nullptr; | const MLoopTri *looptri_src = nullptr; | ||||
| int num_looptri_src = 0; | int num_looptri_src = 0; | ||||
| size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE; | size_t buff_size_interp = MREMAP_DEFAULT_BUFSIZE; | ||||
| float(*vcos_interp)[3] = nullptr; | float(*vcos_interp)[3] = nullptr; | ||||
| int *indices_interp = nullptr; | int *indices_interp = nullptr; | ||||
| float *weights_interp = nullptr; | float *weights_interp = nullptr; | ||||
| const MLoop *ml_src; | |||||
| const MLoop *ml_dst; | |||||
| const MPoly *mp_src; | const MPoly *mp_src; | ||||
| const MPoly *mp_dst; | const MPoly *mp_dst; | ||||
| int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src; | int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src; | ||||
| IslandResult **islands_res; | IslandResult **islands_res; | ||||
| size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE; | size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE; | ||||
| if (!use_from_vert) { | if (!use_from_vert) { | ||||
| Show All 33 Lines | |||||
| if (dirty_nors_dst || do_loop_nors_dst) { | if (dirty_nors_dst || do_loop_nors_dst) { | ||||
| const bool *sharp_edges = static_cast<const bool *>( | const bool *sharp_edges = static_cast<const bool *>( | ||||
| CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge")); | CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge")); | ||||
| BKE_mesh_normals_loop_split(vert_positions_dst, | BKE_mesh_normals_loop_split(vert_positions_dst, | ||||
| BKE_mesh_vertex_normals_ensure(mesh_dst), | BKE_mesh_vertex_normals_ensure(mesh_dst), | ||||
| numverts_dst, | numverts_dst, | ||||
| edges_dst, | edges_dst, | ||||
| numedges_dst, | numedges_dst, | ||||
| loops_dst, | corner_verts_dst, | ||||
| corner_edges_dst, | |||||
| loop_nors_dst, | loop_nors_dst, | ||||
| numloops_dst, | numloops_dst, | ||||
| polys_dst, | polys_dst, | ||||
| poly_nors_dst, | poly_nors_dst, | ||||
| numpolys_dst, | numpolys_dst, | ||||
| use_split_nors_dst, | use_split_nors_dst, | ||||
| split_angle_dst, | split_angle_dst, | ||||
| sharp_edges, | sharp_edges, | ||||
| Show All 13 Lines | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (use_from_vert) { | if (use_from_vert) { | ||||
| BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, | BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, | ||||
| &vert_to_loop_map_src_buff, | &vert_to_loop_map_src_buff, | ||||
| polys_src, | polys_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| num_verts_src, | num_verts_src, | ||||
| num_polys_src, | num_polys_src, | ||||
| num_loops_src); | num_loops_src); | ||||
| if (mode & MREMAP_USE_POLY) { | if (mode & MREMAP_USE_POLY) { | ||||
| BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, | BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, | ||||
| &vert_to_poly_map_src_buff, | &vert_to_poly_map_src_buff, | ||||
| polys_src, | polys_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| num_verts_src, | num_verts_src, | ||||
| num_polys_src, | num_polys_src, | ||||
| num_loops_src); | num_loops_src); | ||||
| } | } | ||||
| } | } | ||||
| /* Needed for islands (or plain mesh) to AStar graph conversion. */ | /* Needed for islands (or plain mesh) to AStar graph conversion. */ | ||||
| BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src, | BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src, | ||||
| &edge_to_poly_map_src_buff, | &edge_to_poly_map_src_buff, | ||||
| edges_src, | edges_src, | ||||
| num_edges_src, | num_edges_src, | ||||
| polys_src, | polys_src, | ||||
| num_polys_src, | num_polys_src, | ||||
| loops_src, | corner_edges_src.data(), | ||||
| num_loops_src); | num_loops_src); | ||||
| if (use_from_vert) { | if (use_from_vert) { | ||||
| loop_to_poly_map_src = static_cast<int *>( | loop_to_poly_map_src = static_cast<int *>( | ||||
| MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(num_loops_src), __func__)); | MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(num_loops_src), __func__)); | ||||
| poly_cents_src = static_cast<float(*)[3]>( | poly_cents_src = static_cast<float(*)[3]>( | ||||
| MEM_mallocN(sizeof(*poly_cents_src) * size_t(num_polys_src), __func__)); | MEM_mallocN(sizeof(*poly_cents_src) * size_t(num_polys_src), __func__)); | ||||
| for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) { | for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) { | ||||
| ml_src = &loops_src[mp_src->loopstart]; | |||||
| for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop; | for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop; | ||||
| plidx_src++, lidx_src++) { | plidx_src++, lidx_src++) { | ||||
| loop_to_poly_map_src[lidx_src] = pidx_src; | loop_to_poly_map_src[lidx_src] = pidx_src; | ||||
| } | } | ||||
| BKE_mesh_calc_poly_center(mp_src, ml_src, positions_src, poly_cents_src[pidx_src]); | BKE_mesh_calc_poly_center( | ||||
| mp_src, &corner_verts_src[mp_src->loopstart], positions_src, poly_cents_src[pidx_src]); | |||||
| } | } | ||||
| } | } | ||||
| /* Island makes things slightly more complex here. | /* Island makes things slightly more complex here. | ||||
| * Basically, we: | * Basically, we: | ||||
| * * Make one treedata for each island's elements. | * * Make one treedata for each island's elements. | ||||
| * * Check all loops of a same dest poly against all treedata. | * * Check all loops of a same dest poly against all treedata. | ||||
| * * Choose the island's elements giving the best results. | * * Choose the island's elements giving the best results. | ||||
| */ | */ | ||||
| /* First, generate the islands, if possible. */ | /* First, generate the islands, if possible. */ | ||||
| if (gen_islands_src) { | if (gen_islands_src) { | ||||
| use_islands = gen_islands_src(positions_src, | use_islands = gen_islands_src(positions_src, | ||||
| num_verts_src, | num_verts_src, | ||||
| edges_src, | edges_src, | ||||
| num_edges_src, | num_edges_src, | ||||
| polys_src, | polys_src, | ||||
| num_polys_src, | num_polys_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| corner_edges_src.data(), | |||||
| num_loops_src, | num_loops_src, | ||||
| &island_store); | &island_store); | ||||
| num_trees = use_islands ? island_store.islands_num : 1; | num_trees = use_islands ? island_store.islands_num : 1; | ||||
| treedata = static_cast<BVHTreeFromMesh *>( | treedata = static_cast<BVHTreeFromMesh *>( | ||||
| MEM_callocN(sizeof(*treedata) * size_t(num_trees), __func__)); | MEM_callocN(sizeof(*treedata) * size_t(num_trees), __func__)); | ||||
| if (isld_steps_src) { | if (isld_steps_src) { | ||||
| as_graphdata = static_cast<BLI_AStarGraph *>( | as_graphdata = static_cast<BLI_AStarGraph *>( | ||||
| Show All 20 Lines | |||||
| /* Build our AStar graphs. */ | /* Build our AStar graphs. */ | ||||
| if (isld_steps_src) { | if (isld_steps_src) { | ||||
| for (tindex = 0; tindex < num_trees; tindex++) { | for (tindex = 0; tindex < num_trees; tindex++) { | ||||
| mesh_island_to_astar_graph(use_islands ? &island_store : nullptr, | mesh_island_to_astar_graph(use_islands ? &island_store : nullptr, | ||||
| tindex, | tindex, | ||||
| positions_src, | positions_src, | ||||
| edge_to_poly_map_src, | edge_to_poly_map_src, | ||||
| num_edges_src, | num_edges_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| corner_edges_src.data(), | |||||
| polys_src, | polys_src, | ||||
| num_polys_src, | num_polys_src, | ||||
| &as_graphdata[tindex]); | &as_graphdata[tindex]); | ||||
| } | } | ||||
| } | } | ||||
| /* Build our BVHtrees, either from verts or tessfaces. */ | /* Build our BVHtrees, either from verts or tessfaces. */ | ||||
| if (use_from_vert) { | if (use_from_vert) { | ||||
| if (use_islands) { | if (use_islands) { | ||||
| blender::BitVector<> verts_active(num_verts_src); | blender::BitVector<> verts_active(num_verts_src); | ||||
| for (tindex = 0; tindex < num_trees; tindex++) { | for (tindex = 0; tindex < num_trees; tindex++) { | ||||
| MeshElemMap *isld = island_store.islands[tindex]; | MeshElemMap *isld = island_store.islands[tindex]; | ||||
| int num_verts_active = 0; | int num_verts_active = 0; | ||||
| verts_active.fill(false); | verts_active.fill(false); | ||||
| for (i = 0; i < isld->count; i++) { | for (i = 0; i < isld->count; i++) { | ||||
| mp_src = &polys_src[isld->indices[i]]; | mp_src = &polys_src[isld->indices[i]]; | ||||
| for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; | for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; | ||||
| lidx_src++) { | lidx_src++) { | ||||
| const uint vidx_src = loops_src[lidx_src].v; | const int vidx_src = corner_verts_src[lidx_src]; | ||||
| if (!verts_active[vidx_src]) { | if (!verts_active[vidx_src]) { | ||||
| verts_active[vidx_src].set(); | verts_active[vidx_src].set(); | ||||
| num_verts_active++; | num_verts_active++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| bvhtree_from_mesh_verts_ex(&treedata[tindex], | bvhtree_from_mesh_verts_ex(&treedata[tindex], | ||||
| positions_src, | positions_src, | ||||
| Show All 24 Lines | |||||
| mp_src = &polys_src[looptri_src[i].poly]; | mp_src = &polys_src[looptri_src[i].poly]; | ||||
| if (island_store.items_to_islands[mp_src->loopstart] == tindex) { | if (island_store.items_to_islands[mp_src->loopstart] == tindex) { | ||||
| looptri_active[i].set(); | looptri_active[i].set(); | ||||
| num_looptri_active++; | num_looptri_active++; | ||||
| } | } | ||||
| } | } | ||||
| bvhtree_from_mesh_looptri_ex(&treedata[tindex], | bvhtree_from_mesh_looptri_ex(&treedata[tindex], | ||||
| positions_src, | positions_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| looptri_src, | looptri_src, | ||||
| num_looptri_src, | num_looptri_src, | ||||
| looptri_active, | looptri_active, | ||||
| num_looptri_active, | num_looptri_active, | ||||
| 0.0, | 0.0, | ||||
| 2, | 2, | ||||
| 6); | 6); | ||||
| } | } | ||||
| Show All 33 Lines | |||||
| islands_res[tindex] = static_cast<IslandResult *>( | islands_res[tindex] = static_cast<IslandResult *>( | ||||
| MEM_reallocN(islands_res[tindex], sizeof(**islands_res) * islands_res_buff_size)); | MEM_reallocN(islands_res[tindex], sizeof(**islands_res) * islands_res_buff_size)); | ||||
| } | } | ||||
| } | } | ||||
| for (tindex = 0; tindex < num_trees; tindex++) { | for (tindex = 0; tindex < num_trees; tindex++) { | ||||
| BVHTreeFromMesh *tdata = &treedata[tindex]; | BVHTreeFromMesh *tdata = &treedata[tindex]; | ||||
| ml_dst = &loops_dst[mp_dst->loopstart]; | for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++) { | ||||
| for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) { | const int vert_dst = corner_verts_dst[mp_dst->loopstart + plidx_dst]; | ||||
| if (use_from_vert) { | if (use_from_vert) { | ||||
| MeshElemMap *vert_to_refelem_map_src = nullptr; | MeshElemMap *vert_to_refelem_map_src = nullptr; | ||||
| copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); | copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| /* Convert the vertex to tree coordinates, if needed. */ | /* Convert the vertex to tree coordinates, if needed. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| if (mesh_remap_bvhtree_query_nearest( | if (mesh_remap_bvhtree_query_nearest( | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
| if (dot > best_nor_dot - 1e-6f) { | if (dot > best_nor_dot - 1e-6f) { | ||||
| /* We need something as fallback decision in case dest normal matches several | /* We need something as fallback decision in case dest normal matches several | ||||
| * source normals (see T44522), using distance between polys' centers here. */ | * source normals (see T44522), using distance between polys' centers here. */ | ||||
| float *pcent_src; | float *pcent_src; | ||||
| float sqdist; | float sqdist; | ||||
| mp_src = &polys_src[pidx_src]; | mp_src = &polys_src[pidx_src]; | ||||
| ml_src = &loops_src[mp_src->loopstart]; | |||||
| if (!pcent_dst_valid) { | if (!pcent_dst_valid) { | ||||
| BKE_mesh_calc_poly_center( | BKE_mesh_calc_poly_center(mp_dst, | ||||
| mp_dst, &loops_dst[mp_dst->loopstart], vert_positions_dst, pcent_dst); | &corner_verts_src[mp_dst->loopstart], | ||||
| vert_positions_dst, | |||||
| pcent_dst); | |||||
| pcent_dst_valid = true; | pcent_dst_valid = true; | ||||
| } | } | ||||
| pcent_src = poly_cents_src[pidx_src]; | pcent_src = poly_cents_src[pidx_src]; | ||||
| sqdist = len_squared_v3v3(pcent_dst, pcent_src); | sqdist = len_squared_v3v3(pcent_dst, pcent_src); | ||||
| if ((dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) { | if ((dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) { | ||||
| best_nor_dot = dot; | best_nor_dot = dot; | ||||
| best_sqdist_fallback = sqdist; | best_sqdist_fallback = sqdist; | ||||
| best_index_src = index_src; | best_index_src = index_src; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (best_index_src == -1) { | if (best_index_src == -1) { | ||||
| /* We found no item to map back from closest vertex... */ | /* We found no item to map back from closest vertex... */ | ||||
| best_nor_dot = -1.0f; | best_nor_dot = -1.0f; | ||||
| hit_dist = FLT_MAX; | hit_dist = FLT_MAX; | ||||
| } | } | ||||
| else if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { | else if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { | ||||
| /* Our best_index_src is a poly one for now! | /* Our best_index_src is a poly one for now! | ||||
| * Have to find its loop matching our closest vertex. */ | * Have to find its loop matching our closest vertex. */ | ||||
| mp_src = &polys_src[best_index_src]; | mp_src = &polys_src[best_index_src]; | ||||
| ml_src = &loops_src[mp_src->loopstart]; | for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++) { | ||||
| for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++, ml_src++) { | const int vert_src = corner_verts_src[mp_src->loopstart + plidx_src]; | ||||
| if (int(ml_src->v) == nearest.index) { | if (vert_src == nearest.index) { | ||||
| best_index_src = plidx_src + mp_src->loopstart; | best_index_src = plidx_src + mp_src->loopstart; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| best_nor_dot = (best_nor_dot + 1.0f) * 0.5f; | best_nor_dot = (best_nor_dot + 1.0f) * 0.5f; | ||||
| islands_res[tindex][plidx_dst].factor = hit_dist ? (best_nor_dot / hit_dist) : 1e18f; | islands_res[tindex][plidx_dst].factor = hit_dist ? (best_nor_dot / hit_dist) : 1e18f; | ||||
| islands_res[tindex][plidx_dst].hit_dist = hit_dist; | islands_res[tindex][plidx_dst].hit_dist = hit_dist; | ||||
| islands_res[tindex][plidx_dst].index_src = best_index_src; | islands_res[tindex][plidx_dst].index_src = best_index_src; | ||||
| } | } | ||||
| else { | else { | ||||
| /* No source for this dest loop! */ | /* No source for this dest loop! */ | ||||
| islands_res[tindex][plidx_dst].factor = 0.0f; | islands_res[tindex][plidx_dst].factor = 0.0f; | ||||
| islands_res[tindex][plidx_dst].hit_dist = FLT_MAX; | islands_res[tindex][plidx_dst].hit_dist = FLT_MAX; | ||||
| islands_res[tindex][plidx_dst].index_src = -1; | islands_res[tindex][plidx_dst].index_src = -1; | ||||
| } | } | ||||
| } | } | ||||
| else if (mode & MREMAP_USE_NORPROJ) { | else if (mode & MREMAP_USE_NORPROJ) { | ||||
| int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1; | int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1; | ||||
| float w = 1.0f; | float w = 1.0f; | ||||
| copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); | copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); | ||||
| copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]); | copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]); | ||||
| /* We do our transform here, since we may do several raycast/nearest queries. */ | /* We do our transform here, since we may do several raycast/nearest queries. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| BLI_space_transform_apply_normal(space_transform, tmp_no); | BLI_space_transform_apply_normal(space_transform, tmp_no); | ||||
| } | } | ||||
| Show All 11 Lines | |||||
| } | } | ||||
| if (n == -1) { | if (n == -1) { | ||||
| /* Fallback to 'nearest' hit here, loops usually comes in 'face group', not good to | /* Fallback to 'nearest' hit here, loops usually comes in 'face group', not good to | ||||
| * have only part of one dest face's loops to map to source. | * have only part of one dest face's loops to map to source. | ||||
| * Note that since we give this a null weight, if whole weight for a given face | * Note that since we give this a null weight, if whole weight for a given face | ||||
| * is null, it means none of its loop mapped to this source island, | * is null, it means none of its loop mapped to this source island, | ||||
| * hence we can skip it later. | * hence we can skip it later. | ||||
| */ | */ | ||||
| copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); | copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| /* Convert the vertex to tree coordinates, if needed. */ | /* Convert the vertex to tree coordinates, if needed. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| /* In any case, this fallback nearest hit should have no weight at all | /* In any case, this fallback nearest hit should have no weight at all | ||||
| Show All 9 Lines | |||||
| else { | else { | ||||
| /* No source for this dest loop! */ | /* No source for this dest loop! */ | ||||
| islands_res[tindex][plidx_dst].hit_dist = FLT_MAX; | islands_res[tindex][plidx_dst].hit_dist = FLT_MAX; | ||||
| islands_res[tindex][plidx_dst].index_src = -1; | islands_res[tindex][plidx_dst].index_src = -1; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { /* Nearest poly either to use all its loops/verts or just closest one. */ | else { /* Nearest poly either to use all its loops/verts or just closest one. */ | ||||
| copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); | copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| /* Convert the vertex to tree coordinates, if needed. */ | /* Convert the vertex to tree coordinates, if needed. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| if (mesh_remap_bvhtree_query_nearest( | if (mesh_remap_bvhtree_query_nearest( | ||||
| ▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| } | } | ||||
| if (last_valid_pidx_isld_src != -1) { | if (last_valid_pidx_isld_src != -1) { | ||||
| /* Find a new valid loop in that new poly (nearest one for now). | /* Find a new valid loop in that new poly (nearest one for now). | ||||
| * Note we could be much more subtle here, again that's for later... */ | * Note we could be much more subtle here, again that's for later... */ | ||||
| int j; | int j; | ||||
| float best_dist_sq = FLT_MAX; | float best_dist_sq = FLT_MAX; | ||||
| ml_dst = &loops_dst[lidx_dst]; | copy_v3_v3(tmp_co, vert_positions_dst[corner_verts_dst[lidx_dst]]); | ||||
| copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); | |||||
| /* We do our transform here, | /* We do our transform here, | ||||
| * since we may do several raycast/nearest queries. */ | * since we may do several raycast/nearest queries. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| pidx_src = (use_islands ? best_island->indices[last_valid_pidx_isld_src] : | pidx_src = (use_islands ? best_island->indices[last_valid_pidx_isld_src] : | ||||
| last_valid_pidx_isld_src); | last_valid_pidx_isld_src); | ||||
| mp_src = &polys_src[pidx_src]; | mp_src = &polys_src[pidx_src]; | ||||
| ml_src = &loops_src[mp_src->loopstart]; | for (j = 0; j < mp_src->totloop; j++) { | ||||
| for (j = 0; j < mp_src->totloop; j++, ml_src++) { | const int vert_src = corner_verts_src[mp_src->loopstart + j]; | ||||
| const float dist_sq = len_squared_v3v3(positions_src[ml_src->v], tmp_co); | const float dist_sq = len_squared_v3v3(positions_src[vert_src], tmp_co); | ||||
| if (dist_sq < best_dist_sq) { | if (dist_sq < best_dist_sq) { | ||||
| best_dist_sq = dist_sq; | best_dist_sq = dist_sq; | ||||
| lidx_src = mp_src->loopstart + j; | lidx_src = mp_src->loopstart + j; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| } | } | ||||
| if (last_valid_pidx_isld_src != -1) { | if (last_valid_pidx_isld_src != -1) { | ||||
| /* Find a new valid loop in that new poly (nearest point on poly for now). | /* Find a new valid loop in that new poly (nearest point on poly for now). | ||||
| * Note we could be much more subtle here, again that's for later... */ | * Note we could be much more subtle here, again that's for later... */ | ||||
| float best_dist_sq = FLT_MAX; | float best_dist_sq = FLT_MAX; | ||||
| int j; | int j; | ||||
| ml_dst = &loops_dst[lidx_dst]; | const int vert_dst = corner_verts_dst[lidx_dst]; | ||||
| copy_v3_v3(tmp_co, vert_positions_dst[ml_dst->v]); | copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); | ||||
| /* We do our transform here, | /* We do our transform here, | ||||
| * since we may do several raycast/nearest queries. */ | * since we may do several raycast/nearest queries. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| pidx_src = (use_islands ? best_island->indices[last_valid_pidx_isld_src] : | pidx_src = (use_islands ? best_island->indices[last_valid_pidx_isld_src] : | ||||
| Show All 13 Lines | |||||
| for (j = poly_to_looptri_map_src[pidx_src].count; j--;) { | for (j = poly_to_looptri_map_src[pidx_src].count; j--;) { | ||||
| float h[3]; | float h[3]; | ||||
| const MLoopTri *lt = | const MLoopTri *lt = | ||||
| &looptri_src[poly_to_looptri_map_src[pidx_src].indices[j]]; | &looptri_src[poly_to_looptri_map_src[pidx_src].indices[j]]; | ||||
| float dist_sq; | float dist_sq; | ||||
| closest_on_tri_to_point_v3(h, | closest_on_tri_to_point_v3(h, | ||||
| tmp_co, | tmp_co, | ||||
| vcos_src[loops_src[lt->tri[0]].v], | vcos_src[corner_verts_src[lt->tri[0]]], | ||||
| vcos_src[loops_src[lt->tri[1]].v], | vcos_src[corner_verts_src[lt->tri[1]]], | ||||
| vcos_src[loops_src[lt->tri[2]].v]); | vcos_src[corner_verts_src[lt->tri[2]]]); | ||||
| dist_sq = len_squared_v3v3(tmp_co, h); | dist_sq = len_squared_v3v3(tmp_co, h); | ||||
| if (dist_sq < best_dist_sq) { | if (dist_sq < best_dist_sq) { | ||||
| copy_v3_v3(hit_co, h); | copy_v3_v3(hit_co, h); | ||||
| best_dist_sq = dist_sq; | best_dist_sq = dist_sq; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) { | if (mode == MREMAP_MODE_LOOP_POLY_NEAREST) { | ||||
| mesh_remap_interp_poly_data_get(mp_src, | mesh_remap_interp_poly_data_get(mp_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| (const float(*)[3])vcos_src, | (const float(*)[3])vcos_src, | ||||
| hit_co, | hit_co, | ||||
| &buff_size_interp, | &buff_size_interp, | ||||
| &vcos_interp, | &vcos_interp, | ||||
| true, | true, | ||||
| &indices_interp, | &indices_interp, | ||||
| &weights_interp, | &weights_interp, | ||||
| false, | false, | ||||
| &best_loop_index_src); | &best_loop_index_src); | ||||
| mesh_remap_item_define(r_map, | mesh_remap_item_define(r_map, | ||||
| lidx_dst, | lidx_dst, | ||||
| isld_res->hit_dist, | isld_res->hit_dist, | ||||
| best_island_index, | best_island_index, | ||||
| 1, | 1, | ||||
| &best_loop_index_src, | &best_loop_index_src, | ||||
| &full_weight); | &full_weight); | ||||
| } | } | ||||
| else { | else { | ||||
| const int sources_num = mesh_remap_interp_poly_data_get( | const int sources_num = mesh_remap_interp_poly_data_get( | ||||
| mp_src, | mp_src, | ||||
| loops_src, | corner_verts_src.data(), | ||||
| (const float(*)[3])vcos_src, | (const float(*)[3])vcos_src, | ||||
| hit_co, | hit_co, | ||||
| &buff_size_interp, | &buff_size_interp, | ||||
| &vcos_interp, | &vcos_interp, | ||||
| true, | true, | ||||
| &indices_interp, | &indices_interp, | ||||
| &weights_interp, | &weights_interp, | ||||
| true, | true, | ||||
| ▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| void BKE_mesh_remap_calc_polys_from_mesh(const int mode, | void BKE_mesh_remap_calc_polys_from_mesh(const int mode, | ||||
| const SpaceTransform *space_transform, | const SpaceTransform *space_transform, | ||||
| const float max_dist, | const float max_dist, | ||||
| const float ray_radius, | const float ray_radius, | ||||
| const Mesh *mesh_dst, | const Mesh *mesh_dst, | ||||
| const float (*vert_positions_dst)[3], | const float (*vert_positions_dst)[3], | ||||
| const MLoop *loops_dst, | const int *corner_verts, | ||||
| const MPoly *polys_dst, | const MPoly *polys_dst, | ||||
| const int numpolys_dst, | const int numpolys_dst, | ||||
| Mesh *me_src, | Mesh *me_src, | ||||
| MeshPairRemap *r_map) | MeshPairRemap *r_map) | ||||
| { | { | ||||
| const float full_weight = 1.0f; | const float full_weight = 1.0f; | ||||
| const float max_dist_sq = max_dist * max_dist; | const float max_dist_sq = max_dist * max_dist; | ||||
| const float(*poly_nors_dst)[3] = nullptr; | const float(*poly_nors_dst)[3] = nullptr; | ||||
| Show All 23 Lines | |||||
| BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); | BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2); | ||||
| if (mode == MREMAP_MODE_POLY_NEAREST) { | if (mode == MREMAP_MODE_POLY_NEAREST) { | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| for (i = 0; i < numpolys_dst; i++) { | for (i = 0; i < numpolys_dst; i++) { | ||||
| const MPoly *mp = &polys_dst[i]; | const MPoly *mp = &polys_dst[i]; | ||||
| BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], vert_positions_dst, tmp_co); | BKE_mesh_calc_poly_center(mp, &corner_verts[mp->loopstart], vert_positions_dst, tmp_co); | ||||
| /* Convert the vertex to tree coordinates, if needed. */ | /* Convert the vertex to tree coordinates, if needed. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| if (mesh_remap_bvhtree_query_nearest( | if (mesh_remap_bvhtree_query_nearest( | ||||
| &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { | &treedata, &nearest, tmp_co, max_dist_sq, &hit_dist)) { | ||||
| const MLoopTri *lt = &treedata.looptri[nearest.index]; | const MLoopTri *lt = &treedata.looptri[nearest.index]; | ||||
| const int poly_index = int(lt->poly); | const int poly_index = int(lt->poly); | ||||
| mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &poly_index, &full_weight); | mesh_remap_item_define(r_map, i, hit_dist, 0, 1, &poly_index, &full_weight); | ||||
| } | } | ||||
| else { | else { | ||||
| /* No source for this dest poly! */ | /* No source for this dest poly! */ | ||||
| BKE_mesh_remap_item_define_invalid(r_map, i); | BKE_mesh_remap_item_define_invalid(r_map, i); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (mode == MREMAP_MODE_POLY_NOR) { | else if (mode == MREMAP_MODE_POLY_NOR) { | ||||
| BLI_assert(poly_nors_dst); | BLI_assert(poly_nors_dst); | ||||
| for (i = 0; i < numpolys_dst; i++) { | for (i = 0; i < numpolys_dst; i++) { | ||||
| const MPoly *mp = &polys_dst[i]; | const MPoly *mp = &polys_dst[i]; | ||||
| BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], vert_positions_dst, tmp_co); | BKE_mesh_calc_poly_center(mp, &corner_verts[mp->loopstart], vert_positions_dst, tmp_co); | ||||
| copy_v3_v3(tmp_no, poly_nors_dst[i]); | copy_v3_v3(tmp_no, poly_nors_dst[i]); | ||||
| /* Convert the vertex to tree coordinates, if needed. */ | /* Convert the vertex to tree coordinates, if needed. */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| BLI_space_transform_apply_normal(space_transform, tmp_no); | BLI_space_transform_apply_normal(space_transform, tmp_no); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
| float poly_dst_2d_size[2]; | float poly_dst_2d_size[2]; | ||||
| float totweights = 0.0f; | float totweights = 0.0f; | ||||
| float hit_dist_accum = 0.0f; | float hit_dist_accum = 0.0f; | ||||
| int sources_num = 0; | int sources_num = 0; | ||||
| const int tris_num = mp->totloop - 2; | const int tris_num = mp->totloop - 2; | ||||
| int j; | int j; | ||||
| BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], vert_positions_dst, pcent_dst); | BKE_mesh_calc_poly_center(mp, &corner_verts[mp->loopstart], vert_positions_dst, pcent_dst); | ||||
| copy_v3_v3(tmp_no, poly_nors_dst[i]); | copy_v3_v3(tmp_no, poly_nors_dst[i]); | ||||
| /* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */ | /* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */ | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, pcent_dst); | BLI_space_transform_apply(space_transform, pcent_dst); | ||||
| BLI_space_transform_apply_normal(space_transform, tmp_no); | BLI_space_transform_apply_normal(space_transform, tmp_no); | ||||
| } | } | ||||
| Show All 12 Lines | |||||
| mul_m3_v3(to_pnor_2d_mat, pcent_dst); | mul_m3_v3(to_pnor_2d_mat, pcent_dst); | ||||
| poly_dst_2d_z = pcent_dst[2]; | poly_dst_2d_z = pcent_dst[2]; | ||||
| /* Get (2D) bounding square of our poly. */ | /* Get (2D) bounding square of our poly. */ | ||||
| INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max); | INIT_MINMAX2(poly_dst_2d_min, poly_dst_2d_max); | ||||
| for (j = 0; j < mp->totloop; j++) { | for (j = 0; j < mp->totloop; j++) { | ||||
| const MLoop *ml = &loops_dst[j + mp->loopstart]; | const int vert = corner_verts[mp->loopstart + j]; | ||||
| copy_v3_v3(tmp_co, vert_positions_dst[ml->v]); | copy_v3_v3(tmp_co, vert_positions_dst[vert]); | ||||
| if (space_transform) { | if (space_transform) { | ||||
| BLI_space_transform_apply(space_transform, tmp_co); | BLI_space_transform_apply(space_transform, tmp_co); | ||||
| } | } | ||||
| mul_v2_m3v3(poly_vcos_2d[j], to_pnor_2d_mat, tmp_co); | mul_v2_m3v3(poly_vcos_2d[j], to_pnor_2d_mat, tmp_co); | ||||
| minmax_v2v2_v2(poly_dst_2d_min, poly_dst_2d_max, poly_vcos_2d[j]); | minmax_v2v2_v2(poly_dst_2d_min, poly_dst_2d_max, poly_vcos_2d[j]); | ||||
| } | } | ||||
| /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast), | /* We adjust our ray-casting grid to ray_radius (the smaller, the more rays are cast), | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||