3

I am working with a triangle meshes with python Open3d and I want to add a texture mapping to my mesh (I didn't find it in the documentation), this is an example code with simple cube mesh:

import numpy as np
import open3d as o3d

vert=[[0,0,0],[0,1,0],[1,1,0],[1,0,0],
   [0,0,1],[0,1,1],[1,1,1],[1,0,1]]

faces=[[0, 1, 2], [0, 2, 3], [6, 5, 4],
 [7, 6, 4], [5, 1, 0], [0, 4, 5], [3, 2, 6],
 [6, 7, 3], [0, 3, 7], [0, 7, 4], [1, 5, 6],
 [1, 6, 2]]

m=o3d.geometry.TriangleMesh(o3d.open3d_pybind.utility.Vector3dVector(vert),
                            o3d.open3d_pybind.utility.Vector3iVector(faces))

m.compute_vertex_normals()
o3d.visualization.draw_geometries([m])

I can see the cube: cube mesh

Now I try to add texture:

text=cv2.imread('~/Downloads/cupe_uv.png')
plt.imshow(text)

this is the texture image: texture image of a cube

DX,DY=0.5/2,0.66/2
v_uv=[[DX,DY],[DX,2*DY],[2*DX,2*DY],[2*DX,DY],
      [0,DX],[DX,1],[3*DX,2*DY],[3*DX,DY]]

v_uv=np.asarray(v_uv)
v_uv=np.concatenate((v_uv,v_uv,v_uv),axis=0)
m.triangle_uvs = o3d.open3d_pybind.utility.Vector2dVector(v_uv)

m.textures=[o3d.geometry.Image(text)]

o3d.visualization.draw_geometries([m])

I know I didn't set the uv coordinates to display all the colors of the cube (but some colors should be there...). Any way the mesh is still with out texture (same as in the beginning).

Nadav Geva
  • 31
  • 1
  • 1
  • 4

2 Answers2

2

mesh.triangle_uvs is an array of shape (3 * num_triangles, 2), not (3 * num_vertices, 2).

Try this:

v_uv = np.random.rand(len(faces) * 3, 2)
m.triangle_uvs = o3d.open3d_pybind.utility.Vector2dVector(v_uv)

By the way, it seems that your Open3D version is quite old.
Open3d 0.10.0 is already out and a lot of new features added.
You might wanna try the new version :)

Jing Zhao
  • 2,420
  • 18
  • 21
  • 2
    For me this just crashes on 0.10 - it used to work on 0.9 with the caveat that now there's a 'textures' property rather than just a singular 'texture'. I made a simplified example here: https://github.com/intel-isl/Open3D/issues/2089 – Oliver Jul 21 '20 at 01:50
  • It is strange. I can save the mesh as an `obj` file and later visualize it using [meshlab](https://www.meshlab.net/) just right. However calling visualization just crashes like you said. – Jing Zhao Jul 21 '20 at 02:18
  • 1
    I think it is something to do with the mesh not having material ids (I don't see any way to set material ids) - if I save the mesh and load it again, it has material ids and can be displayed. – Oliver Jul 21 '20 at 06:13
  • I don't see any way to set material and material_ids either. Your guess sounds very reasonable to me! – Jing Zhao Jul 21 '20 at 06:36
  • Thanks! you are right about the size of triangles_uvs, unfortunately it still doesn't work. I even tried a simpler version with just one triangle, but still I don't see any texture. I also think it might be related to the "has_triangle_material_ids" property, but I didn't find a way to add materials. P.s. I am using open3d 0.10.0. – Nadav Geva Jul 26 '20 at 14:24
  • 1
    Actually like Oliver suggested, it might be a bug of `0.10.0`. I think you can either choose to use version `0.9.0`, which still works (from my experience), or you can first save the mesh to disk using `o3d.io.write_triangle_mesh` and then read the mesh back in, it seems then you can visualize just fine in `0.10.0` :) – Jing Zhao Jul 26 '20 at 14:45
  • Thanks, saving .obj (with a different SW) and reading it with o3d works. I used this work around before, but I was hoping a simpler straight forward method will work. – Nadav Geva Jul 27 '20 at 07:38
1

Like @jing-zhao said in https://stackoverflow.com/a/63005705/15099601,

v_uv = np.random.rand(len(faces) * 3, 2) 
m.triangle_uvs = o3d.open3d_pybind.utility.Vector2dVector(v_uv)

will work. For Open3d version 0.10.0, the material_ids do not seem to get set.

m.triangle_material_ids = o3d.utility.IntVector([0]*len(faces))

fixes that, so that the textured cube can be visualized without crashing.

Jan
  • 11
  • 4