Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_mapping.cc
| Show All 27 Lines | |||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Mesh Connectivity Mapping | /** \name Mesh Connectivity Mapping | ||||
| * \{ */ | * \{ */ | ||||
| /* ngon version wip, based on BM_uv_vert_map_create */ | /* ngon version wip, based on BM_uv_vert_map_create */ | ||||
| UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, | UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly, | ||||
| const bool *hide_poly, | const bool *hide_poly, | ||||
| const bool *select_poly, | const bool *select_poly, | ||||
| const MLoop *mloop, | const int *corner_verts, | ||||
| const float (*mloopuv)[2], | const float (*mloopuv)[2], | ||||
| uint totpoly, | uint totpoly, | ||||
| uint totvert, | uint totvert, | ||||
| const float limit[2], | const float limit[2], | ||||
| const bool selected, | const bool selected, | ||||
| const bool use_winding) | const bool use_winding) | ||||
| { | { | ||||
| UvVertMap *vmap; | UvVertMap *vmap; | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) { | ||||
| } | } | ||||
| nverts = mp->totloop; | nverts = mp->totloop; | ||||
| for (i = 0; i < nverts; i++) { | for (i = 0; i < nverts; i++) { | ||||
| buf->loop_of_poly_index = ushort(i); | buf->loop_of_poly_index = ushort(i); | ||||
| buf->poly_index = a; | buf->poly_index = a; | ||||
| buf->separate = false; | buf->separate = false; | ||||
| buf->next = vmap->vert[mloop[mp->loopstart + i].v]; | buf->next = vmap->vert[corner_verts[mp->loopstart + i]]; | ||||
| vmap->vert[mloop[mp->loopstart + i].v] = buf; | vmap->vert[corner_verts[mp->loopstart + i]] = buf; | ||||
| if (use_winding) { | if (use_winding) { | ||||
| copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i]); | copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i]); | ||||
| } | } | ||||
| buf++; | buf++; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
| * of polys or loops that use that vertex as a corner. The lists are allocated | * of polys or loops that use that vertex as a corner. The lists are allocated | ||||
| * from one memory pool. | * from one memory pool. | ||||
| * | * | ||||
| * Wrapped by #BKE_mesh_vert_poly_map_create & BKE_mesh_vert_loop_map_create | * Wrapped by #BKE_mesh_vert_poly_map_create & BKE_mesh_vert_loop_map_create | ||||
| */ | */ | ||||
| static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, | static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, | ||||
| int **r_mem, | int **r_mem, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const MLoop *mloop, | const int *corner_verts, | ||||
| int totvert, | int totvert, | ||||
| int totpoly, | int totpoly, | ||||
| int totloop, | int totloop, | ||||
| const bool do_loops) | const bool do_loops) | ||||
| { | { | ||||
| MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totvert), __func__); | MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totvert), __func__); | ||||
| int *indices, *index_iter; | int *indices, *index_iter; | ||||
| int i, j; | int i, j; | ||||
| indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totloop), __func__)); | indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totloop), __func__)); | ||||
| index_iter = indices; | index_iter = indices; | ||||
| /* Count number of polys for each vertex */ | /* Count number of polys for each vertex */ | ||||
| for (i = 0; i < totpoly; i++) { | for (i = 0; i < totpoly; i++) { | ||||
| const MPoly *p = &mpoly[i]; | const MPoly *p = &mpoly[i]; | ||||
| for (j = 0; j < p->totloop; j++) { | for (j = 0; j < p->totloop; j++) { | ||||
| map[mloop[p->loopstart + j].v].count++; | map[corner_verts[p->loopstart + j]].count++; | ||||
| } | } | ||||
| } | } | ||||
| /* Assign indices mem */ | /* Assign indices mem */ | ||||
| for (i = 0; i < totvert; i++) { | for (i = 0; i < totvert; i++) { | ||||
| map[i].indices = index_iter; | map[i].indices = index_iter; | ||||
| index_iter += map[i].count; | index_iter += map[i].count; | ||||
| /* Reset 'count' for use as index in last loop */ | /* Reset 'count' for use as index in last loop */ | ||||
| map[i].count = 0; | map[i].count = 0; | ||||
| } | } | ||||
| /* Find the users */ | /* Find the users */ | ||||
| for (i = 0; i < totpoly; i++) { | for (i = 0; i < totpoly; i++) { | ||||
| const MPoly *p = &mpoly[i]; | const MPoly *p = &mpoly[i]; | ||||
| for (j = 0; j < p->totloop; j++) { | for (j = 0; j < p->totloop; j++) { | ||||
| uint v = mloop[p->loopstart + j].v; | const int v = corner_verts[p->loopstart + j]; | ||||
| map[v].indices[map[v].count] = do_loops ? p->loopstart + j : i; | map[v].indices[map[v].count] = do_loops ? p->loopstart + j : i; | ||||
| map[v].count++; | map[v].count++; | ||||
| } | } | ||||
| } | } | ||||
| *r_map = map; | *r_map = map; | ||||
| *r_mem = indices; | *r_mem = indices; | ||||
| } | } | ||||
| void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, | void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, | ||||
| int **r_mem, | int **r_mem, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const MLoop *mloop, | const int *corner_verts, | ||||
| int totvert, | int totvert, | ||||
| int totpoly, | int totpoly, | ||||
| int totloop) | int totloop) | ||||
| { | { | ||||
| mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false); | mesh_vert_poly_or_loop_map_create( | ||||
| r_map, r_mem, mpoly, corner_verts, totvert, totpoly, totloop, false); | |||||
| } | } | ||||
| void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, | void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, | ||||
| int **r_mem, | int **r_mem, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const MLoop *mloop, | const int *corner_verts, | ||||
| int totvert, | int totvert, | ||||
| int totpoly, | int totpoly, | ||||
| int totloop) | int totloop) | ||||
| { | { | ||||
| mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true); | mesh_vert_poly_or_loop_map_create( | ||||
| r_map, r_mem, mpoly, corner_verts, totvert, totpoly, totloop, true); | |||||
| } | } | ||||
| void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, | void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, | ||||
| int **r_mem, | int **r_mem, | ||||
| const int totvert, | const int totvert, | ||||
| const MLoopTri *mlooptri, | const MLoopTri *mlooptri, | ||||
| const int totlooptri, | const int totlooptri, | ||||
| const MLoop *mloop, | const int *corner_verts, | ||||
| const int /*totloop*/) | const int /*totloop*/) | ||||
| { | { | ||||
| MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totvert), __func__); | MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totvert), __func__); | ||||
| int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totlooptri) * 3, __func__)); | int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totlooptri) * 3, __func__)); | ||||
| int *index_step; | int *index_step; | ||||
| const MLoopTri *mlt; | const MLoopTri *mlt; | ||||
| int i; | int i; | ||||
| /* count face users */ | /* count face users */ | ||||
| for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) { | for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) { | ||||
| for (int j = 3; j--;) { | for (int j = 3; j--;) { | ||||
| map[mloop[mlt->tri[j]].v].count++; | map[corner_verts[mlt->tri[j]]].count++; | ||||
| } | } | ||||
| } | } | ||||
| /* create offsets */ | /* create offsets */ | ||||
| index_step = indices; | index_step = indices; | ||||
| for (i = 0; i < totvert; i++) { | for (i = 0; i < totvert; i++) { | ||||
| map[i].indices = index_step; | map[i].indices = index_step; | ||||
| index_step += map[i].count; | index_step += map[i].count; | ||||
| /* re-count, using this as an index below */ | /* re-count, using this as an index below */ | ||||
| map[i].count = 0; | map[i].count = 0; | ||||
| } | } | ||||
| /* assign looptri-edge users */ | /* assign looptri-edge users */ | ||||
| for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) { | for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) { | ||||
| for (int j = 3; j--;) { | for (int j = 3; j--;) { | ||||
| MeshElemMap *map_ele = &map[mloop[mlt->tri[j]].v]; | MeshElemMap *map_ele = &map[corner_verts[mlt->tri[j]]]; | ||||
| map_ele->indices[map_ele->count++] = i; | map_ele->indices[map_ele->count++] = i; | ||||
| } | } | ||||
| } | } | ||||
| *r_map = map; | *r_map = map; | ||||
| *r_mem = indices; | *r_mem = indices; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, | void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, | ||||
| int **r_mem, | int **r_mem, | ||||
| const MEdge * /*medge*/, | const MEdge * /*medge*/, | ||||
| const int totedge, | const int totedge, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const int totpoly, | const int totpoly, | ||||
| const MLoop *mloop, | const int *corner_edges, | ||||
| const int totloop) | const int totloop) | ||||
| { | { | ||||
| using namespace blender; | |||||
| MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totedge), __func__); | MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totedge), __func__); | ||||
| int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totloop) * 2, __func__)); | int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totloop) * 2, __func__)); | ||||
| int *index_step; | int *index_step; | ||||
| const MPoly *mp; | const MPoly *mp; | ||||
| int i; | |||||
| /* count face users */ | /* count face users */ | ||||
| for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { | for (const int64_t i : IndexRange(totloop)) { | ||||
| const MLoop *ml; | map[corner_edges[i]].count += 2; | ||||
| int j = mp->totloop; | |||||
| for (ml = &mloop[mp->loopstart]; j--; ml++) { | |||||
| map[ml->e].count += 2; | |||||
| } | |||||
| } | } | ||||
| /* create offsets */ | /* create offsets */ | ||||
| index_step = indices; | index_step = indices; | ||||
| for (i = 0; i < totedge; i++) { | for (int i = 0; i < totedge; i++) { | ||||
| map[i].indices = index_step; | map[i].indices = index_step; | ||||
| index_step += map[i].count; | index_step += map[i].count; | ||||
| /* re-count, using this as an index below */ | /* re-count, using this as an index below */ | ||||
| map[i].count = 0; | map[i].count = 0; | ||||
| } | } | ||||
| int i; | |||||
| /* assign loop-edge users */ | /* assign loop-edge users */ | ||||
| for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { | for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { | ||||
| const MLoop *ml; | |||||
| MeshElemMap *map_ele; | MeshElemMap *map_ele; | ||||
| const int max_loop = mp->loopstart + mp->totloop; | const int max_loop = mp->loopstart + mp->totloop; | ||||
| int j = mp->loopstart; | for (int j = mp->loopstart; j < max_loop; j++) { | ||||
| for (ml = &mloop[j]; j < max_loop; j++, ml++) { | map_ele = &map[corner_edges[j]]; | ||||
| map_ele = &map[ml->e]; | |||||
| map_ele->indices[map_ele->count++] = j; | map_ele->indices[map_ele->count++] = j; | ||||
| map_ele->indices[map_ele->count++] = j + 1; | map_ele->indices[map_ele->count++] = j + 1; | ||||
| } | } | ||||
| /* last edge/loop of poly, must point back to first loop! */ | /* last edge/loop of poly, must point back to first loop! */ | ||||
| map_ele->indices[map_ele->count - 1] = mp->loopstart; | map_ele->indices[map_ele->count - 1] = mp->loopstart; | ||||
| } | } | ||||
| *r_map = map; | *r_map = map; | ||||
| *r_mem = indices; | *r_mem = indices; | ||||
| } | } | ||||
| void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, | void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, | ||||
| int **r_mem, | int **r_mem, | ||||
| const MEdge * /*medge*/, | const MEdge * /*medge*/, | ||||
| const int totedge, | const int totedge, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const int totpoly, | const int totpoly, | ||||
| const MLoop *mloop, | const int *corner_edges, | ||||
| const int totloop) | const int totloop) | ||||
| { | { | ||||
| MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totedge), __func__); | MeshElemMap *map = MEM_cnew_array<MeshElemMap>(size_t(totedge), __func__); | ||||
| int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totloop), __func__)); | int *indices = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totloop), __func__)); | ||||
| int *index_step; | int *index_step; | ||||
| const MPoly *mp; | const MPoly *mp; | ||||
| int i; | int i; | ||||
| /* count face users */ | /* count face users */ | ||||
| for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { | for (i = 0; i < totloop; i++) { | ||||
| const MLoop *ml; | map[corner_edges[i]].count++; | ||||
| int j = mp->totloop; | |||||
| for (ml = &mloop[mp->loopstart]; j--; ml++) { | |||||
| map[ml->e].count++; | |||||
| } | |||||
| } | } | ||||
| /* create offsets */ | /* create offsets */ | ||||
| index_step = indices; | index_step = indices; | ||||
| for (i = 0; i < totedge; i++) { | for (i = 0; i < totedge; i++) { | ||||
| map[i].indices = index_step; | map[i].indices = index_step; | ||||
| index_step += map[i].count; | index_step += map[i].count; | ||||
| /* re-count, using this as an index below */ | /* re-count, using this as an index below */ | ||||
| map[i].count = 0; | map[i].count = 0; | ||||
| } | } | ||||
| /* assign poly-edge users */ | /* assign poly-edge users */ | ||||
| for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { | for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { | ||||
| const MLoop *ml; | for (int j = 0; j < mp->totloop; j++) { | ||||
| int j = mp->totloop; | const int edge_i = corner_edges[mp->loopstart + j]; | ||||
| for (ml = &mloop[mp->loopstart]; j--; ml++) { | MeshElemMap *map_ele = &map[edge_i]; | ||||
| MeshElemMap *map_ele = &map[ml->e]; | |||||
| map_ele->indices[map_ele->count++] = i; | map_ele->indices[map_ele->count++] = i; | ||||
| } | } | ||||
| } | } | ||||
| *r_map = map; | *r_map = map; | ||||
| *r_mem = indices; | *r_mem = indices; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | Array<Vector<int>> build_vert_to_edge_map(const Span<MEdge> edges, const int verts_num) | ||||
| for (const int64_t i : edges.index_range()) { | for (const int64_t i : edges.index_range()) { | ||||
| map[edges[i].v1].append(int(i)); | map[edges[i].v1].append(int(i)); | ||||
| map[edges[i].v2].append(int(i)); | map[edges[i].v2].append(int(i)); | ||||
| } | } | ||||
| return map; | return map; | ||||
| } | } | ||||
| Array<Vector<int>> build_vert_to_poly_map(const Span<MPoly> polys, | Array<Vector<int>> build_vert_to_poly_map(const Span<MPoly> polys, | ||||
| const Span<MLoop> loops, | const Span<int> corner_verts, | ||||
| int verts_num) | int verts_num) | ||||
| { | { | ||||
| Array<Vector<int>> map(verts_num); | Array<Vector<int>> map(verts_num); | ||||
| for (const int64_t i : polys.index_range()) { | for (const int64_t i : polys.index_range()) { | ||||
| const MPoly &poly = polys[i]; | const MPoly &poly = polys[i]; | ||||
| for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { | for (const int64_t vert_i : corner_verts.slice(poly.loopstart, poly.totloop)) { | ||||
| map[loop.v].append(int(i)); | map[int(vert_i)].append(int(i)); | ||||
| } | } | ||||
| } | } | ||||
| return map; | return map; | ||||
| } | } | ||||
| Array<Vector<int>> build_vert_to_loop_map(const Span<MLoop> loops, const int verts_num) | Array<Vector<int>> build_vert_to_loop_map(const Span<int> corner_verts, const int verts_num) | ||||
| { | { | ||||
| Array<Vector<int>> map(verts_num); | Array<Vector<int>> map(verts_num); | ||||
| for (const int64_t i : loops.index_range()) { | for (const int64_t i : corner_verts.index_range()) { | ||||
| map[loops[i].v].append(int(i)); | map[corner_verts[i]].append(int(i)); | ||||
| } | } | ||||
| return map; | return map; | ||||
| } | } | ||||
| Array<Vector<int>> build_edge_to_loop_map(const Span<MLoop> loops, const int edges_num) | Array<Vector<int>> build_edge_to_loop_map(const Span<int> corner_edges, const int edges_num) | ||||
| { | { | ||||
| Array<Vector<int>> map(edges_num); | Array<Vector<int>> map(edges_num); | ||||
| for (const int64_t i : loops.index_range()) { | for (const int64_t i : corner_edges.index_range()) { | ||||
| map[loops[i].e].append(int(i)); | map[corner_edges[i]].append(int(i)); | ||||
| } | } | ||||
| return map; | return map; | ||||
| } | } | ||||
| Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<MLoop> loops, const int edges_num) | Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<int> corner_edges, | ||||
| const int edges_num) | |||||
| { | { | ||||
| Vector<Vector<int>> map(edges_num); | Vector<Vector<int>> map(edges_num); | ||||
| for (const int64_t i : loops.index_range()) { | for (const int64_t i : corner_edges.index_range()) { | ||||
| map[loops[i].e].append(int(i)); | map[corner_edges[i]].append(int(i)); | ||||
| } | } | ||||
| return map; | return map; | ||||
| } | } | ||||
| } // namespace blender::bke::mesh_topology | } // namespace blender::bke::mesh_topology | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Mesh loops/poly islands. | /** \name Mesh loops/poly islands. | ||||
| * Used currently for UVs and 'smooth groups'. | * Used currently for UVs and 'smooth groups'. | ||||
| * \{ */ | * \{ */ | ||||
| /** | /** | ||||
| * Callback deciding whether the given poly/loop/edge define an island boundary or not. | * Callback deciding whether the given poly/loop/edge define an island boundary or not. | ||||
| */ | */ | ||||
| using MeshRemap_CheckIslandBoundary = bool (*)(const MPoly *mpoly, | using MeshRemap_CheckIslandBoundary = bool (*)(const MPoly *mpoly, | ||||
| const MLoop *mloop, | const int corner, | ||||
| const MEdge *medge, | const MEdge *medge, | ||||
| const int edge_index, | const int edge_index, | ||||
| const bool *sharp_edges, | const bool *sharp_edges, | ||||
| const int edge_user_count, | const int edge_user_count, | ||||
| const MPoly *mpoly_array, | const MPoly *mpoly_array, | ||||
| const MeshElemMap *edge_poly_map, | const MeshElemMap *edge_poly_map, | ||||
| void *user_data); | void *user_data); | ||||
| static void poly_edge_loop_islands_calc(const MEdge *medge, | static void poly_edge_loop_islands_calc(const MEdge *medge, | ||||
| const int totedge, | const int totedge, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const int totpoly, | const int totpoly, | ||||
| const MLoop *mloop, | const int *corner_edges, | ||||
| const int totloop, | const int totloop, | ||||
| const bool *sharp_edges, | const bool *sharp_edges, | ||||
| MeshElemMap *edge_poly_map, | MeshElemMap *edge_poly_map, | ||||
| const bool use_bitflags, | const bool use_bitflags, | ||||
| MeshRemap_CheckIslandBoundary edge_boundary_check, | MeshRemap_CheckIslandBoundary edge_boundary_check, | ||||
| void *edge_boundary_check_data, | void *edge_boundary_check_data, | ||||
| int **r_poly_groups, | int **r_poly_groups, | ||||
| int *r_totgroup, | int *r_totgroup, | ||||
| Show All 30 Lines | static void poly_edge_loop_islands_calc(const MEdge *medge, | ||||
| if (r_edge_borders) { | if (r_edge_borders) { | ||||
| edge_borders = BLI_BITMAP_NEW(totedge, __func__); | edge_borders = BLI_BITMAP_NEW(totedge, __func__); | ||||
| *r_totedgeborder = 0; | *r_totedgeborder = 0; | ||||
| } | } | ||||
| if (!edge_poly_map) { | if (!edge_poly_map) { | ||||
| BKE_mesh_edge_poly_map_create( | BKE_mesh_edge_poly_map_create( | ||||
| &edge_poly_map, &edge_poly_mem, medge, totedge, mpoly, totpoly, mloop, totloop); | &edge_poly_map, &edge_poly_mem, medge, totedge, mpoly, totpoly, corner_edges, totloop); | ||||
| } | } | ||||
| poly_groups = static_cast<int *>(MEM_callocN(sizeof(int) * size_t(totpoly), __func__)); | poly_groups = static_cast<int *>(MEM_callocN(sizeof(int) * size_t(totpoly), __func__)); | ||||
| poly_stack = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totpoly), __func__)); | poly_stack = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totpoly), __func__)); | ||||
| while (true) { | while (true) { | ||||
| int poly; | int poly; | ||||
| int bit_poly_group_mask = 0; | int bit_poly_group_mask = 0; | ||||
| Show All 16 Lines | while (true) { | ||||
| /* start searching from here next time */ | /* start searching from here next time */ | ||||
| poly_prev = poly + 1; | poly_prev = poly + 1; | ||||
| poly_groups[poly] = poly_group_id; | poly_groups[poly] = poly_group_id; | ||||
| poly_stack[ps_end_idx++] = poly; | poly_stack[ps_end_idx++] = poly; | ||||
| while (ps_curr_idx != ps_end_idx) { | while (ps_curr_idx != ps_end_idx) { | ||||
| const MPoly *mp; | const MPoly *mp; | ||||
| const MLoop *ml; | |||||
| int j; | |||||
| poly = poly_stack[ps_curr_idx++]; | poly = poly_stack[ps_curr_idx++]; | ||||
| BLI_assert(poly_groups[poly] == poly_group_id); | BLI_assert(poly_groups[poly] == poly_group_id); | ||||
| mp = &mpoly[poly]; | mp = &mpoly[poly]; | ||||
| for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) { | for (const int64_t corner : blender::IndexRange(mp->loopstart, mp->totloop)) { | ||||
| /* loop over poly users */ | /* loop over poly users */ | ||||
| const int me_idx = int(ml->e); | const int me_idx = corner_edges[corner]; | ||||
| const MEdge *me = &medge[me_idx]; | const MEdge *me = &medge[me_idx]; | ||||
| const MeshElemMap *map_ele = &edge_poly_map[me_idx]; | const MeshElemMap *map_ele = &edge_poly_map[me_idx]; | ||||
| const int *p = map_ele->indices; | const int *p = map_ele->indices; | ||||
| int i = map_ele->count; | int i = map_ele->count; | ||||
| if (!edge_boundary_check( | if (!edge_boundary_check(mp, | ||||
| mp, ml, me, me_idx, sharp_edges, i, mpoly, map_ele, edge_boundary_check_data)) { | int(corner), | ||||
| me, | |||||
| me_idx, | |||||
| sharp_edges, | |||||
| i, | |||||
| mpoly, | |||||
| map_ele, | |||||
| edge_boundary_check_data)) { | |||||
| for (; i--; p++) { | for (; i--; p++) { | ||||
| /* if we meet other non initialized its a bug */ | /* if we meet other non initialized its a bug */ | ||||
| BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); | BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); | ||||
| if (poly_groups[*p] == 0) { | if (poly_groups[*p] == 0) { | ||||
| poly_groups[*p] = poly_group_id; | poly_groups[*p] = poly_group_id; | ||||
| poly_stack[ps_end_idx++] = *p; | poly_stack[ps_end_idx++] = *p; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | static void poly_edge_loop_islands_calc(const MEdge *medge, | ||||
| *r_poly_groups = poly_groups; | *r_poly_groups = poly_groups; | ||||
| if (r_edge_borders) { | if (r_edge_borders) { | ||||
| *r_edge_borders = edge_borders; | *r_edge_borders = edge_borders; | ||||
| *r_totedgeborder = num_edgeborders; | *r_totedgeborder = num_edgeborders; | ||||
| } | } | ||||
| } | } | ||||
| static bool poly_is_island_boundary_smooth_cb(const MPoly *mp, | static bool poly_is_island_boundary_smooth_cb(const MPoly *mp, | ||||
| const MLoop * /*ml*/, | const int /*corner*/, | ||||
| const MEdge * /*me*/, | const MEdge * /*me*/, | ||||
| const int edge_index, | const int edge_index, | ||||
| const bool *sharp_edges, | const bool *sharp_edges, | ||||
| const int edge_user_count, | const int edge_user_count, | ||||
| const MPoly *mpoly_array, | const MPoly *mpoly_array, | ||||
| const MeshElemMap *edge_poly_map, | const MeshElemMap *edge_poly_map, | ||||
| void * /*user_data*/) | void * /*user_data*/) | ||||
| { | { | ||||
| Show All 9 Lines | static bool poly_is_island_boundary_smooth_cb(const MPoly *mp, | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| int *BKE_mesh_calc_smoothgroups(const MEdge *medge, | int *BKE_mesh_calc_smoothgroups(const MEdge *medge, | ||||
| const int totedge, | const int totedge, | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const int totpoly, | const int totpoly, | ||||
| const MLoop *mloop, | const int *corner_edges, | ||||
| const int totloop, | const int totloop, | ||||
| const bool *sharp_edges, | const bool *sharp_edges, | ||||
| int *r_totgroup, | int *r_totgroup, | ||||
| const bool use_bitflags) | const bool use_bitflags) | ||||
| { | { | ||||
| int *poly_groups = nullptr; | int *poly_groups = nullptr; | ||||
| poly_edge_loop_islands_calc(medge, | poly_edge_loop_islands_calc(medge, | ||||
| totedge, | totedge, | ||||
| mpoly, | mpoly, | ||||
| totpoly, | totpoly, | ||||
| mloop, | corner_edges, | ||||
| totloop, | totloop, | ||||
| sharp_edges, | sharp_edges, | ||||
| nullptr, | nullptr, | ||||
| use_bitflags, | use_bitflags, | ||||
| poly_is_island_boundary_smooth_cb, | poly_is_island_boundary_smooth_cb, | ||||
| nullptr, | nullptr, | ||||
| &poly_groups, | &poly_groups, | ||||
| r_totgroup, | r_totgroup, | ||||
| ▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | |||||
| /* TODO: I'm not sure edge seam flag is enough to define UV islands? | /* TODO: I'm not sure edge seam flag is enough to define UV islands? | ||||
| * Maybe we should also consider UV-maps values | * Maybe we should also consider UV-maps values | ||||
| * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?). | * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?). | ||||
| * Would make things much more complex though, | * Would make things much more complex though, | ||||
| * and each UVMap would then need its own mesh mapping, not sure we want that at all! | * and each UVMap would then need its own mesh mapping, not sure we want that at all! | ||||
| */ | */ | ||||
| struct MeshCheckIslandBoundaryUv { | struct MeshCheckIslandBoundaryUv { | ||||
| const MLoop *loops; | const int *corner_verts; | ||||
| const int *corner_edges; | |||||
| const float (*luvs)[2]; | const float (*luvs)[2]; | ||||
| const MeshElemMap *edge_loop_map; | const MeshElemMap *edge_loop_map; | ||||
| }; | }; | ||||
| static bool mesh_check_island_boundary_uv(const MPoly * /*mp*/, | static bool mesh_check_island_boundary_uv(const MPoly * /*mp*/, | ||||
| const MLoop *ml, | const int corner, | ||||
| const MEdge *me, | const MEdge *me, | ||||
| const int /*edge_index*/, | const int /*edge_index*/, | ||||
| const bool * /*sharp_edges*/, | const bool * /*sharp_edges*/, | ||||
| const int /*edge_user_count*/, | const int /*edge_user_count*/, | ||||
| const MPoly * /*mpoly_array*/, | const MPoly * /*mpoly_array*/, | ||||
| const MeshElemMap * /*edge_poly_map*/, | const MeshElemMap * /*edge_poly_map*/, | ||||
| void *user_data) | void *user_data) | ||||
| { | { | ||||
| if (user_data) { | if (user_data) { | ||||
| const MeshCheckIslandBoundaryUv *data = static_cast<const MeshCheckIslandBoundaryUv *>( | const MeshCheckIslandBoundaryUv *data = static_cast<const MeshCheckIslandBoundaryUv *>( | ||||
| user_data); | user_data); | ||||
| const MLoop *loops = data->loops; | const int *corner_verts = data->corner_verts; | ||||
| const float(*luvs)[2] = data->luvs; | const float(*luvs)[2] = data->luvs; | ||||
| const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e]; | const MeshElemMap *edge_to_loops = &data->edge_loop_map[data->corner_edges[corner]]; | ||||
| BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0); | BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0); | ||||
| const uint v1 = loops[edge_to_loops->indices[0]].v; | const int v1 = corner_verts[edge_to_loops->indices[0]]; | ||||
| const uint v2 = loops[edge_to_loops->indices[1]].v; | const int v2 = corner_verts[edge_to_loops->indices[1]]; | ||||
| const float *uvco_v1 = luvs[edge_to_loops->indices[0]]; | const float *uvco_v1 = luvs[edge_to_loops->indices[0]]; | ||||
| const float *uvco_v2 = luvs[edge_to_loops->indices[1]]; | const float *uvco_v2 = luvs[edge_to_loops->indices[1]]; | ||||
| for (int i = 2; i < edge_to_loops->count; i += 2) { | for (int i = 2; i < edge_to_loops->count; i += 2) { | ||||
| if (loops[edge_to_loops->indices[i]].v == v1) { | if (corner_verts[edge_to_loops->indices[i]] == v1) { | ||||
| if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]]) || | if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]]) || | ||||
| !equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]])) { | !equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]])) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(loops[edge_to_loops->indices[i]].v == v2); | BLI_assert(corner_verts[edge_to_loops->indices[i]] == v2); | ||||
| UNUSED_VARS_NDEBUG(v2); | UNUSED_VARS_NDEBUG(v2); | ||||
| if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]]) || | if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]]) || | ||||
| !equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]])) { | !equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]])) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Edge is UV boundary if tagged as seam. */ | /* Edge is UV boundary if tagged as seam. */ | ||||
| return (me->flag & ME_SEAM) != 0; | return (me->flag & ME_SEAM) != 0; | ||||
| } | } | ||||
| static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges, | static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges, | ||||
| const int totedge, | const int totedge, | ||||
| const MPoly *polys, | const MPoly *polys, | ||||
| const int totpoly, | const int totpoly, | ||||
| const MLoop *loops, | const int *corner_verts, | ||||
| const int *corner_edges, | |||||
| const int totloop, | const int totloop, | ||||
| const float (*luvs)[2], | const float (*luvs)[2], | ||||
| MeshIslandStore *r_island_store) | MeshIslandStore *r_island_store) | ||||
| { | { | ||||
| int *poly_groups = nullptr; | int *poly_groups = nullptr; | ||||
| int num_poly_groups; | int num_poly_groups; | ||||
| /* map vars */ | /* map vars */ | ||||
| Show All 20 Lines | static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges, | ||||
| int grp_idx, p_idx, pl_idx, l_idx; | int grp_idx, p_idx, pl_idx, l_idx; | ||||
| BKE_mesh_loop_islands_clear(r_island_store); | BKE_mesh_loop_islands_clear(r_island_store); | ||||
| BKE_mesh_loop_islands_init( | BKE_mesh_loop_islands_init( | ||||
| r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE); | r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE); | ||||
| BKE_mesh_edge_poly_map_create( | BKE_mesh_edge_poly_map_create( | ||||
| &edge_poly_map, &edge_poly_mem, edges, totedge, polys, totpoly, loops, totloop); | &edge_poly_map, &edge_poly_mem, edges, totedge, polys, totpoly, corner_edges, totloop); | ||||
| if (luvs) { | if (luvs) { | ||||
| BKE_mesh_edge_loop_map_create( | BKE_mesh_edge_loop_map_create( | ||||
| &edge_loop_map, &edge_loop_mem, edges, totedge, polys, totpoly, loops, totloop); | &edge_loop_map, &edge_loop_mem, edges, totedge, polys, totpoly, corner_edges, totloop); | ||||
| edge_boundary_check_data.loops = loops; | edge_boundary_check_data.corner_verts = corner_verts; | ||||
| edge_boundary_check_data.corner_edges = corner_edges; | |||||
| edge_boundary_check_data.luvs = luvs; | edge_boundary_check_data.luvs = luvs; | ||||
| edge_boundary_check_data.edge_loop_map = edge_loop_map; | edge_boundary_check_data.edge_loop_map = edge_loop_map; | ||||
| } | } | ||||
| poly_edge_loop_islands_calc(edges, | poly_edge_loop_islands_calc(edges, | ||||
| totedge, | totedge, | ||||
| polys, | polys, | ||||
| totpoly, | totpoly, | ||||
| loops, | corner_edges, | ||||
| totloop, | totloop, | ||||
| nullptr, | nullptr, | ||||
| edge_poly_map, | edge_poly_map, | ||||
| false, | false, | ||||
| mesh_check_island_boundary_uv, | mesh_check_island_boundary_uv, | ||||
| luvs ? &edge_boundary_check_data : nullptr, | luvs ? &edge_boundary_check_data : nullptr, | ||||
| &poly_groups, | &poly_groups, | ||||
| &num_poly_groups, | &num_poly_groups, | ||||
| Show All 33 Lines | for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) { | ||||
| for (p_idx = 0; p_idx < totpoly; p_idx++) { | for (p_idx = 0; p_idx < totpoly; p_idx++) { | ||||
| if (poly_groups[p_idx] != grp_idx) { | if (poly_groups[p_idx] != grp_idx) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| const MPoly *mp = &polys[p_idx]; | const MPoly *mp = &polys[p_idx]; | ||||
| poly_indices[num_pidx++] = p_idx; | poly_indices[num_pidx++] = p_idx; | ||||
| for (l_idx = mp->loopstart, pl_idx = 0; pl_idx < mp->totloop; l_idx++, pl_idx++) { | for (l_idx = mp->loopstart, pl_idx = 0; pl_idx < mp->totloop; l_idx++, pl_idx++) { | ||||
| const MLoop *ml = &loops[l_idx]; | const int edge_i = corner_edges[l_idx]; | ||||
| loop_indices[num_lidx++] = l_idx; | loop_indices[num_lidx++] = l_idx; | ||||
| if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, ml->e) && | if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, edge_i) && | ||||
| (edge_border_count[ml->e] < 2)) { | (edge_border_count[edge_i] < 2)) { | ||||
| edge_border_count[ml->e]++; | edge_border_count[edge_i]++; | ||||
| if (edge_border_count[ml->e] == 2) { | if (edge_border_count[edge_i] == 2) { | ||||
| edge_innercut_indices[num_einnercuts++] = int(ml->e); | edge_innercut_indices[num_einnercuts++] = edge_i; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BKE_mesh_loop_islands_add(r_island_store, | BKE_mesh_loop_islands_add(r_island_store, | ||||
| num_lidx, | num_lidx, | ||||
| loop_indices, | loop_indices, | ||||
| Show All 27 Lines | |||||
| } | } | ||||
| bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3], | bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3], | ||||
| const int totvert, | const int totvert, | ||||
| const MEdge *edges, | const MEdge *edges, | ||||
| const int totedge, | const int totedge, | ||||
| const MPoly *polys, | const MPoly *polys, | ||||
| const int totpoly, | const int totpoly, | ||||
| const MLoop *loops, | const int *corner_verts, | ||||
| const int *corner_edges, | |||||
| const int totloop, | const int totloop, | ||||
| MeshIslandStore *r_island_store) | MeshIslandStore *r_island_store) | ||||
| { | { | ||||
| UNUSED_VARS(vert_positions, totvert); | UNUSED_VARS(vert_positions, totvert); | ||||
| return mesh_calc_islands_loop_poly_uv( | return mesh_calc_islands_loop_poly_uv(edges, | ||||
| edges, totedge, polys, totpoly, loops, totloop, nullptr, r_island_store); | totedge, | ||||
| polys, | |||||
| totpoly, | |||||
| corner_verts, | |||||
| corner_edges, | |||||
| totloop, | |||||
| nullptr, | |||||
| r_island_store); | |||||
| } | } | ||||
| bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], | bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], | ||||
| const int totvert, | const int totvert, | ||||
| MEdge *edges, | MEdge *edges, | ||||
| const int totedge, | const int totedge, | ||||
| MPoly *polys, | MPoly *polys, | ||||
| const int totpoly, | const int totpoly, | ||||
| MLoop *loops, | const int *corner_verts, | ||||
| const int *corner_edges, | |||||
| const int totloop, | const int totloop, | ||||
| const float (*luvs)[2], | const float (*luvs)[2], | ||||
| MeshIslandStore *r_island_store) | MeshIslandStore *r_island_store) | ||||
| { | { | ||||
| UNUSED_VARS(vert_positions, totvert); | UNUSED_VARS(vert_positions, totvert); | ||||
| BLI_assert(luvs != nullptr); | BLI_assert(luvs != nullptr); | ||||
| return mesh_calc_islands_loop_poly_uv( | return mesh_calc_islands_loop_poly_uv( | ||||
| edges, totedge, polys, totpoly, loops, totloop, luvs, r_island_store); | edges, totedge, polys, totpoly, corner_verts, corner_edges, totloop, luvs, r_island_store); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||