2 minutes
Getting all vertex positions in a mesh
I made my own OBJ importer written in Python for Maya. No real use case, just for fun. Then I looked into exporting out an OBJ and needed to get the positions of all the vertices in polygonal mesh, since that information is stored like this in an OBJ:
# This file uses centimeters as units for non-parametric coordinates.
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
Using the 2.0 Python API, I could get those positions:
def get_vertex_pos_of_mesh(mesh, as_mpoint_array=False):
selection_list = om.MSelectionList()
selection_list.add(mesh)
dag_path = selection_list.getDagPath(0)
mpoint_array = om.MFnMesh(dag_path).getPoints()
if as_mpoint_array:
return mpoint_array
else:
point_list = []
for mpoint in mpoint_array:
point_list.append([mpoint[0], mpoint[1], mpoint[2]])
return point_list
And, as expected, this runs almost instantaneously.
I also tried PyMel’s built-in getPoints() method, since it’s a simple one-liner:
def get_vertex_pos_of_mesh_pymel(mesh):
return pm.PyNode(mesh).getPoints()
This was a lot slower than using the API though.
That made me wonder about some code I remembered from a long ago, when I was just starting out in Python, and how fast that would be. I actually used it here: http://nielsvaes.be/posts/copy_vertex_weights/. There’s a Maya command named pointPosition() that will also get the position of a point, like this:
def get_vertex_pos_of_mesh_point_position(mesh):
mesh = pm.PyNode(mesh)
mesh_name = mesh.name()
points_list = []
for vertex_number in range(mesh.numVertices()):
vertex_name = "%s.vtx[%s]" % (mesh_name, vertex_number)
position = pm.pointPosition(vertex_name, world=True)
points_list.append(position)
return points_list
It worked just fine, but was extremely slow.
So I figured I’d give the xform() command a try to see how that would stack up:
def get_vertex_pos_of_mesh_xform(mesh):
mesh = pm.PyNode(mesh)
mesh_name = mesh.name()
points_list = []
for vertex_number in range(mesh.numVertices()):
vertex_name = "%s.vtx[%s]" % (mesh_name, vertex_number)
position = pm.xform(query=True, translation=True, worldSpace=True)
points_list.append(position)
return points_list
It’s also slow, but surprisingly about 44% faster than using pointPosition()
# root : __main__: get_vertex_pos_of_mesh 436.00 ms #
# root : __main__: get_vertex_pos_of_mesh_pymel 3798.00 ms #
# root : __main__: get_vertex_pos_of_mesh_xform 13897.00 ms #
# root : __main__: get_vertex_pos_of_mesh_point_position 21959.00 ms #
So if you’re ever in need of having to get the position of every vertex in a mesh, it’s save to say you should just use the Python API. Using the 2.0 version to write that function is also still pretty short and easy to read.