0
# Visualization and Rendering
1
2
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.
3
4
## Capabilities
5
6
### Interactive 3D Viewing
7
8
Display meshes and scenes in interactive 3D viewers.
9
10
```python { .api }
11
def show(self, viewer=None, **kwargs) -> None:
12
"""
13
Display mesh in interactive 3D viewer.
14
15
Parameters:
16
- viewer: str, viewer type ('gl', 'notebook', 'pyglet')
17
- **kwargs: viewer-specific options like window size, lighting
18
"""
19
20
def scene(self) -> Scene:
21
"""
22
Create Scene object containing this mesh.
23
24
Returns:
25
Scene object with mesh added
26
"""
27
28
class Scene:
29
"""Scene graph container for multiple geometries"""
30
31
def show(self, viewer=None, **kwargs) -> None:
32
"""Display scene in interactive viewer"""
33
34
def save_image(self, resolution=(1920, 1080), **kwargs) -> bytes:
35
"""
36
Render scene to image.
37
38
Parameters:
39
- resolution: (width, height) image size
40
- **kwargs: rendering options
41
42
Returns:
43
bytes, PNG image data
44
"""
45
```
46
47
### Visual Properties and Materials
48
49
Control appearance through colors, materials, and textures.
50
51
```python { .api }
52
@property
53
def visual(self):
54
"""Visual properties interface"""
55
56
class ColorVisuals:
57
"""Simple color-based visual properties"""
58
59
@property
60
def face_colors(self) -> np.ndarray:
61
"""
62
Face colors as (m, 4) RGBA array.
63
64
Returns:
65
(m, 4) face colors in RGBA format
66
"""
67
68
@face_colors.setter
69
def face_colors(self, colors: np.ndarray) -> None:
70
"""Set face colors"""
71
72
@property
73
def vertex_colors(self) -> np.ndarray:
74
"""
75
Vertex colors as (n, 4) RGBA array.
76
77
Returns:
78
(n, 4) vertex colors in RGBA format
79
"""
80
81
@vertex_colors.setter
82
def vertex_colors(self, colors: np.ndarray) -> None:
83
"""Set vertex colors"""
84
85
class TextureVisuals:
86
"""Texture-based visual properties"""
87
88
@property
89
def material(self):
90
"""Material properties object"""
91
92
@property
93
def uv(self) -> np.ndarray:
94
"""
95
UV texture coordinates.
96
97
Returns:
98
(n, 2) UV coordinates for vertices
99
"""
100
101
def copy(self) -> 'TextureVisuals':
102
"""Create copy of texture visuals"""
103
```
104
105
### Scene Management
106
107
Manage complex scenes with multiple objects and transformations.
108
109
```python { .api }
110
class Scene:
111
"""Scene graph for multiple geometries with transforms"""
112
113
@property
114
def geometry(self) -> dict:
115
"""Dictionary of geometry objects in scene"""
116
117
@property
118
def graph(self) -> dict:
119
"""Scene graph with transformation hierarchy"""
120
121
@property
122
def bounds(self) -> np.ndarray:
123
"""Combined bounds of all geometries"""
124
125
@property
126
def extents(self) -> np.ndarray:
127
"""Size of scene bounding box"""
128
129
@property
130
def centroid(self) -> np.ndarray:
131
"""Geometric center of scene"""
132
133
def add_geometry(self, geometry, node_name=None, geom_name=None, parent_node_name=None, transform=None) -> str:
134
"""
135
Add geometry to scene.
136
137
Parameters:
138
- geometry: Trimesh or other geometry object
139
- node_name: str, name for scene graph node
140
- geom_name: str, name for geometry object
141
- parent_node_name: str, parent node for hierarchy
142
- transform: (4, 4) transformation matrix
143
144
Returns:
145
str, name of created node
146
"""
147
148
def delete_geometry(self, names) -> None:
149
"""
150
Remove geometry from scene.
151
152
Parameters:
153
- names: str or list of geometry names to remove
154
"""
155
156
def set_camera_transform(self, transform=None, angles=None, distance=None, center=None) -> None:
157
"""
158
Set camera position and orientation.
159
160
Parameters:
161
- transform: (4, 4) camera transformation matrix
162
- angles: (3,) camera rotation angles
163
- distance: float, distance from center
164
- center: (3,) point to look at
165
"""
166
```
167
168
### Lighting and Shading
169
170
Control lighting conditions and shading models.
171
172
```python { .api }
173
def set_lights(self, lights=None) -> None:
174
"""
175
Set scene lighting.
176
177
Parameters:
178
- lights: list of light dictionaries or None for default
179
"""
180
181
class DirectionalLight:
182
"""Directional light source"""
183
def __init__(self, direction=[0, 0, -1], color=[1, 1, 1], intensity=1.0):
184
"""
185
Parameters:
186
- direction: (3,) light direction vector
187
- color: (3,) RGB color
188
- intensity: float, light intensity
189
"""
190
191
class PointLight:
192
"""Point light source"""
193
def __init__(self, position=[0, 0, 0], color=[1, 1, 1], intensity=1.0):
194
"""
195
Parameters:
196
- position: (3,) light position
197
- color: (3,) RGB color
198
- intensity: float, light intensity
199
"""
200
```
201
202
### Export and Rendering
203
204
Export scenes and render to various formats.
205
206
```python { .api }
207
def export(self, file_obj=None, file_type=None, **kwargs):
208
"""
209
Export scene to file.
210
211
Parameters:
212
- file_obj: file path or file-like object
213
- file_type: str, export format
214
- **kwargs: format-specific options
215
216
Returns:
217
bytes if file_obj is None
218
"""
219
220
def save_image(self, resolution=(1920, 1080), visible=True, **kwargs) -> bytes:
221
"""
222
Render scene to image.
223
224
Parameters:
225
- resolution: (width, height) pixel resolution
226
- visible: bool, show viewer window during render
227
- **kwargs: rendering options
228
229
Returns:
230
bytes, PNG image data
231
"""
232
233
def to_gltf(self, merge_buffers=True, **kwargs) -> dict:
234
"""
235
Convert scene to GLTF format.
236
237
Parameters:
238
- merge_buffers: bool, combine binary data
239
- **kwargs: GLTF export options
240
241
Returns:
242
dict, GLTF scene data
243
"""
244
```
245
246
### Jupyter Notebook Integration
247
248
Display meshes and scenes in Jupyter notebooks.
249
250
```python { .api }
251
def scene_to_notebook(scene, height=500, **kwargs):
252
"""
253
Display scene in Jupyter notebook.
254
255
Parameters:
256
- scene: Scene object to display
257
- height: int, viewer height in pixels
258
- **kwargs: notebook viewer options
259
260
Returns:
261
Interactive 3D widget for notebook
262
"""
263
264
def scene_to_html(scene, **kwargs) -> str:
265
"""
266
Generate HTML for scene visualization.
267
268
Parameters:
269
- scene: Scene object
270
- **kwargs: HTML generation options
271
272
Returns:
273
str, HTML content for 3D visualization
274
"""
275
276
def in_notebook() -> bool:
277
"""
278
Check if running in Jupyter notebook.
279
280
Returns:
281
bool, True if in notebook environment
282
"""
283
```
284
285
### Viewer Customization
286
287
Customize viewer appearance and behavior.
288
289
```python { .api }
290
class SceneViewer:
291
"""Interactive OpenGL scene viewer"""
292
293
def __init__(self, scene, start_loop=True, **kwargs):
294
"""
295
Parameters:
296
- scene: Scene object to display
297
- start_loop: bool, start event loop immediately
298
- **kwargs: viewer options
299
"""
300
301
def save_image(self, filename=None) -> None:
302
"""Save current view as image"""
303
304
def reset_view(self) -> None:
305
"""Reset camera to default position"""
306
307
def on_key_press(self, symbol, modifiers) -> None:
308
"""Handle keyboard input"""
309
310
def on_mouse_press(self, x, y, button, modifiers) -> None:
311
"""Handle mouse input"""
312
```
313
314
### Color and Texture Utilities
315
316
Work with colors, textures, and visual materials.
317
318
```python { .api }
319
def random_color() -> np.ndarray:
320
"""
321
Generate random RGBA color.
322
323
Returns:
324
(4,) RGBA color array
325
"""
326
327
def interpolate_color(color_a, color_b, factor) -> np.ndarray:
328
"""
329
Interpolate between two colors.
330
331
Parameters:
332
- color_a: (3,) or (4,) first color
333
- color_b: (3,) or (4,) second color
334
- factor: float, interpolation factor (0-1)
335
336
Returns:
337
Interpolated color array
338
"""
339
340
def to_rgba(colors) -> np.ndarray:
341
"""
342
Convert colors to RGBA format.
343
344
Parameters:
345
- colors: color array in various formats
346
347
Returns:
348
(n, 4) RGBA color array
349
"""
350
351
def vertex_colors_from_face_colors(mesh, face_colors) -> np.ndarray:
352
"""
353
Convert face colors to vertex colors by averaging.
354
355
Parameters:
356
- mesh: Trimesh object
357
- face_colors: (m, 3) or (m, 4) face colors
358
359
Returns:
360
(n, 4) vertex colors
361
"""
362
```
363
364
## Usage Examples
365
366
### Basic Visualization
367
368
```python
369
import trimesh
370
import numpy as np
371
372
# Load and display mesh
373
mesh = trimesh.load('model.stl')
374
mesh.show() # Opens interactive 3D viewer
375
376
# Create scene with multiple objects
377
scene = trimesh.Scene()
378
379
# Add meshes to scene
380
box = trimesh.primitives.Box(extents=[1, 1, 1])
381
sphere = trimesh.primitives.Sphere(radius=0.5)
382
383
# Position objects with transforms
384
box_transform = trimesh.transformations.translation_matrix([2, 0, 0])
385
sphere_transform = trimesh.transformations.translation_matrix([-2, 0, 0])
386
387
scene.add_geometry(box, transform=box_transform)
388
scene.add_geometry(sphere, transform=sphere_transform)
389
scene.add_geometry(mesh) # At origin
390
391
# Display scene
392
scene.show()
393
```
394
395
### Colors and Materials
396
397
```python
398
# Set solid colors
399
mesh.visual.face_colors = [255, 0, 0, 255] # Red faces
400
mesh.visual.vertex_colors = np.random.randint(0, 255, (len(mesh.vertices), 4)) # Random vertex colors
401
402
# Color faces by height
403
face_centers = mesh.triangles_center
404
heights = face_centers[:, 2] # Z-coordinates
405
normalized_heights = (heights - heights.min()) / (heights.max() - heights.min())
406
407
# Create color map
408
import matplotlib.pyplot as plt
409
colors = plt.cm.viridis(normalized_heights)
410
mesh.visual.face_colors = (colors * 255).astype(np.uint8)
411
412
mesh.show()
413
414
# Color vertices by curvature
415
if hasattr(mesh, 'discrete_mean_curvature_measure'):
416
curvature = mesh.discrete_mean_curvature_measure()
417
curvature_normalized = (curvature - curvature.min()) / (curvature.max() - curvature.min())
418
419
curvature_colors = plt.cm.coolwarm(curvature_normalized)
420
mesh.visual.vertex_colors = (curvature_colors * 255).astype(np.uint8)
421
mesh.show()
422
```
423
424
### Scene Management
425
426
```python
427
# Create complex scene
428
scene = trimesh.Scene()
429
430
# Add multiple geometries with different materials
431
geometries = [
432
(trimesh.primitives.Box(extents=[1, 1, 1]), [1, 0, 0], [0, 0, 0]), # Red box at origin
433
(trimesh.primitives.Sphere(radius=0.7), [0, 1, 0], [3, 0, 0]), # Green sphere
434
(trimesh.primitives.Cylinder(radius=0.5, height=2), [0, 0, 1], [0, 3, 0]), # Blue cylinder
435
]
436
437
for geom, color, position in geometries:
438
# Set color
439
geom.visual.face_colors = color + [1.0] # Add alpha
440
441
# Create transform
442
transform = trimesh.transformations.translation_matrix(position)
443
444
# Add to scene
445
scene.add_geometry(geom, transform=transform)
446
447
# Set camera position
448
scene.set_camera_transform(
449
distance=10,
450
center=[1.5, 1.5, 0],
451
angles=[np.pi/6, np.pi/4, 0]
452
)
453
454
# Display scene
455
scene.show()
456
457
# Save scene as image
458
image_data = scene.save_image(resolution=(1920, 1080))
459
with open('scene_render.png', 'wb') as f:
460
f.write(image_data)
461
```
462
463
### Custom Lighting
464
465
```python
466
# Create scene with custom lighting
467
scene = trimesh.Scene([mesh])
468
469
# Define multiple light sources
470
lights = [
471
{
472
'type': 'DirectionalLight',
473
'direction': [1, -1, -1],
474
'color': [1.0, 1.0, 1.0],
475
'intensity': 0.8
476
},
477
{
478
'type': 'DirectionalLight',
479
'direction': [-1, 1, 0.5],
480
'color': [0.8, 0.9, 1.0], # Slightly blue
481
'intensity': 0.4
482
},
483
{
484
'type': 'PointLight',
485
'position': [0, 0, 5],
486
'color': [1.0, 0.8, 0.6], # Warm color
487
'intensity': 0.6
488
}
489
]
490
491
scene.set_lights(lights)
492
scene.show()
493
```
494
495
### Jupyter Notebook Visualization
496
497
```python
498
# In Jupyter notebook
499
import trimesh
500
from trimesh.viewer import scene_to_notebook
501
502
# Create scene
503
mesh = trimesh.load('model.stl')
504
scene = mesh.scene()
505
506
# Display in notebook with custom height
507
scene_to_notebook(scene, height=600)
508
509
# Or generate HTML for embedding
510
html_content = trimesh.viewer.scene_to_html(scene)
511
from IPython.display import HTML
512
HTML(html_content)
513
```
514
515
### Advanced Visualization Techniques
516
517
```python
518
# Transparency and advanced materials
519
mesh.visual.face_colors = [128, 128, 255, 100] # Semi-transparent blue
520
521
# Wireframe visualization
522
edges = mesh.edges_unique
523
edge_viz = trimesh.load_path(mesh.vertices[edges])
524
edge_viz.colors = [255, 255, 255, 255] # White edges
525
526
# Combine mesh and wireframe in scene
527
scene = trimesh.Scene([mesh, edge_viz])
528
scene.show()
529
530
# Vertex highlighting
531
# Find boundary vertices (if mesh has boundary)
532
boundary_edges = mesh.edges[mesh.face_adjacency_edges[mesh.face_adjacency_unshared]]
533
boundary_vertices = np.unique(boundary_edges)
534
535
# Create vertex color array
536
vertex_colors = np.full((len(mesh.vertices), 4), [200, 200, 200, 255]) # Gray default
537
vertex_colors[boundary_vertices] = [255, 0, 0, 255] # Red boundary vertices
538
539
mesh.visual.vertex_colors = vertex_colors
540
mesh.show()
541
542
# Normal visualization
543
face_centers = mesh.triangles_center
544
face_normals = mesh.face_normals
545
normal_length = 0.1
546
547
# Create line segments for normals
548
normal_lines = []
549
for center, normal in zip(face_centers, face_normals):
550
normal_lines.extend([center, center + normal * normal_length])
551
552
normal_path = trimesh.load_path(np.array(normal_lines).reshape(-1, 3))
553
normal_path.colors = [0, 255, 0, 255] # Green normals
554
555
# Show mesh with normals
556
scene = trimesh.Scene([mesh, normal_path])
557
scene.show()
558
```
559
560
### Export and Rendering
561
562
```python
563
# Render high-quality images
564
scene = mesh.scene()
565
566
# Set up professional lighting
567
scene.set_lights([
568
{'type': 'DirectionalLight', 'direction': [1, -1, -1], 'intensity': 0.8},
569
{'type': 'DirectionalLight', 'direction': [-1, 1, 0.5], 'intensity': 0.3},
570
])
571
572
# Render at different resolutions
573
resolutions = [(1920, 1080), (3840, 2160), (1024, 1024)]
574
for i, res in enumerate(resolutions):
575
image_data = scene.save_image(resolution=res)
576
with open(f'render_{res[0]}x{res[1]}.png', 'wb') as f:
577
f.write(image_data)
578
579
# Export scene to various formats
580
scene.export('scene.gltf') # GLTF with materials
581
scene.export('scene.obj') # OBJ format
582
scene.export('scene.dae') # COLLADA format
583
584
# Export to web-friendly format
585
gltf_data = scene.to_gltf(merge_buffers=True)
586
import json
587
with open('scene_web.gltf', 'w') as f:
588
json.dump(gltf_data, f, indent=2)
589
```