в pymeshlab, как я могу загрузить из массива и напрямую добавить пользовательский идентификатор для вершин и граней
Я использую pymeshlab для обработки мешей непосредственно из Blender в соответствии с приведенным ниже кодом.
Однако я хочу иметь возможность связать вершины и грани с исходной сеткой в Blender, чтобы после обработки сетки я мог отображать отличия от оригинала.
В идеале я бы просто хотел, чтобы каждая вершина и грань сохраняли идентификатор Blender из исходной сетки, и это должно было быть включено в экспорт в pymeshlab и реимпорт обратно, но я не уверен, как это сделать.
Это усложняется очевидной необходимостью триангулировать все грани до того, как pymeshlab примет их (поскольку импорт через массив numpy ограничен тремя вершинами на грань). Таким образом, мне нужно создать собственный идентификатор Blender ID для лиц, которые триангулированы. Очевидно, это неприятно, и любые советы по прямому импорту ngons / etc в pymeshlab также будут восприняты, как если бы я мог просто использовать тот же идентификатор, что и исходная сетка Blender, это было бы намного проще.
Их можно сопоставить на основе исходного местоположения импорта - например, путем вычисления настраиваемого свойства по той же формуле в обоих приложениях, но это кажется гораздо менее элегантным.
ms.apply_filter("define_new_per_vertex_attribute", name="v_ID", expr="x+y+z")
Таким образом, мне интересно, есть ли способ просто загрузить массив идентификаторов прямо в меш, когда я копирую его в pymeshlab [и любой способ не выполнять сначала триангуляцию].
import bpy
import pymeshlab
import numpy
def exportMeshToMeshLab(blenderMesh):
# NB pymeshlab is fussy
# verts and faces have to be provided in a numpy array with verts as type float64 and faces as int32
# faces have to be triangulated - quads and ngons are not allowed
verts = [] #numpyp.empty((0,3), float64)
for v in blenderMesh.vertices:
verts.append([v.co[0], v.co[1], v.co[2]])
verts = numpy.asarray(verts, dtype=numpy.float64)
if len(verts) == 0:
print("No vertices were found, so function aborting")
return
# print(verts.shape) # must report (numOfVerts, 3)
# print(verts.dtype.name) # must report float64
faces = []
tooManyVerts = False
for poly in blenderMesh.polygons:
curFace = []
for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
curFace.append(blenderMesh.loops[loop_index].vertex_index)
if len(curFace) == 3:
faces.append(curFace)
else:
tooManyVerts = True
if tooManyVerts:
print("WARNING: Meshlab will only accept faces with THREE vertices")
if len(faces) == 0:
print("No triangular faces were found, so function aborting")
return
faces = numpy.asarray(faces, dtype=numpy.int32)
# print(faces.shape) # must report (numOfVerts, 3)
# print(faces.dtype.name)
# create a new Mesh with the two arrays
meshlabMesh = pymeshlab.Mesh(verts, faces)
# create a new MeshSet (a meshset can have multiple meshes each in a differnt layer - but that's not covered with this function)
meshlabMeshSet = pymeshlab.MeshSet()
# add the mesh to the MeshSet with the current name
meshlabMeshSet.add_mesh(meshlabMesh, blenderMesh.name)
return meshlabMeshSet
def importMeshFromMeshLab(meshlabMesh):
# NB from_pydata in Blender is fussy
# verts and faces have to be provided in a standard Python list (NOT a numpy array)
verts = meshlabMesh.current_mesh().vertex_matrix().tolist()
#vID= meshlabMesh.current_mesh().vertex_matrix().ID # TODO: return this
faces = meshlabMesh.current_mesh().face_matrix().tolist()
#fID= meshlabMesh.current_mesh().face_matrix().ID # TODO: return this
return verts, faces #, vID, fID
print("START")
print("Exporting the selected Blender mesh object to MeshLab")
print("NB - this will fail if all faces are not triangulated first")
me = bpy.context.object.data
mls = exportMeshToMeshLab(me) # (mls = meshlabMeshSet)
# apply filter to the current selected mesh (last loaded)
mls.compute_geometric_measures()
# compute the geometric measures of the current mesh
# and save the results in the out_dict dictionary
out_dict = mls.compute_geometric_measures()
print("compute_geometric_measures are:")
print(" avg_edge_length = ", out_dict['avg_edge_length'])
print(" total_edge_length = ", out_dict['total_edge_length'))
print(" mesh_volume = ", out_dict['mesh_volume'))
print(" surface_area = ", out_dict['surface_area'))
print("Now we're importing the mesh back into Blender")
print(" and creating a new object from the mesh")
print("Importing the MeshLab mesh back to Blender and creating it as a new object")
verts, faces = importMeshFromMeshLab(mls)
mesh = bpy.data.meshes.new("meshFromMeshLab") # add the new mesh
mesh.from_pydata(verts, [], faces) # this could also be done as a bmesh too...
ob = bpy.data.objects.new("meshFromMeshLab", mesh)
bpy.context.collection.objects.link(ob)
print("DONE")
Первичные источники кода:
https://github.com/dgm3333/3d-print-toolbox-modified/blob/master/meshlab_integration.py
https://blenderartists.org/t/meshlab-accessible-direct-from-blender-python/1299022
https://pymeshlab.readthedocs.io/en/0.1.9/tutorials/import_mesh_from_arrays.html
https://pymeshlab.readthedocs.io/en/0.1.9/tutorials/user_defined_mesh_attributes.html