diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index 8a0ae63ce72..10c450cb6ec 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -29,7 +29,8 @@ struct MFace; void BKE_mesh_legacy_convert_uvs_to_struct( Mesh *mesh, blender::ResourceScope &temp_mloopuv_for_convert, - blender::Vector &loop_layers_to_write); + blender::Vector &loop_layers_to_write, + const int mesh_ldata_totlayer_real); void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh); /** @@ -121,6 +122,8 @@ struct MLoop *BKE_mesh_legacy_convert_corners_to_loops( void BKE_mesh_legacy_convert_loops_to_corners(struct Mesh *mesh); +void BKE_mesh_assert_customdata_alloc(Mesh *mesh); + /** * Recreate #MFace Tessellation. * diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index cf71ecf0270..29acb05969a 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -253,6 +253,8 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address } else { Set names_to_skip; + + const int mesh_ldata_totlayer_real = mesh->ldata.totlayer; if (!BLO_write_is_undo(writer)) { /* When converting to the old mesh format, don't save redundant attributes. */ names_to_skip.add_multiple_new({"position", @@ -296,7 +298,11 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address CustomData_blend_write_prepare(mesh->pdata, poly_layers, names_to_skip); if (!BLO_write_is_undo(writer)) { - BKE_mesh_legacy_convert_uvs_to_struct(mesh, temp_arrays_for_legacy_format, loop_layers); + /* If ASAN isn't doing it's job, assert! */ + // BKE_mesh_assert_customdata_alloc(mesh); + + BKE_mesh_legacy_convert_uvs_to_struct( + mesh, temp_arrays_for_legacy_format, loop_layers, mesh_ldata_totlayer_real); BKE_mesh_legacy_face_set_from_generic(poly_layers); } } diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index b6977cd9855..63f5741bf37 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -1658,7 +1658,8 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh) void BKE_mesh_legacy_convert_uvs_to_struct( Mesh *mesh, blender::ResourceScope &temp_mloopuv_for_convert, - blender::Vector &loop_layers_to_write) + blender::Vector &loop_layers_to_write, + const int mesh_ldata_totlayer_real) { using namespace blender; using namespace blender::bke; @@ -1693,6 +1694,10 @@ void BKE_mesh_legacy_convert_uvs_to_struct( mesh->totloop); mloopuv_layer.data = mloopuv.data(); + /* FIXME: proof of concept, works but should not be necessary. */ + const int mesh_ldata_totlayer_for_write = mesh->ldata.totlayer; + mesh->ldata.totlayer = mesh_ldata_totlayer_real; + char buffer[MAX_CUSTOMDATA_LAYER_NAME]; const bool *vert_selection = static_cast(CustomData_get_layer_named( &mesh->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(layer.name, buffer))); @@ -1701,6 +1706,8 @@ void BKE_mesh_legacy_convert_uvs_to_struct( const bool *pin = static_cast(CustomData_get_layer_named( &mesh->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer.name, buffer))); + mesh->ldata.totlayer = mesh_ldata_totlayer_for_write; + threading::parallel_for(mloopuv.index_range(), 2048, [&](IndexRange range) { for (const int i : range) { copy_v2_v2(mloopuv[i].uv, coords[i]); @@ -2183,3 +2190,12 @@ void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh) } /** \} */ + +void BKE_mesh_assert_customdata_alloc(Mesh *mesh) +{ + CustomData *cdata[] = {&mesh->vdata, &mesh->edata, &mesh->ldata, &mesh->pdata}; + for (size_t i = 0; i < ARRAY_SIZE(cdata); i++) { + BLI_assert(int(MEM_allocN_len(cdata[i]->layers) / sizeof(*cdata[i]->layers)) >= + cdata[i]->totlayer); + } +}