Work with obj meshes using OpenMesh in Python
OpenMesh is a very powerful library for processing 3D meshes. It provides a wide range of operations for meshes (like creating vertices and faces, manipulation with texture mapping of vertices) and moreover includes handful functions for iterating over adjacent vertices and faces in mesh. OpenMesh has Python version which can be used for fast implementation.
Here I will show how to work with 3D meshes using Python bindings of OpenMesh library.
Install it using pip:
pip install openmesh
Let’s write a simple test app using openmesh module
import openmesh as om
import numpy as np
Create mesh object
mesh = om.TriMesh()
Add vertices
# add a a couple of vertices to the mesh
vh0 = mesh.add_vertex([0, 1, 0])
vh1 = mesh.add_vertex([1, 0, 0])
vh2 = mesh.add_vertex([2, 1, 0])
vh3 = mesh.add_vertex([0,-1, 0])
vh4 = mesh.add_vertex([2,-1, 0])
Add faces
fh0 = mesh.add_face(vh0, vh1, vh2)fh1 = mesh.add_face(vh1, vh3, vh4)fh2 = mesh.add_face(vh0, vh3, vh1)
Or alternatively using Python list of vertices:
vh_list = [vh2, vh1, vh4]fh3 = mesh.add_face(vh_list)
Iterate over vertices
for i, vh in enumerate(mesh.vertices()):
print(vh.idx())
iterate over the vertices adjacent to a vertex vh0
for vh in mesh.vv(vh0):
print(vh.idx())
Get texture coordinates of vertex:
tc = mesh.texcoord2D(vh)
Important notes
Don’t use enumerate() in for loop over vertices. Otherwise you will get unexpected behavior like the same texture coordinates for different vertices.
OpenMesh doesn’t save texture coordinates for vertices(vt lines) in obj file. To fix it pass argument vertex_tex_coord in the method write_mesh (source):
om.write_mesh(‘test_out.obj’, mesh, vertex_tex_coord=True)
Moreover OpenMesh doesn’t save material file in the resultant obj file on default.
To preserve material info use attribute face_color when reading obj file
mesh = openmesh.read_trimesh('test.obj', vertex_tex_coord=True, face_color=True)
and writing to file
openmesh.write_mesh('test_out.obj', mesh, vertex_tex_coord=True, face_color=True)
The same can be applied to normals. Reading obj mesh with normals
mesh = openmesh.read_trimesh('test.obj', vertex_normal=True)
and writing to file
openmesh.write_mesh('test_out.obj', mesh, vertex_normal=True)
Also from my experience using OpenMesh I would point to interesting observation: the order of texture coordinate assignment is changing. Let’s say original
f 1/1 2/2 3/3
Resultant obj
f 1/3 2/1 3/2
That’s easy, isn’t it? Good luck in working with meshes using OpenMesh.