Source code for mani_skill.utils.geometry.trimesh_utils

## TODO clean up the code here, too many functions that are plurals of one or the other and confusing naming
import numpy as np
import sapien
import sapien.physx as physx
import sapien.render
import trimesh
import trimesh.creation


[docs]def get_component_meshes(component: physx.PhysxRigidBaseComponent): """Get component (collision) meshes in the component's frame.""" meshes = [] for geom in component.get_collision_shapes(): if isinstance(geom, physx.PhysxCollisionShapeBox): mesh = trimesh.creation.box(extents=2 * geom.half_size) elif isinstance(geom, physx.PhysxCollisionShapeCapsule): mesh = trimesh.creation.capsule( height=2 * geom.half_length, radius=geom.radius ) elif isinstance(geom, physx.PhysxCollisionShapeCylinder): mesh = trimesh.creation.cylinder( radius=geom.radius, height=2 * geom.half_length ) elif isinstance(geom, physx.PhysxCollisionShapeSphere): mesh = trimesh.creation.icosphere(radius=geom.radius) elif isinstance(geom, physx.PhysxCollisionShapePlane): continue elif isinstance(geom, (physx.PhysxCollisionShapeConvexMesh)): vertices = geom.vertices # [n, 3] faces = geom.get_triangles() vertices = vertices * geom.scale mesh = trimesh.Trimesh(vertices=vertices, faces=faces) elif isinstance(geom, physx.PhysxCollisionShapeTriangleMesh): vertices = geom.vertices faces = geom.get_triangles() vertices = vertices * geom.scale mesh = trimesh.Trimesh(vertices=vertices, faces=faces) else: raise TypeError(type(geom)) mesh.apply_transform(geom.get_local_pose().to_transformation_matrix()) meshes.append(mesh) return meshes
[docs]def get_render_body_meshes(visual_body: sapien.render.RenderBodyComponent): meshes = [] for render_shape in visual_body.render_shapes: meshes += get_render_shape_meshes(render_shape) return meshes
[docs]def get_render_shape_meshes(render_shape: sapien.render.RenderShape): meshes = [] if type(render_shape) == sapien.render.RenderShapeBox: mesh = trimesh.creation.box(extents=2 * render_shape.half_size) meshes.append(mesh) elif type(render_shape) == sapien.render.RenderShapeCapsule: mesh = trimesh.creation.capsule( height=2 * render_shape.half_length, radius=render_shape.radius ) meshes.append(mesh) elif type(render_shape) == sapien.render.RenderShapeCylinder: mesh = trimesh.creation.cylinder( radius=render_shape.radius, height=2 * render_shape.half_length ) meshes.append(mesh) elif type(render_shape) == sapien.render.RenderShapeSphere: mesh = trimesh.creation.icosphere(radius=render_shape.radius) meshes.append(mesh) elif type(render_shape) == sapien.render.RenderShapePlane: pass elif type(render_shape) == sapien.render.RenderShapeTriangleMesh: for part in render_shape.parts: vertices = part.vertices * render_shape.scale # [n, 3] faces = part.triangles mesh = trimesh.Trimesh(vertices=vertices, faces=faces) meshes.append(mesh) for mesh in meshes: mesh.apply_transform(render_shape.local_pose.to_transformation_matrix()) return meshes
[docs]def get_actor_visual_meshes(actor: sapien.Entity): """Get actor (visual) meshes in the actor frame.""" meshes = [] comp = actor.find_component_by_type(sapien.render.RenderBodyComponent) if comp is not None: meshes.extend(get_render_body_meshes(comp)) return meshes
[docs]def merge_meshes(meshes: list[trimesh.Trimesh]): n, vs, fs = 0, [], [] for mesh in meshes: v, f = mesh.vertices, mesh.faces vs.append(v) fs.append(f + n) n = n + v.shape[0] if n: return trimesh.Trimesh(np.vstack(vs), np.vstack(fs)) else: return None
[docs]def get_component_mesh(component: physx.PhysxRigidBaseComponent, to_world_frame=True): mesh = merge_meshes(get_component_meshes(component)) if mesh is None: return None if to_world_frame: T = component.pose.to_transformation_matrix() mesh.apply_transform(T) return mesh
[docs]def get_actor_visual_mesh(actor: sapien.Entity): mesh = merge_meshes(get_actor_visual_meshes(actor)) if mesh is None: return None return mesh