Import, export, process, analyze and view triangular meshes.
Interactive 3D visualization, material and texture support, scene management, and integration with various rendering systems. Trimesh provides comprehensive tools for displaying, rendering, and exporting 3D content.
Display meshes and scenes in interactive 3D viewers.
def show(self, viewer=None, **kwargs) -> None:
"""
Display mesh in interactive 3D viewer.
Parameters:
- viewer: str, viewer type ('gl', 'notebook', 'pyglet')
- **kwargs: viewer-specific options like window size, lighting
"""
def scene(self) -> Scene:
"""
Create Scene object containing this mesh.
Returns:
Scene object with mesh added
"""
class Scene:
"""Scene graph container for multiple geometries"""
def show(self, viewer=None, **kwargs) -> None:
"""Display scene in interactive viewer"""
def save_image(self, resolution=(1920, 1080), **kwargs) -> bytes:
"""
Render scene to image.
Parameters:
- resolution: (width, height) image size
- **kwargs: rendering options
Returns:
bytes, PNG image data
"""Control appearance through colors, materials, and textures.
@property
def visual(self):
"""Visual properties interface"""
class ColorVisuals:
"""Simple color-based visual properties"""
@property
def face_colors(self) -> np.ndarray:
"""
Face colors as (m, 4) RGBA array.
Returns:
(m, 4) face colors in RGBA format
"""
@face_colors.setter
def face_colors(self, colors: np.ndarray) -> None:
"""Set face colors"""
@property
def vertex_colors(self) -> np.ndarray:
"""
Vertex colors as (n, 4) RGBA array.
Returns:
(n, 4) vertex colors in RGBA format
"""
@vertex_colors.setter
def vertex_colors(self, colors: np.ndarray) -> None:
"""Set vertex colors"""
class TextureVisuals:
"""Texture-based visual properties"""
@property
def material(self):
"""Material properties object"""
@property
def uv(self) -> np.ndarray:
"""
UV texture coordinates.
Returns:
(n, 2) UV coordinates for vertices
"""
def copy(self) -> 'TextureVisuals':
"""Create copy of texture visuals"""Manage complex scenes with multiple objects and transformations.
class Scene:
"""Scene graph for multiple geometries with transforms"""
@property
def geometry(self) -> dict:
"""Dictionary of geometry objects in scene"""
@property
def graph(self) -> dict:
"""Scene graph with transformation hierarchy"""
@property
def bounds(self) -> np.ndarray:
"""Combined bounds of all geometries"""
@property
def extents(self) -> np.ndarray:
"""Size of scene bounding box"""
@property
def centroid(self) -> np.ndarray:
"""Geometric center of scene"""
def add_geometry(self, geometry, node_name=None, geom_name=None, parent_node_name=None, transform=None) -> str:
"""
Add geometry to scene.
Parameters:
- geometry: Trimesh or other geometry object
- node_name: str, name for scene graph node
- geom_name: str, name for geometry object
- parent_node_name: str, parent node for hierarchy
- transform: (4, 4) transformation matrix
Returns:
str, name of created node
"""
def delete_geometry(self, names) -> None:
"""
Remove geometry from scene.
Parameters:
- names: str or list of geometry names to remove
"""
def set_camera_transform(self, transform=None, angles=None, distance=None, center=None) -> None:
"""
Set camera position and orientation.
Parameters:
- transform: (4, 4) camera transformation matrix
- angles: (3,) camera rotation angles
- distance: float, distance from center
- center: (3,) point to look at
"""Control lighting conditions and shading models.
def set_lights(self, lights=None) -> None:
"""
Set scene lighting.
Parameters:
- lights: list of light dictionaries or None for default
"""
class DirectionalLight:
"""Directional light source"""
def __init__(self, direction=[0, 0, -1], color=[1, 1, 1], intensity=1.0):
"""
Parameters:
- direction: (3,) light direction vector
- color: (3,) RGB color
- intensity: float, light intensity
"""
class PointLight:
"""Point light source"""
def __init__(self, position=[0, 0, 0], color=[1, 1, 1], intensity=1.0):
"""
Parameters:
- position: (3,) light position
- color: (3,) RGB color
- intensity: float, light intensity
"""Export scenes and render to various formats.
def export(self, file_obj=None, file_type=None, **kwargs):
"""
Export scene to file.
Parameters:
- file_obj: file path or file-like object
- file_type: str, export format
- **kwargs: format-specific options
Returns:
bytes if file_obj is None
"""
def save_image(self, resolution=(1920, 1080), visible=True, **kwargs) -> bytes:
"""
Render scene to image.
Parameters:
- resolution: (width, height) pixel resolution
- visible: bool, show viewer window during render
- **kwargs: rendering options
Returns:
bytes, PNG image data
"""
def to_gltf(self, merge_buffers=True, **kwargs) -> dict:
"""
Convert scene to GLTF format.
Parameters:
- merge_buffers: bool, combine binary data
- **kwargs: GLTF export options
Returns:
dict, GLTF scene data
"""Display meshes and scenes in Jupyter notebooks.
def scene_to_notebook(scene, height=500, **kwargs):
"""
Display scene in Jupyter notebook.
Parameters:
- scene: Scene object to display
- height: int, viewer height in pixels
- **kwargs: notebook viewer options
Returns:
Interactive 3D widget for notebook
"""
def scene_to_html(scene, **kwargs) -> str:
"""
Generate HTML for scene visualization.
Parameters:
- scene: Scene object
- **kwargs: HTML generation options
Returns:
str, HTML content for 3D visualization
"""
def in_notebook() -> bool:
"""
Check if running in Jupyter notebook.
Returns:
bool, True if in notebook environment
"""Customize viewer appearance and behavior.
class SceneViewer:
"""Interactive OpenGL scene viewer"""
def __init__(self, scene, start_loop=True, **kwargs):
"""
Parameters:
- scene: Scene object to display
- start_loop: bool, start event loop immediately
- **kwargs: viewer options
"""
def save_image(self, filename=None) -> None:
"""Save current view as image"""
def reset_view(self) -> None:
"""Reset camera to default position"""
def on_key_press(self, symbol, modifiers) -> None:
"""Handle keyboard input"""
def on_mouse_press(self, x, y, button, modifiers) -> None:
"""Handle mouse input"""Work with colors, textures, and visual materials.
def random_color() -> np.ndarray:
"""
Generate random RGBA color.
Returns:
(4,) RGBA color array
"""
def interpolate_color(color_a, color_b, factor) -> np.ndarray:
"""
Interpolate between two colors.
Parameters:
- color_a: (3,) or (4,) first color
- color_b: (3,) or (4,) second color
- factor: float, interpolation factor (0-1)
Returns:
Interpolated color array
"""
def to_rgba(colors) -> np.ndarray:
"""
Convert colors to RGBA format.
Parameters:
- colors: color array in various formats
Returns:
(n, 4) RGBA color array
"""
def vertex_colors_from_face_colors(mesh, face_colors) -> np.ndarray:
"""
Convert face colors to vertex colors by averaging.
Parameters:
- mesh: Trimesh object
- face_colors: (m, 3) or (m, 4) face colors
Returns:
(n, 4) vertex colors
"""import trimesh
import numpy as np
# Load and display mesh
mesh = trimesh.load('model.stl')
mesh.show() # Opens interactive 3D viewer
# Create scene with multiple objects
scene = trimesh.Scene()
# Add meshes to scene
box = trimesh.primitives.Box(extents=[1, 1, 1])
sphere = trimesh.primitives.Sphere(radius=0.5)
# Position objects with transforms
box_transform = trimesh.transformations.translation_matrix([2, 0, 0])
sphere_transform = trimesh.transformations.translation_matrix([-2, 0, 0])
scene.add_geometry(box, transform=box_transform)
scene.add_geometry(sphere, transform=sphere_transform)
scene.add_geometry(mesh) # At origin
# Display scene
scene.show()# Set solid colors
mesh.visual.face_colors = [255, 0, 0, 255] # Red faces
mesh.visual.vertex_colors = np.random.randint(0, 255, (len(mesh.vertices), 4)) # Random vertex colors
# Color faces by height
face_centers = mesh.triangles_center
heights = face_centers[:, 2] # Z-coordinates
normalized_heights = (heights - heights.min()) / (heights.max() - heights.min())
# Create color map
import matplotlib.pyplot as plt
colors = plt.cm.viridis(normalized_heights)
mesh.visual.face_colors = (colors * 255).astype(np.uint8)
mesh.show()
# Color vertices by curvature
if hasattr(mesh, 'discrete_mean_curvature_measure'):
curvature = mesh.discrete_mean_curvature_measure()
curvature_normalized = (curvature - curvature.min()) / (curvature.max() - curvature.min())
curvature_colors = plt.cm.coolwarm(curvature_normalized)
mesh.visual.vertex_colors = (curvature_colors * 255).astype(np.uint8)
mesh.show()# Create complex scene
scene = trimesh.Scene()
# Add multiple geometries with different materials
geometries = [
(trimesh.primitives.Box(extents=[1, 1, 1]), [1, 0, 0], [0, 0, 0]), # Red box at origin
(trimesh.primitives.Sphere(radius=0.7), [0, 1, 0], [3, 0, 0]), # Green sphere
(trimesh.primitives.Cylinder(radius=0.5, height=2), [0, 0, 1], [0, 3, 0]), # Blue cylinder
]
for geom, color, position in geometries:
# Set color
geom.visual.face_colors = color + [1.0] # Add alpha
# Create transform
transform = trimesh.transformations.translation_matrix(position)
# Add to scene
scene.add_geometry(geom, transform=transform)
# Set camera position
scene.set_camera_transform(
distance=10,
center=[1.5, 1.5, 0],
angles=[np.pi/6, np.pi/4, 0]
)
# Display scene
scene.show()
# Save scene as image
image_data = scene.save_image(resolution=(1920, 1080))
with open('scene_render.png', 'wb') as f:
f.write(image_data)# Create scene with custom lighting
scene = trimesh.Scene([mesh])
# Define multiple light sources
lights = [
{
'type': 'DirectionalLight',
'direction': [1, -1, -1],
'color': [1.0, 1.0, 1.0],
'intensity': 0.8
},
{
'type': 'DirectionalLight',
'direction': [-1, 1, 0.5],
'color': [0.8, 0.9, 1.0], # Slightly blue
'intensity': 0.4
},
{
'type': 'PointLight',
'position': [0, 0, 5],
'color': [1.0, 0.8, 0.6], # Warm color
'intensity': 0.6
}
]
scene.set_lights(lights)
scene.show()# In Jupyter notebook
import trimesh
from trimesh.viewer import scene_to_notebook
# Create scene
mesh = trimesh.load('model.stl')
scene = mesh.scene()
# Display in notebook with custom height
scene_to_notebook(scene, height=600)
# Or generate HTML for embedding
html_content = trimesh.viewer.scene_to_html(scene)
from IPython.display import HTML
HTML(html_content)# Transparency and advanced materials
mesh.visual.face_colors = [128, 128, 255, 100] # Semi-transparent blue
# Wireframe visualization
edges = mesh.edges_unique
edge_viz = trimesh.load_path(mesh.vertices[edges])
edge_viz.colors = [255, 255, 255, 255] # White edges
# Combine mesh and wireframe in scene
scene = trimesh.Scene([mesh, edge_viz])
scene.show()
# Vertex highlighting
# Find boundary vertices (if mesh has boundary)
boundary_edges = mesh.edges[mesh.face_adjacency_edges[mesh.face_adjacency_unshared]]
boundary_vertices = np.unique(boundary_edges)
# Create vertex color array
vertex_colors = np.full((len(mesh.vertices), 4), [200, 200, 200, 255]) # Gray default
vertex_colors[boundary_vertices] = [255, 0, 0, 255] # Red boundary vertices
mesh.visual.vertex_colors = vertex_colors
mesh.show()
# Normal visualization
face_centers = mesh.triangles_center
face_normals = mesh.face_normals
normal_length = 0.1
# Create line segments for normals
normal_lines = []
for center, normal in zip(face_centers, face_normals):
normal_lines.extend([center, center + normal * normal_length])
normal_path = trimesh.load_path(np.array(normal_lines).reshape(-1, 3))
normal_path.colors = [0, 255, 0, 255] # Green normals
# Show mesh with normals
scene = trimesh.Scene([mesh, normal_path])
scene.show()# Render high-quality images
scene = mesh.scene()
# Set up professional lighting
scene.set_lights([
{'type': 'DirectionalLight', 'direction': [1, -1, -1], 'intensity': 0.8},
{'type': 'DirectionalLight', 'direction': [-1, 1, 0.5], 'intensity': 0.3},
])
# Render at different resolutions
resolutions = [(1920, 1080), (3840, 2160), (1024, 1024)]
for i, res in enumerate(resolutions):
image_data = scene.save_image(resolution=res)
with open(f'render_{res[0]}x{res[1]}.png', 'wb') as f:
f.write(image_data)
# Export scene to various formats
scene.export('scene.gltf') # GLTF with materials
scene.export('scene.obj') # OBJ format
scene.export('scene.dae') # COLLADA format
# Export to web-friendly format
gltf_data = scene.to_gltf(merge_buffers=True)
import json
with open('scene_web.gltf', 'w') as f:
json.dump(gltf_data, f, indent=2)Install with Tessl CLI
npx tessl i tessl/pypi-trimesh