Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Reading .obj mesh with multiple texture vertices/vertex fails #1487

Open
nikolas-claussen opened this issue Aug 19, 2024 · 1 comment

Comments

@nikolas-claussen
Copy link

Reading .obj mesh with multiple texture vertices/vertex fails. This situation occurs frequently in UV mapping - when cuts are made to map a mesh which is not topologically a disk to the UV square, vertices along the cut are assigned multiple texture positions.

To reproduce, create a .obj mesh with UV mapping and cuts (e.g. in blender, create a UV sphere and export it as uv_sphere.obj).

mesh = meshio.read("uv_sphere.obj")

yields

ValueError: len(points) = 482, but len(point_data["obj:vt"]) = 559

Version: meshio==5.3.5

@TimeTravelerFromNow
Copy link

Here's a PR from earlier this year that suggests a solution for this. Also, issues #1261, #1377 are related.

Here's the source that causes the error, I think this check is useful, however won't suffice for .objs
line 162 src/meshio/_mesh.py

      # assert point data consistency and convert to numpy arrays
       for key, item in self.point_data.items():
           self.point_data[key] = np.asarray(item)
           if len(self.point_data[key]) != len(self.points):
               raise ValueError(
                   f"len(points) = {len(self.points)}, "
                   f'but len(point_data["{key}"]) = {len(self.point_data[key])}'
               )

The problem with this assertion for .obj loading is that the vertex texture attribute "obj:vt" and other keys in valid .obj files commonly are not the same count as the number of vertices.
I have a suggestion how this could be changed to validate the "face" data which appears as

f 1/1 2/2 3/3 4/4
f 5/1 8/2 7/3 6/4
f 1/1 5/2 6/3 2/4

in an obj file.
For example, f 5/1 8/2 7/3 6/4 is saying face 2 is made up of vertex 5 8 7 6. With corresponding vertex textures index 1 2 3 4 defined in the file as vt 0.000000 0.000000 etc.

Reading this documentation about the obj format https://learnwebgl.brown37.net/, what we should validate is that the indices in each face data doesn't exceed the length of the available attributes.
So if there are 4 "obj:vt" we should read each face, so

f 1/1 2/2 3/3 4/4 would pass the validation since for each vertex_index/texture_index, texture_index <= len(point_data["obj:vt"])

f 1/1 2/2 3/3 4/5 would fail since 4/5 has a texture_index = 5 > len(point_data["obj:vt"])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants