Fix: Invalid custom data read during legacy mesh format conversion

In a previous step of the mesh writing process, the loop `totlayer` was
replaced and a temporary vector is used for layer data instead. Use this
temporary vector to find the UV sub-layers, since the vector and the
CustomData struct in the mesh don't necessarily match. Also use a
local variable for mesh loop count to make it clearer that the mesh
isn't used except at the end.

Thanks to Campbell for finding the source of this error.
This commit is contained in:
Hans Goudey
2023-03-19 23:24:52 -04:00
parent f23e3c7f04
commit de49d18af5

View File

@@ -1551,6 +1551,19 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh)
/** \name Generic UV Map Conversion
* \{ */
static const bool *layers_find_bool_named(const Span<CustomDataLayer> layers,
const blender::StringRef name)
{
for (const CustomDataLayer &layer : layers) {
if (layer.type == CD_PROP_BOOL) {
if (layer.name == name) {
return static_cast<const bool *>(layer.data);
}
}
}
return nullptr;
}
void BKE_mesh_legacy_convert_uvs_to_struct(
Mesh *mesh,
blender::ResourceScope &temp_mloopuv_for_convert,
@@ -1558,6 +1571,7 @@ void BKE_mesh_legacy_convert_uvs_to_struct(
{
using namespace blender;
using namespace blender::bke;
const int loops_num = mesh->totloop;
Vector<CustomDataLayer, 16> new_layer_to_write;
/* Don't write the boolean UV map sublayers which will be written in the legacy #MLoopUV type. */
@@ -1582,20 +1596,19 @@ void BKE_mesh_legacy_convert_uvs_to_struct(
new_layer_to_write.append(layer);
continue;
}
const Span<float2> coords{static_cast<const float2 *>(layer.data), mesh->totloop};
const Span<float2> coords{static_cast<const float2 *>(layer.data), loops_num};
CustomDataLayer mloopuv_layer = layer;
mloopuv_layer.type = CD_MLOOPUV;
MutableSpan<MLoopUV> mloopuv = temp_mloopuv_for_convert.construct<Array<MLoopUV>>(
mesh->totloop);
MutableSpan<MLoopUV> mloopuv = temp_mloopuv_for_convert.construct<Array<MLoopUV>>(loops_num);
mloopuv_layer.data = mloopuv.data();
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const bool *vert_selection = static_cast<const bool *>(CustomData_get_layer_named(
&mesh->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(layer.name, buffer)));
const bool *edge_selection = static_cast<const bool *>(CustomData_get_layer_named(
&mesh->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(layer.name, buffer)));
const bool *pin = static_cast<const bool *>(CustomData_get_layer_named(
&mesh->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer.name, buffer)));
const bool *vert_selection = layers_find_bool_named(
loop_layers_to_write, BKE_uv_map_vert_select_name_get(layer.name, buffer));
const bool *edge_selection = layers_find_bool_named(
loop_layers_to_write, BKE_uv_map_edge_select_name_get(layer.name, buffer));
const bool *pin = layers_find_bool_named(loop_layers_to_write,
BKE_uv_map_pin_name_get(layer.name, buffer));
threading::parallel_for(mloopuv.index_range(), 2048, [&](IndexRange range) {
for (const int i : range) {