Search code examples
c++openmesh

Assertion block_size == b failed when reading an OpenMesh file


When reading an OpenMesh file via

OpenMesh::EPropHandleT<bool> prop_feature_edge;
mesh.add_property(prop_feature_edge, "feature");
OpenMesh::IO::read_mesh(mesh, "testmesh.om");

I get the error

Assertion failed: block_size == b, file E:\JB\workspace\OpenMesh-Windows-Gitlab-master\c9e6b25f\src\OpenMesh\Core\IO\reader\OMReader.cc, line 564

I looked it up in the source, but do not really get what the assertion is checking there. The problem is probably related to how different properties of the mesh are stored/loaded, but the error message is not really helpful to see what went wrong.

Note that the file path in the assertion comes from the openmesh binaries and not my project path. The assert is defined in this source source.

The file was written using

OpenMesh::EPropHandleT<bool> prop_feature_edge;
mesh.add_property(prop_feature_edge, "feature");
mesh.property(prop_feature_edge).set_persistent(true);
OpenMesh::IO::write_mesh(mesh, "testmesh.om");

In my testcase I write the mesh and re-read it again and it fails, so there should be no differences in byte order, default options or library versions.

Relevant Stacktrace:

    myProgram.exe!OpenMesh::IO::_OMReader_::restore_binary_custom_data(class std::basic_istream<char,struct std::char_traits<char> > &,class OpenMesh::BaseProperty *,unsigned __int64,bool)    Unknown
    myProgram.exe!OpenMesh::IO::_OMReader_::read_binary_edge_chunk(class std::basic_istream<char,struct std::char_traits<char> > &,class OpenMesh::IO::BaseImporter &,class OpenMesh::IO::Options &,bool)   Unknown
    myProgram.exe!OpenMesh::IO::_OMReader_::read_binary(class std::basic_istream<char,struct std::char_traits<char> > &,class OpenMesh::IO::BaseImporter &,class OpenMesh::IO::Options &)   Unknown
    myProgram.exe!OpenMesh::IO::_OMReader_::read(class std::basic_istream<char,struct std::char_traits<char> > &,class OpenMesh::IO::BaseImporter &,class OpenMesh::IO::Options &)  Unknown
    myProgram.exe!OpenMesh::IO::_OMReader_::read(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class OpenMesh::IO::BaseImporter &,class OpenMesh::IO::Options &)  Unknown
    myProgram.exe!OpenMesh::IO::_IOManager_::read(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class OpenMesh::IO::BaseImporter &,class OpenMesh::IO::Options &) Unknown
    myProgram.exe!OpenMesh::IO::read_mesh<OpenMesh::TriMesh_ArrayKernelT<OpenMesh::DefaultTraits> >(OpenMesh::TriMesh_ArrayKernelT<OpenMesh::DefaultTraits> & _mesh, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & _filename, OpenMesh::IO::Options & _opt, bool _clear) Line 141    C++
    myProgram.exe!main(int argc, char * * argv) Line 479    C++
    [External Code] 

So this really looks like some wrong size calculation in the custom properties. I copied the code adding custom properties and requesting existing ones (like face status and vertex colors) from writing the mesh just before reading the mesh to be sure to have the same mesh properties and it still crashes.

Comparing the properties of the configured meshes they seem to be the same:

properties before writing
3 vprops:
  v:points
  <vprop>
  v:colors
1 hprops:
  <hprop>
2 eprops:
  <eprop>
  feature, persistent
2 fprops:
  <fprop>
  f:status
0 mprops:
#bytes written: 169006

properties before reading
3 vprops:
  v:points
  <vprop>
  v:colors
1 hprops:
  <hprop>
2 eprops:
  <eprop>
  feature, persistent
2 fprops:
  <fprop>
  f:status
0 mprops:

Solution

  • I found the solution to the problem.

    Before writing I had deleted faces. This requires a (non permenent) status flag on the faces, which needs to be added via request_face_status().

    This worked fine and collect_garbage() correctly removed the faces, but the corresponding edges were not deleted. This caused the number of edges to be different before writing and after loading while the stored feature property probably had the same size as before which did not match the number of loaded edges.

    The solution is to add

    mesh.request_edge_status()
    

    in addition to mesh.request_face_status(). Depending on the operations on the mesh it is probably a good idea to use mesh.request_vertex_status() as well.