Cleanup: Improve BKE_mesh_uv_vert_map_create arguments

Use Span and modern naming for mesh data.
This commit is contained in:
Hans Goudey
2025-07-18 16:13:40 -04:00
committed by Hans Goudey
parent a9865f5119
commit dfeb425e51
4 changed files with 41 additions and 31 deletions

View File

@@ -100,10 +100,10 @@ struct MeshElemMap {
/* mapping */
UvVertMap *BKE_mesh_uv_vert_map_create(blender::OffsetIndices<int> faces,
const int *corner_verts,
const float (*mloopuv)[2],
unsigned int totvert,
const float limit[2],
blender::Span<int> corner_verts,
blender::Span<blender::float2> uv_map,
int verts_num,
const blender::float2 &limit,
bool use_winding);
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);

View File

@@ -35,17 +35,16 @@
/** \name Mesh Connectivity Mapping
* \{ */
UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
const int *corner_verts,
const float (*mloopuv)[2],
uint totvert,
const float limit[2],
const bool use_winding)
UvVertMap *BKE_mesh_uv_vert_map_create(blender::OffsetIndices<int> faces,
blender::Span<int> corner_verts,
blender::Span<blender::float2> uv_map,
int verts_num,
const blender::float2 &limit,
bool use_winding)
{
using namespace blender;
/* NOTE: N-gon version WIP, based on #BM_uv_vert_map_create. */
UvVertMap *vmap;
UvMapVert *buf;
int i, totuv, nverts;
totuv = 0;
@@ -59,9 +58,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
return nullptr;
}
vmap = MEM_callocN<UvVertMap>("UvVertMap");
buf = vmap->buf = MEM_calloc_arrayN<UvMapVert>(size_t(totuv), "UvMapVert");
vmap->vert = MEM_calloc_arrayN<UvMapVert *>(totvert, "UvMapVert*");
UvVertMap *vmap = MEM_callocN<UvVertMap>("UvVertMap");
UvMapVert *buf = vmap->buf = MEM_calloc_arrayN<UvMapVert>(size_t(totuv), "UvMapVert");
vmap->vert = MEM_calloc_arrayN<UvMapVert *>(size_t(verts_num), "UvMapVert*");
if (!vmap->vert || !vmap->buf) {
BKE_mesh_uv_vert_map_free(vmap);
@@ -73,9 +72,9 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
winding = MEM_calloc_arrayN<bool>(size_t(faces.size()), "winding");
}
blender::Vector<blender::float2, 32> face_uvs;
Vector<float2, 32> face_uvs;
for (const int64_t a : faces.index_range()) {
const blender::IndexRange face = faces[a];
const IndexRange face = faces[a];
if (use_winding) {
face_uvs.resize(face.size());
@@ -91,7 +90,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
vmap->vert[corner_verts[face[i]]] = buf;
if (use_winding) {
copy_v2_v2(face_uvs[i], mloopuv[face[i]]);
copy_v2_v2(face_uvs[i], uv_map[face[i]]);
}
buf++;
@@ -104,8 +103,8 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
}
/* sort individual uvs for each vert */
for (uint a = 0; a < totvert; a++) {
UvMapVert *newvlist = nullptr, *vlist = vmap->vert[a];
for (const int64_t vert : IndexRange(verts_num)) {
UvMapVert *newvlist = nullptr, *vlist = vmap->vert[vert];
UvMapVert *iterv, *v, *lastv, *next;
const float *uv, *uv2;
float uvdiff[2];
@@ -116,14 +115,14 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
v->next = newvlist;
newvlist = v;
uv = mloopuv[faces[v->face_index].start() + v->loop_of_face_index];
uv = uv_map[faces[v->face_index].start() + v->loop_of_face_index];
lastv = nullptr;
iterv = vlist;
while (iterv) {
next = iterv->next;
uv2 = mloopuv[faces[iterv->face_index].start() + iterv->loop_of_face_index];
uv2 = uv_map[faces[iterv->face_index].start() + iterv->loop_of_face_index];
sub_v2_v2v2(uvdiff, uv2, uv);
if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
@@ -148,7 +147,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const blender::OffsetIndices<int> faces,
newvlist->separate = true;
}
vmap->vert[a] = newvlist;
vmap->vert[vert] = newvlist;
}
if (use_winding) {

View File

@@ -188,17 +188,22 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la
{
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
const Mesh *mesh = storage->mesh;
const float(*mloopuv)[2] = static_cast<const float(*)[2]>(
CustomData_get_layer_n(&mesh->corner_data, CD_PROP_FLOAT2, layer_index));
const bke::AttributeAccessor attributes = mesh->attributes();
const StringRef name = CustomData_get_layer_name(
&mesh->corner_data, CD_PROP_FLOAT2, layer_index);
const VArraySpan uv_map = *attributes.lookup<float2>(name, bke::AttrDomain::Corner);
const int num_vert = mesh->verts_num;
const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
/* Initialize memory required for the operations. */
if (storage->loop_uv_indices == nullptr) {
storage->loop_uv_indices = MEM_malloc_arrayN<int>(size_t(mesh->corners_num),
"loop uv vertex index");
}
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
storage->faces, storage->corner_verts.data(), mloopuv, num_vert, limit, true);
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(storage->faces,
storage->corner_verts,
uv_map,
num_vert,
blender::float2(STD_UV_CONNECT_LIMIT),
true);
/* NOTE: First UV vertex is supposed to be always marked as separate. */
storage->num_uv_coordinates = -1;
for (int vertex_index = 0; vertex_index < num_vert; vertex_index++) {

View File

@@ -261,15 +261,21 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
UvMapVert *v;
UvVertMap *vmap;
blender::Vector<CCGVertHDL, 16> fverts;
float limit[2];
float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
const int corners_num = faces.total_size();
/* previous behavior here is without accounting for winding, however this causes stretching in
* UV map in really simple cases with mirror + subsurf, see second part of #44530.
* Also, initially intention is to treat merged vertices from mirror modifier as seams.
* This fixes a very old regression (2.49 was correct here) */
vmap = BKE_mesh_uv_vert_map_create(faces, corner_verts, mloopuv, totvert, limit, true);
vmap = BKE_mesh_uv_vert_map_create(
faces,
{corner_verts, corners_num},
{reinterpret_cast<const blender::float2 *>(mloopuv), corners_num},
totvert,
blender::float2(STD_UV_CONNECT_LIMIT),
true);
if (!vmap) {
return 0;
}