|
|
|
|
@@ -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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|