Fix #110471: Normal Edit modifier screws up UVs

The issue was that `CustomData_swap` modifies all layers, but does not ensure
that the layers are actually mutable. This resulted in it modifying shared layers.
Now it ensures that the layers are mutable first (which copies the layers if they
are shared).

Longer term, it would be good to remove `CustomData_swap` since it's not a
good API performance wise, but that is outside of the scope of this patch.

Pull Request: https://projects.blender.org/blender/blender/pulls/110678
This commit is contained in:
Jacques Lucke
2023-08-01 14:27:16 +02:00
parent 8df5968603
commit 09b6eac5c4
6 changed files with 25 additions and 11 deletions

View File

@@ -432,7 +432,7 @@ void CustomData_swap_corners(struct CustomData *data, int index, const int *corn
/**
* Swap two items of given custom data, in all available layers.
*/
void CustomData_swap(struct CustomData *data, int index_a, int index_b);
void CustomData_swap(struct CustomData *data, int index_a, int index_b, const int totelem);
/**
* Retrieve a pointer to an element of the active layer of the given \a type, chosen by the

View File

@@ -550,6 +550,7 @@ void BKE_mesh_face_flip_ex(int face_offset,
int *corner_verts,
int *corner_edges,
struct CustomData *loop_data,
int tot_loop,
float (*lnors)[3],
struct MDisps *mdisp,
bool use_loop_mdisp_flip);
@@ -569,6 +570,7 @@ void BKE_mesh_faces_flip(const int *face_offsets,
int *corner_verts,
int *corner_edges,
struct CustomData *loop_data,
int loops_num,
int faces_num);
/**

View File

@@ -3505,7 +3505,7 @@ void CustomData_swap_corners(CustomData *data, const int index, const int *corne
}
}
void CustomData_swap(CustomData *data, const int index_a, const int index_b)
void CustomData_swap(CustomData *data, const int index_a, const int index_b, const int totelem)
{
char buff_static[256];
@@ -3514,17 +3514,17 @@ void CustomData_swap(CustomData *data, const int index_a, const int index_b)
}
for (int i = 0; i < data->totlayer; i++) {
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
CustomDataLayer &layer = data->layers[i];
ensure_layer_data_is_mutable(layer, totelem);
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(layer.type));
const size_t size = typeInfo->size;
const size_t offset_a = size * index_a;
const size_t offset_b = size * index_b;
void *buff = size <= sizeof(buff_static) ? buff_static : MEM_mallocN(size, __func__);
memcpy(buff, POINTER_OFFSET(data->layers[i].data, offset_a), size);
memcpy(POINTER_OFFSET(data->layers[i].data, offset_a),
POINTER_OFFSET(data->layers[i].data, offset_b),
size);
memcpy(POINTER_OFFSET(data->layers[i].data, offset_b), buff, size);
memcpy(buff, POINTER_OFFSET(layer.data, offset_a), size);
memcpy(POINTER_OFFSET(layer.data, offset_a), POINTER_OFFSET(layer.data, offset_b), size);
memcpy(POINTER_OFFSET(layer.data, offset_b), buff, size);
if (buff != buff_static) {
MEM_freeN(buff);

View File

@@ -503,6 +503,7 @@ void BKE_mesh_face_flip_ex(const int face_offset,
int *corner_verts,
int *corner_edges,
CustomData *loop_data,
int tot_loop,
float (*lnors)[3],
MDisps *mdisp,
const bool use_loop_mdisp_flip)
@@ -541,7 +542,7 @@ void BKE_mesh_face_flip_ex(const int face_offset,
if (lnors) {
swap_v3_v3(lnors[loopstart], lnors[loopend]);
}
CustomData_swap(loop_data, loopstart, loopend);
CustomData_swap(loop_data, loopstart, loopend, tot_loop);
}
/* Even if we did not swap the other 'pivot' loop, we need to set its swapped edge. */
if (loopstart == loopend) {
@@ -557,14 +558,22 @@ void BKE_mesh_face_flip(const int face_offset,
const int totloop)
{
MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(loop_data, CD_MDISPS, totloop);
BKE_mesh_face_flip_ex(
face_offset, face_size, corner_verts, corner_edges, loop_data, nullptr, mdisp, true);
BKE_mesh_face_flip_ex(face_offset,
face_size,
corner_verts,
corner_edges,
loop_data,
totloop,
nullptr,
mdisp,
true);
}
void BKE_mesh_faces_flip(const int *face_offsets,
int *corner_verts,
int *corner_edges,
CustomData *loop_data,
int loops_num,
int faces_num)
{
const blender::OffsetIndices faces(blender::Span(face_offsets, faces_num + 1));
@@ -575,6 +584,7 @@ void BKE_mesh_faces_flip(const int *face_offsets,
corner_verts,
corner_edges,
loop_data,
loops_num,
nullptr,
mdisp,
true);

View File

@@ -164,6 +164,7 @@ static void rna_Mesh_flip_normals(Mesh *mesh)
mesh->corner_verts_for_write().data(),
mesh->corner_edges_for_write().data(),
&mesh->loop_data,
mesh->totloop,
mesh->faces_num);
BKE_mesh_tessface_clear(mesh);
BKE_mesh_runtime_clear_geometry(mesh);

View File

@@ -211,6 +211,7 @@ static bool faces_check_flip(blender::MutableSpan<int> corner_verts,
corner_verts.data(),
corner_edges.data(),
ldata,
corner_edges.size(),
reinterpret_cast<float(*)[3]>(nos),
mdisp,
true);