trimesh icon indicating copy to clipboard operation
trimesh copied to clipboard

How to export obj with specific faces colored?

Open rknizzle opened this issue 1 year ago • 1 comments

Hi im trying to color particular faces of a mesh and then export it as obj/mtl and view it in threejs/blender.

I ran the following code and was expecting the faces to be colored but it seems like it gives the vertices a color which makes the color bleed over to neighboring faces:

    mesh = trimesh.load('cube-with-thin-ridge.stl', force='mesh')

    mesh.visual.face_colors[0] = [255, 0, 0, 255]
    mesh.visual.face_colors[1] = [255, 0, 0, 255]
    mesh.visual.face_colors[32] = [255, 0, 0, 255]
    mesh.visual.face_colors[33] = [255, 0, 0, 255]


    mesh.export("trimesh-output.obj", include_normals=True, include_color=True)

Heres an image of the output of the code: got-from-trimesh And the output obj file: trimesh-output.zip

This is an image of my desired result: expected-red-face-grey

And here are the obj/mtl files that exported from Autodesk Netfabb which gave me my desired result: netfabb-output.zip

Questions:

  1. Is there a way to specify that the faces should be colored rather than the vertices when exporting to obj/mtl?
  2. Is there any other export file type that keep face colors?

I would be happy to contribute if this doesn't already exist and seems like a reasonable feature to implement

rknizzle avatar Dec 12 '23 15:12 rknizzle

Hey yeah this is a little tough with OBJ, since as far as I know there's no face-color mode that's well supported (well-supported being meshlab and maybe three.js :). If there is a mode like that PR's super welcome! Yeah the vertex colors look really janky if you don't run either mesh.unmerge_vertices() (which disconnects everything) or mesh.smooth_shaded (which disconnects faces above an angle threshold). mesh.smooth_shaded would probably be the best looking:

In [1]: import trimesh

In [2]: import numpy as np

In [3]: m = trimesh.creation.box()

In [4]: faces = np.isclose(m.face_normals, [0, 0, 1]).all(axis=1)

In [5]: s = m.smooth_shaded

In [6]: faces = np.isclose(s.face_normals, [0, 0, 1]).all(axis=1)

In [7]: s.visual.face_colors[faces] = [255,0,0,255]

In [9]: _ = s.export('~/Downloads/face_color.obj')

In [10]: s.visual.kind
Out[10]: 'face'

In [11]: s.visual.face_colors
Out[11]:
TrackedArray([[102, 102, 102, 255],
              [102, 102, 102, 255],
              [102, 102, 102, 255],
              [102, 102, 102, 255],
              [102, 102, 102, 255],
              [102, 102, 102, 255],
              [255,   0,   0, 255],
              [255,   0,   0, 255],
              [102, 102, 102, 255],
              [102, 102, 102, 255],
              [102, 102, 102, 255],
              [102, 102, 102, 255]], dtype=uint8)

In [12]: _ = s.export('~/Downloads/face_color.obj')
Screenshot 2023-12-13 at 7 04 52 PM

mikedh avatar Dec 14 '23 00:12 mikedh