def write_wavefront_obj(verts, faces, normals):
  """ save polygons in obj format

  obj format is more commonly used than ply

  Args:
    verts (np.array): shape=(nvert,3) dtype=float,
      vertices in cartesian coordinates.
    faces (np.array): shape=(nface,nside) dtype=int,
      polygons each specified as a list of vertices
      (in vertex coordinates defined by verts).
    normals (np.array): shape=(nvert,3) dtype=float,
      normal vectors used for smooth lighting.
      There is one normal vector per vertex.
  Returns:
    str: content of the obj file
  """
  text = ''
  if faces.dtype.kind != 'i':
    print('Warning: faces should be integers. Converting now.')
    faces = faces.astype(int)

  vert_fmt = '{name:s} {x:7.6f} {y:7.6f} {z:7.6f}\n'  # weights not supported
  # write vertices
  for ivert in range(len(verts)):
    vert  = verts[ivert]
    x, y, z = vert
    text += vert_fmt.format(name='v', x=x, y=y, z=z)
  # write normals
  for inorm in range(len(normals)):
    norm  = normals[inorm]
    x, y, z = norm
    text += vert_fmt.format(name='vn', x=x, y=y, z=z)
  # write faces
  face_fmt = '{name:s} {polyx:d}//{normalx:d} {polyy:d}//{normaly:d} {polyz:d}//{normalz:d}\n'  # texture not supported
  for iface in range(len(faces)):
    face  = faces[iface]
    x, y, z = face+1
    text += face_fmt.format(name='f', polyx=x, polyy=y, polyz=z,
      normalx=x, normaly=y, normalz=z)
  return text