我正在使用 pymeshlab 直接从 Blender 处理网格,如下面的代码所示。
但是,我希望能够将顶点和面链接回 Blender 中的原始网格,以便在处理网格后,我可以显示与原始网格的差异。
理想情况下,我希望每个顶点和面都存储来自原始网格的 Blender ID,并将其包含在导出到 pymeshlab 和重新导入中,但我不确定如何。
这很复杂,因为在 pymeshlab 接受它们之前显然需要对所有面进行三角测量(因为通过 numpy 数组的导入限制为每个面三个顶点)。因此,我需要为三角化的面生成自定义 Blender ID。显然这是一种痛苦,任何关于将 ngons/etc 直接导入 pymeshlab 的建议也会受到重视,就好像我可以使用与原始 Blender 网格相同的 ID 那样它会简单得多。
可以根据原始导入位置关联它们 - 例如,通过在两个应用程序中使用相同的公式计算自定义属性,但这似乎不太优雅。
ms.apply_filter("define_new_per_vertex_attribute", name="v_ID", expr="x+y+z")
因此,我想知道是否有一种方法可以将一个 numpy 的 ID 数组直接加载到网格中,因为我将其复制到 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