I wrote a piece of python code which can serialize a mesh as either an ascii or binary PLY file. I can open the generated ascii files in MeshLab just fine. The generated binary files causes MeshLab to crash, however (it just segfaults). I was not able to open the files in Blender either. I'm having troubles understanding why MeshLab crashes, because as far as I understand, I am adhering to the header that I wrote. Here is the offending code:
def write_ply(mesh, filename, binary=True):
"""
Output the mesh object as an ASCII .ply file, or as a little endian binary file.
"""
header = "comment This file was generated by the SurfacePy library\n"
header += "element vertex {0}\n".format(len(mesh.vertices))
header += "property float x\nproperty float y\nproperty float z\n"
header += "element face {0}\n".format(len(mesh.triangles))
header += "property list uchar int vertex_indices\n"
header += "end_header\n"
with open(filename, 'wb') as file:
if binary==True:
file.write(__pack_string("ply\nformat binary_little_endian 1.0\n"))
else:
file.write(__pack_string("ply\nformat ascii 1.0\n"))
file.write(__pack_string(header))
if binary==True:
for vert in mesh.vertices:
file.write(struct.pack('<fff', vert.x, vert.y, vert.z))
for tri in mesh.triangles:
file.write(struct.pack('<Biii', ord('3'), tri.i1, tri.i3, tri.i2))
else:
for vert in mesh.vertices:
file.write(__pack_string("{0}\n".format(vert)))
for tri in mesh.triangles:
file.write(__pack_string("3 {0} {1} {2}\n".format(tri.i1, tri.i3, tri.i2)))
def __pack_string(str):
"""
Returns a bytes object of a string, in little-endian format.
"""
chars = [c.encode('utf-8') for c in str]
fmt = "<{0}".format(''.join(['c' for i in range(0, len(chars))]))
return __pack(fmt, chars)
def __pack(fmt, args):
return struct.pack(fmt, *args)
Am I writing the bytes incorrectly?
This one was actually trivial to solve. I was storing the property list count type as uchar
, but the integer should have been written directly into the uchar
, and not converted from a char as I did.
So I should do struct.pack('<Biii', 3, ...
and NOT struct.pack('<Biii', ord('3'), ...