mikedh / trimesh

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

Enhancement Ideas #199

Closed mikedh closed 2 years ago

mikedh commented 6 years ago

I was pinged recently looking for some projects to help out with, here are some ideas. PR's are always appreciated!

Updated 7/27/2020

Marviel commented 6 years ago

@mikedh awesome list, we'd all love to see some of these changes, stoked to know you're considering things like built-in mesh simplification, etc.

A convention I've seen in some other repos is to have each task listed as their own github issue, and give them an easy medium hard label applied to them, based on the perceived difficulty.

Also allows us to start threaded conversations on each of the tasks in your list.

Anyhow just a thought! Not sure the extent to which we want to use Issues here :)

mikedh commented 6 years ago

Yeah it would be great to get some of this stuff! In the interest of avoiding a ton of immediately orphaned new issues the process I'd suggest initially would be:

1) I'll update this list in- place with new ideas. 2) If someone is interested in working on one of the ideas, they can open a new issue looking for advice before PR'ing.

mmatl commented 6 years ago

@mikedh I'm going to try to tackle textures. Let me know if you have any thoughts -- I was also thinking a new TextureVisuals object. Loading the texture file itself will probably requireimageio -- are you okay with introducing that dep? It's really lightweight.

mikedh commented 6 years ago

Sounds good, discussion for texture in https://github.com/mikedh/trimesh/issues/218

LinJiarui commented 6 years ago

@mikedh Hey mike, it's great to see that you mentioned IFC, which I'm quite familiar with. I also used IfcOpenShell to get geometries from IFC file and then voxelize them with trimesh. That's why I found trimesh and created two PRs :) So, maybe I can help in IFC importing.

mikedh commented 6 years ago

Hey @LinJiarui that would be great! I took a look at ifcopenshell-python briefly, and it looks like the biggest stumbling block would be packaging. As per https://github.com/IfcOpenShell/IfcOpenShell/issues/146, you can't install it via pip, and it would be preferable to address that before adding it as a dependency.

CIbuildwheel might be a good solution, but is definitely a lot of work!

nschloe commented 5 years ago

Perhaps optimesh is something for you, too.

(BTW I just added trimesh to the awesome list.)

FXXB commented 5 years ago

@mikedh Thank you for your trimesh library. Just awesome. I am rewriting my code which so far mainly deals with numpy.stl's. Since trimesh really does the job I am in the process of switching from numpy.stl to trimesh. So far I couldn´t find something to convert numpy.stl to trimesh. Is there already a method to convert numpy.stl files to trimesh and vice versa. I would highly appreciate a hint on how to resolve. Thank you and best regards

FXXB commented 5 years ago

Hi @bbarroqueiro Thank you for your quick response. Yes, of course, I can save the numpy.stl representation as .stl and reload it as .stl in the trimesh representation, but I would prefer to do the job without export/import. Something like trimesh.load (numpy-stl.data) I wondered if this direct conversion between numpy-stl and trimesh already exists... Sorry for the confusion

FXXB commented 5 years ago

Hi @bbarroqueiro
Thank you for your assistance. I will give it a try and let you know. Best regards

mikedh commented 5 years ago

Oh numpy-stl from pypi? It looks like they just use a custom dtype, you can probably access the data directly:

In [1]: import trimesh

In [2]: from stl import Mesh

In [3]: r = Mesh.from_file('models/featuretype.STL')

In [4]: r.data
Out[4]: 
array([([ 0.        , -0.        ,  0.01694411], [[ 1.8933141 ,  0.5625    ,  1.        ], [ 1.8952131 ,  0.58420604,  1.        ], [ 1.125     ,  0.703125  ,  1.        ]], [0]),
       ([ 0.        , -0.        ,  0.01688094], [[ 1.8952131 ,  0.58420604,  1.        ], [ 1.9008526 ,  0.60525256,  1.        ], [ 1.125     ,  0.703125  ,  1.        ]], [0]),
       ([ 0.        ,  0.        ,  0.01622234], [[ 1.125     ,  0.703125  ,  1.        ], [ 1.9008526 ,  0.60525256,  1.        ], [ 1.9100609 ,  0.625     ,  1.        ]], [0]),
       ...,
       ([ 0.        ,  0.0625    ,  0.        ], [[ 1.75      , -0.25      ,  1.        ], [ 1.25      , -0.25      ,  0.875     ], [ 1.25      , -0.25      ,  1.        ]], [0]),
       ([ 0.        , -0.        ,  0.25      ], [[ 1.75      , -0.25      ,  0.875     ], [ 1.75      ,  0.25      ,  0.875     ], [ 1.25      , -0.25      ,  0.875     ]], [0]),
       ([ 0.        ,  0.        ,  0.25      ], [[ 1.25      , -0.25      ,  0.875     ], [ 1.75      ,  0.25      ,  0.875     ], [ 1.25      ,  0.25      ,  0.875     ]], [0])],
      dtype=[('normals', '<f4', (3,)), ('vectors', '<f4', (3, 3)), ('attr', '<u2', (1,))])

In [5]: r.vectors.shape
Out[5]: (3476, 3, 3)

In [6]: m = trimesh.Trimesh(**trimesh.triangles.to_kwargs(r.vectors))

In [7]: m.faces.shape
Out[7]: (3476, 3)
FXXB commented 5 years ago

Thank you so much. That's it. I must have missed the .to_kwargs method. Thanks again

science-code commented 5 years ago

Hello! Was there any progress on mesh simplification/decimation with Trimesh?

sklausing commented 4 years ago

Hello there everyone, my first ever comment on github haha! I think it would be nice to specify dtype for several functions when passing in arrays of points (not always converting to float64 when checking appropriate 3-dimensional). Constantly running into a memory issue when using ray.contains_points. I did see a comment that suggested iterating through, perhaps on the Z axis to avoid this issue, although i do think it could help having the option to use float16 or float 32.

nschloe commented 4 years ago

meshio author here. I think handling the I/O via meshio would be a good idea here. If you're interested I could cook up a PR.

mikedh commented 4 years ago

Hey @nschloe that would be awesome! Super open to PR's!

FreakTheMighty commented 4 years ago

OpenMesh has python bindings and decimation. Its not the lightest dependency, but it could provide mesh simplification.

Roughly, you can go back and forth between OpenMesh and trimesh like so:

def tri_to_om(mesh):
    om_mesh = om.TriMesh(np.array(mesh.vertices))
    om_mesh.add_faces(np.array(mesh.faces))
    return om_mesh

def om_to_tri(om_mesh):
    mesh = trimesh.Trimesh()
    mesh.vertices = om_mesh.points()
    mesh.faces = om_mesh.face_vertex_indices()
    mesh.face_normals = om_mesh.face_normals()
    mesh.vertex_normals = om_mesh.vertex_normals()
    return mesh

Decimation looks something like. I find their interface pretty confusing. It took a while for me to make sense of it at all.

    mod = om.TriMeshModQuadricHandle()
    decimator = om.TriMeshDecimater(om_mesh)
    decimator.add(mod)
    mod = decimator.module(mod)
    mod.set_binary(False)
    mod.set_max_err(4)
    decimator.initialize()
    decimator.decimate_to(to)
    om_mesh.garbage_collection()

Its also possible to lock edges to preserve them during decimation.

Kramer84 commented 4 years ago

Hi Mike

I have seen the issue concerning quadric edge decimation and the potential enhancement using sp4cerat's fast quadric edge decimation. For now I am trying to learn how to do the bindings using Cython, but I am running into some issues, mainly concerning the conversion of numpy arrays into the custom object vec3f defined in sp4cerat's code. (As I have little to no experience with C++)

The easiest way to proceed would, in my opinion, to export the mesh as a temporary .OBJ file, doing the reduction using a simple cython wrapper, and loading the new file into trimesh again, but this solution is not elegant at all, and a lot of time would be lost from the conversion, the savings and the loading of objects... On the other hand, this would require the least modifications in the original code. But still, not elegant.

An other idea would to pass the OBJ string directly as an argument into the code, but then I struggle to know if the type of the string in the new function used to pass the OBJ string should be *char or stdin or a FILE Stream** , and there would still be time spent for the OBJ conversion.

But the best way to proceed would be to convert the numpy arrays into the custom type defined by sp4cerat and setting the variables through a new C++ function, but this would be a lot of work and research.

I would like to know if you have any ideas about how to do this (or some interesting articles about this topic) or if you have already begun this implementation. I have begun some analysis and will soon begin some testing here

Greatings

Kristof S.

FreakTheMighty commented 4 years ago

@mikedh I've been using this library for quadratic mesh simplification. I think this could be the perfect library for integrating into trimesh.

Its got a lot going for it:

simplified = simplify_mesh(np.array(mesh.vertices),
                       np.array(mesh.faces, dtype=np.uint32),
                       node_target)
decimated= trimesh.Trimesh(vertices=simplified[0], faces=simplified[1])

I believe it should be cross platform, but there is an outstanding issue on windows that I wasn't able to offer a pull request for. Perhaps someone in this community would be able to address it https://github.com/jannessm/quadric-mesh-simplification/issues/2

CC @jannessm

jannessm commented 4 years ago

@FreakTheMighty: thanks for your support.

regarding the vertex attributes. I have implemented this library to use it in the context of geometric deep learning. therefore, I needed an interpolation of feature vectors assigned to vertices. But as @FreakTheMighty mentioned, it can be used very easily for quadric mesh simplification without features.

Currently, I am quite busy. Therefore, I would be very glad, if I receive some support for the mentioned issue.

mikedh commented 4 years ago

hey @jannessm that looks awesome! I really like how self contained it is. If I get some cycles I'd love to help get cibuildwheel set up, although unfortunately I'm also kind of slammed this season. I'll try to look at it once I drag https://github.com/Toblerity/rtree/pull/163 over the finish line.

Kramer84 commented 4 years ago

Hi @mikedh , even if now this issue seems to be solved i managed to wrap Sp4cerat's Fast-Quadric-Mesh-Algorithm in C++ with Cython It works well enough on stanfords bunny sample for simplifying it down from 112402 to 1000 in less then a second. The algorithm is only composed of two scripts. The simplification is also possible on non watertight meshes and does not change open triangle borders.

repo: PySimplify

usage is similar:

>>> from simplify import pySimplify
>>> import trimesh as tr
>>> bunny = tr.load_mesh('Stanford_Bunny_sample.stl)
>>> bunny
<trimesh.Trimesh(vertices.shape=(56203, 3), faces.shape=(112402, 3))>
>>> simplify = pySimplifyy()
>>> simplify.setMesh(bunny)
>>> simplify.simplify_mesh(target_count = 1000, aggressiveness=7, verbose=10)
iteration 0 - triangles 112402 threshold 2.187e-06
iteration 5 - triangles 62674 threshold 0.00209715
iteration 10 - triangles 21518 threshold 0.0627485
iteration 15 - triangles 9086 threshold 0.61222
iteration 20 - triangles 4692 threshold 3.40483
iteration 25 - triangles 2796 threshold 13.4929
iteration 30 - triangles 1812 threshold 42.6184
iteration 35 - triangles 1262 threshold 114.416
simplified mesh in 0.2254 seconds from 112402 to 1000 triangles
>>> smallBunny = simplify.getMesh()
>>> smallBunny
<trimesh.Trimesh(vertices.shape=(502, 3), faces.shape=(1000, 3))>

The tracking of the color and material attributes is not yet implemented, but as it is already implemented in the c++ code it is just a mater of wrapping one more function.

I can help to integrating it into trimesh if you plan not to use it as an external dependency.

FreakTheMighty commented 4 years ago

@Kramer84, thank you for doing this work! It seems like Issues are not enabled on that repo, is that intentional?

Kramer84 commented 4 years ago

@FreakTheMighty I forgot it, the issues are now enabled, thanks!

tpank commented 3 years ago

Hi @mikedh ,

thank you for this awesome library! Would it be possible to include the option for a multi-dimensional pitch in Path2d.rasterize? This would only require to remove the current input checks that enforce the user to provide a uniform spacing for all directions. The same is already possible in trimesh.voxel.creation.voxelize (even though its not in the documentation and possibly not intended).

mikedh commented 3 years ago

Hey @tpank if it's just removing a check and adding a unit test absolutely! Happy to take PR's!

mikedh commented 2 years ago

Closing in favor of the updated issue #1557