Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_mapping.cc
| Show All 28 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 MLoop *mloop, | ||||
| const MLoopUV *mloopuv, | 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; | ||||
| UvMapVert *buf; | UvMapVert *buf; | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) { | ||||
| 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[mloop[mp->loopstart + i].v]; | ||||
| vmap->vert[mloop[mp->loopstart + i].v] = buf; | vmap->vert[mloop[mp->loopstart + i].v] = buf; | ||||
| if (use_winding) { | if (use_winding) { | ||||
| copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv); | copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i]); | ||||
| } | } | ||||
| buf++; | buf++; | ||||
| } | } | ||||
| if (use_winding) { | if (use_winding) { | ||||
| winding[a] = cross_poly_v2(tf_uv, uint(nverts)) > 0; | winding[a] = cross_poly_v2(tf_uv, uint(nverts)) > 0; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* sort individual uvs for each vert */ | /* sort individual uvs for each vert */ | ||||
| for (a = 0; a < totvert; a++) { | for (a = 0; a < totvert; a++) { | ||||
| UvMapVert *newvlist = nullptr, *vlist = vmap->vert[a]; | UvMapVert *newvlist = nullptr, *vlist = vmap->vert[a]; | ||||
| UvMapVert *iterv, *v, *lastv, *next; | UvMapVert *iterv, *v, *lastv, *next; | ||||
| const float *uv, *uv2; | const float *uv, *uv2; | ||||
| float uvdiff[2]; | float uvdiff[2]; | ||||
| while (vlist) { | while (vlist) { | ||||
| v = vlist; | v = vlist; | ||||
| vlist = vlist->next; | vlist = vlist->next; | ||||
| v->next = newvlist; | v->next = newvlist; | ||||
| newvlist = v; | newvlist = v; | ||||
| uv = mloopuv[mpoly[v->poly_index].loopstart + v->loop_of_poly_index].uv; | uv = mloopuv[mpoly[v->poly_index].loopstart + v->loop_of_poly_index]; | ||||
| lastv = nullptr; | lastv = nullptr; | ||||
| iterv = vlist; | iterv = vlist; | ||||
| while (iterv) { | while (iterv) { | ||||
| next = iterv->next; | next = iterv->next; | ||||
| uv2 = mloopuv[mpoly[iterv->poly_index].loopstart + iterv->loop_of_poly_index].uv; | uv2 = mloopuv[mpoly[iterv->poly_index].loopstart + iterv->loop_of_poly_index]; | ||||
| sub_v2_v2v2(uvdiff, uv2, uv); | sub_v2_v2v2(uvdiff, uv2, uv); | ||||
| if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] && | if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] && | ||||
| (!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) { | (!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) { | ||||
| if (lastv) { | if (lastv) { | ||||
| lastv->next = next; | lastv->next = next; | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 860 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 MLoop *loops; | ||||
| const MLoopUV *luvs; | 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 MLoop *ml, | ||||
| const MEdge *me, | const MEdge *me, | ||||
| 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 MLoop *loops = data->loops; | ||||
| const MLoopUV *luvs = 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[ml->e]; | ||||
| 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 uint v1 = loops[edge_to_loops->indices[0]].v; | ||||
| const uint v2 = loops[edge_to_loops->indices[1]].v; | const uint v2 = loops[edge_to_loops->indices[1]].v; | ||||
| const float *uvco_v1 = luvs[edge_to_loops->indices[0]].uv; | const float *uvco_v1 = luvs[edge_to_loops->indices[0]]; | ||||
| const float *uvco_v2 = luvs[edge_to_loops->indices[1]].uv; | 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 (loops[edge_to_loops->indices[i]].v == v1) { | ||||
| if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]].uv) || | if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]]) || | ||||
| !equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]].uv)) { | !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(loops[edge_to_loops->indices[i]].v == v2); | ||||
| UNUSED_VARS_NDEBUG(v2); | UNUSED_VARS_NDEBUG(v2); | ||||
| if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]].uv) || | if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]]) || | ||||
| !equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]].uv)) { | !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 MLoop *loops, | ||||
| const int totloop, | const int totloop, | ||||
| const MLoopUV *luvs, | 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 */ | ||||
| MeshElemMap *edge_poly_map; | MeshElemMap *edge_poly_map; | ||||
| int *edge_poly_mem; | int *edge_poly_mem; | ||||
| ▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | |||||
| 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, | MLoop *loops, | ||||
| const int totloop, | const int totloop, | ||||
| const MLoopUV *luvs, | 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, loops, totloop, luvs, r_island_store); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||