Work with obj meshes using OpenMesh in Python

Privalov Vladimir
2 min readFeb 16, 2021

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.

--

--