Source code for concepts.simulator.sapien2.mesh_utils

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File   : mesh_utils.py
# Author : Jiayuan Mao
# Email  : maojiayuan@gmail.com
# Date   : 07/29/2024
#
# This file is part of Project Concepts.
# Distributed under terms of the MIT license.

from typing import List

import numpy as np
import trimesh
from trimesh import Trimesh

import sapien.core as sapien

[docs] def get_actor_meshes(actor: sapien.Entity): """Get actor (collision) meshes in the actor frame.""" meshes = [] for col_shape in actor.get_collision_shapes(): geom = col_shape.geometry if isinstance(geom, sapien.BoxGeometry): mesh = trimesh.creation.box(extents=2 * geom.half_lengths) elif isinstance(geom, sapien.CapsuleGeometry): mesh = trimesh.creation.capsule( height=2 * geom.half_length, radius=geom.radius ) elif isinstance(geom, sapien.SphereGeometry): mesh = trimesh.creation.icosphere(radius=geom.radius) elif isinstance(geom, sapien.PlaneGeometry): continue elif isinstance( geom, (sapien.ConvexMeshGeometry, sapien.NonconvexMeshGeometry) ): vertices = geom.vertices # [n, 3] faces = geom.indices.reshape(-1, 3) # [m * 3] vertices = vertices * geom.scale mesh = Trimesh(vertices=vertices, faces=faces) else: raise TypeError(type(geom)) mesh.apply_transform(col_shape.get_local_pose().to_transformation_matrix()) meshes.append(mesh) return meshes
[docs] def get_visual_body_meshes(visual_body: sapien.RenderBody): meshes = [] for render_shape in visual_body.get_render_shapes(): vertices = render_shape.mesh.vertices * visual_body.scale # [n, 3] faces = render_shape.mesh.indices.reshape(-1, 3) # [m * 3] mesh = Trimesh(vertices=vertices, faces=faces) mesh.apply_transform(visual_body.local_pose.to_transformation_matrix()) meshes.append(mesh) return meshes
[docs] def get_actor_visual_meshes(actor: sapien.ActorBase): """Get actor (visual) meshes in the actor frame.""" meshes = [] for vb in actor.get_visual_bodies(): meshes.extend(get_visual_body_meshes(vb)) return meshes
[docs] def merge_meshes(meshes: List[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(np.vstack(vs), np.vstack(fs)) else: return None
[docs] def get_actor_mesh(actor: sapien.ActorBase, to_world_frame=True, visual=False): if visual: mesh = merge_meshes(get_actor_visual_meshes(actor)) else: mesh = merge_meshes(get_actor_meshes(actor)) if mesh is None: return None if to_world_frame: T = actor.pose.to_transformation_matrix() mesh.apply_transform(T) return mesh
[docs] def get_actor_visual_mesh(actor: sapien.ActorBase): mesh = merge_meshes(get_actor_visual_meshes(actor)) if mesh is None: return None return mesh
[docs] def get_articulation_meshes( articulation: sapien.ArticulationBase, exclude_link_names=() ): """Get link meshes in the world frame.""" meshes = [] for link in articulation.get_links(): if link.name in exclude_link_names: continue mesh = get_actor_mesh(link, True) if mesh is None: continue meshes.append(mesh) return meshes