From aedff9dbef6c5847b6d8e855eb64401d44611f20 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 21 Jul 2016 16:53:00 +0200 Subject: Add BKE_mesh_calc_islands_loop_poly_uvmap and use it in new OSD UV subdiv. Also renamed BKE_mesh_calc_islands_loop_poly_uv to BKE_mesh_calc_islands_loop_poly_edgeseam, to avoid confusion... --- source/blender/blenkernel/intern/mesh_mapping.c | 130 ++++++++++++++++++++---- 1 file changed, 109 insertions(+), 21 deletions(-) (limited to 'source/blender/blenkernel/intern/mesh_mapping.c') diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index dc2e95385be..1a20300457f 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -593,12 +593,12 @@ void BKE_mesh_origindex_map_create_looptri( */ typedef bool (*MeshRemap_CheckIslandBoundary)( const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge, - const int nbr_egde_users); + const int nbr_egde_users, void *user_data); static void poly_edge_loop_islands_calc( const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop, MeshElemMap *edge_poly_map, - const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, + const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, void *edge_boundary_check_data, int **r_poly_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, int *r_totedgeborder) { int *poly_groups; @@ -680,7 +680,7 @@ static void poly_edge_loop_islands_calc( const MeshElemMap *map_ele = &edge_poly_map[me_idx]; const int *p = map_ele->indices; int i = map_ele->count; - if (!edge_boundary_check(mp, ml, me, i)) { + if (!edge_boundary_check(mp, ml, me, i, edge_boundary_check_data)) { for (; i--; p++) { /* if we meet other non initialized its a bug */ BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); @@ -772,7 +772,7 @@ static void poly_edge_loop_islands_calc( } static bool poly_is_island_boundary_smooth_cb( - const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users) + const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users, void *UNUSED(user_data)) { /* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */ return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2)); @@ -795,7 +795,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, poly_edge_loop_islands_calc( medge, totedge, mpoly, totpoly, mloop, totloop, NULL, use_bitflags, - poly_is_island_boundary_smooth_cb, &poly_groups, r_totgroup, NULL, NULL); + poly_is_island_boundary_smooth_cb, NULL, &poly_groups, r_totgroup, NULL, NULL); return poly_groups; } @@ -902,28 +902,59 @@ void BKE_mesh_loop_islands_add( * Would make things much more complex though, and each UVMap would then need its own mesh mapping, * not sure we want that at all! */ +typedef struct MeshCheckIslandBoundaryUv { + const MLoop *loops; + const MLoopUV *luvs; + const MeshElemMap *edge_loop_map; +} MeshCheckIslandBoundaryUv; + static bool mesh_check_island_boundary_uv( - const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, const int UNUSED(nbr_egde_users)) + const MPoly *UNUSED(mp), const MLoop *ml, const MEdge *me, + const int UNUSED(nbr_egde_users), void *user_data) { - /* Edge is UV boundary if tagged as seam. */ - return (me->flag & ME_SEAM) != 0; + if (user_data) { + const MeshCheckIslandBoundaryUv *data = user_data; + const MLoop *loops = data->loops; + const MLoopUV *luvs = data->luvs; + const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e]; + + BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0); + + const unsigned int v1 = loops[edge_to_loops->indices[0]].v; + const unsigned int v2 = loops[edge_to_loops->indices[1]].v; + const float *uvco_v1 = luvs[edge_to_loops->indices[0]].uv; + const float *uvco_v2 = luvs[edge_to_loops->indices[1]].uv; + for (int i = 2; i < edge_to_loops->count; i += 2) { + if (loops[edge_to_loops->indices[i]].v == v1) { + if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]].uv) || + !equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]].uv)) + { + return true; + } + } + else { + BLI_assert(loops[edge_to_loops->indices[i]].v == v2); + if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]].uv) || + !equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]].uv)) + { + return true; + } + } + } + return false; + } + else { + /* Edge is UV boundary if tagged as seam. */ + return (me->flag & ME_SEAM) != 0; + } } -/** - * Calculate UV islands. - * - * \note Currently we only consider edges tagges as seams as UV boundaries. This has the advantages of simplicity, - * and being valid/common to all UV maps. However, it means actual UV islands whithout matching UV seams - * will not be handled correctly... - * - * \note All this could be optimized... - * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do... - */ -bool BKE_mesh_calc_islands_loop_poly_uv( +static bool mesh_calc_islands_loop_poly_uv( MVert *UNUSED(verts), const int UNUSED(totvert), MEdge *edges, const int totedge, MPoly *polys, const int totpoly, MLoop *loops, const int totloop, + const MLoopUV *luvs, MeshIslandStore *r_island_store) { int *poly_groups = NULL; @@ -933,6 +964,11 @@ bool BKE_mesh_calc_islands_loop_poly_uv( MeshElemMap *edge_poly_map; int *edge_poly_mem; + MeshElemMap *edge_loop_map; + int *edge_loop_mem; + + MeshCheckIslandBoundaryUv edge_boundary_check_data; + int *poly_indices; int *loop_indices; int num_pidx, num_lidx; @@ -953,9 +989,18 @@ bool BKE_mesh_calc_islands_loop_poly_uv( BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem, edges, totedge, polys, totpoly, loops, totloop); + if (luvs) { + BKE_mesh_edge_loop_map_create(&edge_loop_map, &edge_loop_mem, + edges, totedge, polys, totpoly, loops, totloop); + edge_boundary_check_data.loops = loops; + edge_boundary_check_data.luvs = luvs; + edge_boundary_check_data.edge_loop_map = edge_loop_map; + } + poly_edge_loop_islands_calc( - edges, totedge, polys, totpoly, loops, totloop, edge_poly_map, false, - mesh_check_island_boundary_uv, &poly_groups, &num_poly_groups, &edge_borders, &num_edge_borders); + edges, totedge, polys, totpoly, loops, totloop, edge_poly_map, false, + mesh_check_island_boundary_uv, luvs ? &edge_boundary_check_data : NULL, + &poly_groups, &num_poly_groups, &edge_borders, &num_edge_borders); if (!num_poly_groups) { /* Should never happen... */ @@ -1012,6 +1057,11 @@ bool BKE_mesh_calc_islands_loop_poly_uv( MEM_freeN(edge_poly_map); MEM_freeN(edge_poly_mem); + if (luvs) { + MEM_freeN(edge_loop_map); + MEM_freeN(edge_loop_mem); + } + MEM_freeN(poly_indices); MEM_freeN(loop_indices); MEM_freeN(poly_groups); @@ -1027,4 +1077,42 @@ bool BKE_mesh_calc_islands_loop_poly_uv( return true; } +/** + * Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams), not some UV layers coordinates. + */ +bool BKE_mesh_calc_islands_loop_poly_edgeseam( + MVert *verts, const int totvert, + MEdge *edges, const int totedge, + MPoly *polys, const int totpoly, + MLoop *loops, const int totloop, + MeshIslandStore *r_island_store) +{ + return mesh_calc_islands_loop_poly_uv( + verts, totvert, edges, totedge, polys, totpoly, loops, totloop, NULL, r_island_store); +} + +/** + * Calculate UV islands. + * + * \note If no MLoopUV layer is passed, we only consider edges tagged as seams as UV boundaries. + * This has the advantages of simplicity, and being valid/common to all UV maps. + * However, it means actual UV islands whithout matching UV seams will not be handled correctly... + * If a valid UV layer is passed as \a luvs parameter, UV coordinates are also used to detect islands boundaries. + * + * \note All this could be optimized... + * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do... + */ +bool BKE_mesh_calc_islands_loop_poly_uvmap( + MVert *verts, const int totvert, + MEdge *edges, const int totedge, + MPoly *polys, const int totpoly, + MLoop *loops, const int totloop, + const MLoopUV *luvs, + MeshIslandStore *r_island_store) +{ + BLI_assert(luvs != NULL); + return mesh_calc_islands_loop_poly_uv( + verts, totvert, edges, totedge, polys, totpoly, loops, totloop, luvs, r_island_store); +} + /** \} */ -- cgit v1.2.3