1

我正在使用 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

4

0 回答 0