mikedh / trimesh

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

Get Transformation for nodes/mesh objects #831

Closed MattSmillie closed 4 years ago

MattSmillie commented 4 years ago

This is a great little library - I've been looking for something just like this to help with parsing gltf models. I've been having quite bit of luck getting the Geometries out of the trimesh objects, however, in testing other models I realise that I'm only getting the base mesh objects rather than the nodes.

I'm trying to figure out how to get the transformation Matrices for each of the nodes which use the same mesh, e.g., the Wheels in this model: https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/CesiumMilkTruck/glTF-Binary/CesiumMilkTruck.glb

scene=trimesh.load(file_obj="CesiumMilkTruck.glb",file_type="glb",merge_primitives=True)
myGraph=scene.graph

my_nodes=myGraph.geometry_nodes.get('Wheels')

I can see ['Wheels.001', 'Wheels'] however, I'm struggling to get the transformations for these nodes from the Wheels mesh. I'm sure I have to use the scene.transforms module but I can't figure it out.

I'm a bit of a python noob so please forgive me if this is a silly question :D

Thanks in advance

mikedh commented 4 years ago

Not a silly question at all, scene graphs definitely need some work on documentation and cleaning up the implementation. Here's a quick overview of what I think you probably want:

In [1]: import trimesh

In [2]: m = trimesh.load('models/cycloidal.3DXML')

In [3]: m
Out[3]: <trimesh.Scene(len(geometry)=13)>

In [4]: m.graph.nodes_geometry?
Type:        property
String form: <property object at 0x7fdf40c54a98>
Docstring:  
The nodes in the scene graph with geometry attached.

Returns
------------
nodes_geometry : (m,) array
  Node names which have geometry associated

In [5]: m.graph.geometry_nodes?
Type:        property
String form: <property object at 0x7fdf40c54ae8>
Docstring:  
Which nodes have this geometry?

Returns
------------
geometry_nodes : dict
  Geometry name : (n,) node names

In [6]: 

In [6]: m.geometry
Out[6]: 
OrderedDict([('60355K430',
              <trimesh.Trimesh(vertices.shape=(22719, 3), faces.shape=(42294, 3))>),
             ('disc_cam_B',
              <trimesh.Trimesh(vertices.shape=(2332, 3), faces.shape=(2388, 3))>),
             ('camshaft',
              <trimesh.Trimesh(vertices.shape=(738, 3), faces.shape=(704, 3))>),
             ('vxb-6800-2rs',
              <trimesh.Trimesh(vertices.shape=(996, 3), faces.shape=(996, 3))>),
             ('disc_cam_A',
              <trimesh.Trimesh(vertices.shape=(2332, 3), faces.shape=(2388, 3))>),
             ('92320A138_spacer',
              <trimesh.Trimesh(vertices.shape=(320, 3), faces.shape=(320, 3))>),
             ('vxb-6812RS',
              <trimesh.Trimesh(vertices.shape=(1808, 3), faces.shape=(1808, 3))>),
             ('output',
              <trimesh.Trimesh(vertices.shape=(1612, 3), faces.shape=(1732, 3))>),
             ('92510A120_spacer',
              <trimesh.Trimesh(vertices.shape=(312, 3), faces.shape=(312, 3))>),
             ('bushing_roller',
              <trimesh.Trimesh(vertices.shape=(304, 3), faces.shape=(304, 3))>),
             ('fixed_lower',
              <trimesh.Trimesh(vertices.shape=(3720, 3), faces.shape=(4068, 3))>),
             ('dowel_125',
              <trimesh.Trimesh(vertices.shape=(96, 3), faces.shape=(92, 3))>),
             ('fixed_top',
              <trimesh.Trimesh(vertices.shape=(3704, 3), faces.shape=(4036, 3))>)])

In [7]: nodes = m.graph.geometry_nodes['fixed_top']

In [8]: nodes
Out[8]: ['fixed_top#1:68:65:67:66']

In [9]: m.graph[nodes[0]]
Out[9]: 
(array([[ -0.736772,   0.      ,   0.676141,   0.      ],
        [ -0.676141,   0.      ,  -0.736772,   0.      ],
        [  0.      ,  -1.      ,   0.      , -17.4625  ],
        [  0.      ,   0.      ,   0.      ,   1.      ]]), 'fixed_top')

In [10]: matrix, geometry_name = m.graph[nodes[0]]
MattSmillie commented 4 years ago

Ahh, Ok thanks,

After I posted the question I got close but gave up! I was able to use the dump() function to get the nodes correctly placed, however, this will be really helpful for a proper implementation of what I'm working on.

Thanks so much for the prompt response