diff options
author | Sybren A. Stüvel <sybren@blender.org> | 2020-05-12 14:21:17 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@blender.org> | 2020-05-12 14:58:40 +0300 |
commit | 973ab436f07c652cb6aa13bedc351df06bce6561 (patch) | |
tree | 166b4cac5199e5379524fb46c21443715885baa4 /source/blender/io/alembic/intern | |
parent | fffcb6e48068d77de6bbaaf35ef30515d1078dac (diff) |
Fix T76514: Invalid geometry in Alembic crashes Blender
Even though {T76514} is caused by invalid geometry, and thus technically
constitutes a bug in the software that created the Alembic file, I would
like Blender not to crash on importing such a file.
The error in the Alembic file consists of invalid mesh loops, where
consecutive loops refer to the same vertex. The `BKE_mesh_validate()`
can actually correct these errors, so this commit focuses on two things:
- Letting Blender survive the situation until the mesh is loaded, and
- Detecting the error so that `BKE_mesh_validate()` can be called only
when necessary. This ensures there is only a minimal impact on
performance when loading actually valid data.
Differential Revision: https://developer.blender.org/D7703
Reviewed By: JacquesLucke
Diffstat (limited to 'source/blender/io/alembic/intern')
-rw-r--r-- | source/blender/io/alembic/intern/abc_customdata.h | 5 | ||||
-rw-r--r-- | source/blender/io/alembic/intern/abc_reader_mesh.cc | 16 |
2 files changed, 20 insertions, 1 deletions
diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index 6107e230627..11b005eb66a 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -68,6 +68,8 @@ struct CDStreamConfig { Alembic::AbcGeom::index_t index; Alembic::AbcGeom::index_t ceil_index; + const char **modifier_error_message; + CDStreamConfig() : mloop(NULL), totloop(0), @@ -80,7 +82,8 @@ struct CDStreamConfig { weight(0.0f), time(0.0f), index(0), - ceil_index(0) + ceil_index(0), + modifier_error_message(NULL) { } }; diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index ec74fb2137e..b85bce3e10a 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -201,6 +201,7 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) unsigned int loop_index = 0; unsigned int rev_loop_index = 0; unsigned int uv_index = 0; + bool seen_invalid_geometry = false; for (int i = 0; i < face_counts->size(); i++) { const int face_size = (*face_counts)[i]; @@ -216,10 +217,18 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) /* NOTE: Alembic data is stored in the reverse order. */ rev_loop_index = loop_index + (face_size - 1); + uint last_vertex_index = 0; for (int f = 0; f < face_size; f++, loop_index++, rev_loop_index--) { MLoop &loop = mloops[rev_loop_index]; loop.v = (*face_indices)[loop_index]; + if (f > 0 && loop.v == last_vertex_index) { + /* This face is invalid, as it has consecutive loops from the same vertex. This is caused + * by invalid geometry in the Alembic file, such as in T76514. */ + seen_invalid_geometry = true; + } + last_vertex_index = loop.v; + if (do_uvs) { MLoopUV &loopuv = mloopuvs[rev_loop_index]; @@ -237,6 +246,12 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) } BKE_mesh_calc_edges(config.mesh, false, false); + if (seen_invalid_geometry) { + if (config.modifier_error_message) { + *config.modifier_error_message = "Mesh hash invalid geometry; more details on the console"; + } + BKE_mesh_validate(config.mesh, true, true); + } } static void process_no_normals(CDStreamConfig &config) @@ -609,6 +624,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh); config.time = sample_sel.getRequestedTime(); + config.modifier_error_message = err_str; read_mesh_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config); |