mikedh / trimesh

Python library for loading and using triangular meshes.
https://trimesh.org
MIT License
3.02k stars 583 forks source link

Question: Do not require loading texture for Mesh with texture? #2315

Closed JulianKnodt closed 2 weeks ago

JulianKnodt commented 3 weeks ago

Is there anyway to load a mesh with textures, but not load the textures? I'm computing the distance between sets of meshes, and I don't care about the texture for this specific case, but because the input GLB mesh has some textures at a URI which may not exist it is causing the import to fail. Is there any way to avoid importing textures so it won't crash, but just get the geometry?

mikedh commented 3 weeks ago

Yeah, you should be able to pass trimesh.load(..., skip_materials=True) which usually provides a decent speedup on meshes with texture:

In [1]: import trimesh

In [3]: print(trimesh.exchange.gltf.load_glb.__doc__)

    Load a GLTF file in the binary GLB format into a trimesh.Scene.

    Implemented from specification:
    https://github.com/KhronosGroup/glTF/tree/master/specification/2.0

    Parameters
    ------------
    file_obj : file- like object
      Containing GLB data
    resolver : trimesh.visual.Resolver
      Object which can be used to load other files by name
    ignore_broken : bool
      If there is a mesh we can't load and this
      is True don't raise an exception but return
      a partial result
    merge_primitives : bool
      If True, each GLTF 'mesh' will correspond to a
      single Trimesh object.
    skip_materials : bool
      If true, will not load materials (if present).

    Returns
    ------------
    kwargs : dict
      Kwargs to instantiate a trimesh.Scene

In [4]: %timeit trimesh.load('DamagedHelmet.glb')
2.19 ms ± 4.72 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [5]: %timeit trimesh.load('DamagedHelmet.glb', skip_materials=True)
1.1 ms ± 8.63 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

That being said it seems like "the input GLB mesh has some textures at a URI which may not exist it is causing the import to fail" should probably be survivable and seems like a bug haha. Was the exception raised in _uri_to_bytes?

JulianKnodt commented 3 weeks ago

I'm just doing trimesh.load('something.glb'), but I'm sometimes passing an obj file and sometimes passing a gltf file 😅, if I remember right the error I'm hitting is that resolver is None, in resolver[uri], but I do not recall where

I'm on my personal computer now, and I'm hitting this at work so I'll try again tmrw and let you know.

mikedh commented 2 weeks ago

Ah yeah skip_materials=False is also implemented for obj so trimesh.load('glb_or_obj.obj', skip_materials=False should work for both.

Cool if you can track it down to a small sample file we could add to tests that would be great. A broken buffer is not always survivable, as if the buffer has core geometry it probably should just crash. I think we could probably have _uri_to_bytes return an ExceptionWrapper which the materials would wrap, but other parts would display a decent message.

Thanks for the report!

JulianKnodt commented 2 weeks ago

Turns out I was running on trimesh 3.21.6, I should've done a bit more due diligence before filing the bug (unless you're backporting fixes). Once I upgraded to the latest version of trimesh, the bug fixed itself. I hit some more bugs later with glb with armatures, but I'll spend some more time isolating the cause and open a new issue if I find specifics.

For now, I'll just close this issue, sorry, and thank you for the comprehensive and thoughtful replies.