0
# Scene Data Structures
1
2
Complete scene graph representation including nodes, meshes, materials, textures, animations, cameras, lights, and metadata. PyAssimp provides hierarchical access to all 3D scene components with Python-friendly data structures and optional NumPy array integration.
3
4
## Capabilities
5
6
### Scene Container
7
8
Root container for all 3D scene data and resources.
9
10
```python { .api }
11
class Scene:
12
"""
13
Root scene container holding all 3D data.
14
15
Attributes:
16
- rootnode: Node, root node of scene hierarchy
17
- meshes: list, list of Mesh objects
18
- materials: list, list of Material objects
19
- textures: list, list of embedded Texture objects
20
- animations: list, list of Animation sequences
21
- cameras: list, list of Camera objects
22
- lights: list, list of Light objects
23
"""
24
rootnode: Node
25
meshes: list
26
materials: list
27
textures: list
28
animations: list
29
cameras: list
30
lights: list
31
```
32
33
Usage examples:
34
35
```python
36
import pyassimp
37
38
scene = pyassimp.load("model.dae")
39
40
# Access scene components
41
print(f"Scene has {len(scene.meshes)} meshes")
42
print(f"Scene has {len(scene.materials)} materials")
43
print(f"Scene has {len(scene.textures)} embedded textures")
44
print(f"Scene has {len(scene.animations)} animations")
45
46
# Traverse scene hierarchy
47
def print_node_hierarchy(node, depth=0):
48
indent = " " * depth
49
print(f"{indent}Node: {node.name}")
50
print(f"{indent} Meshes: {len(node.meshes)}")
51
print(f"{indent} Children: {len(node.children)}")
52
53
for child in node.children:
54
print_node_hierarchy(child, depth + 1)
55
56
print_node_hierarchy(scene.rootnode)
57
58
pyassimp.release(scene)
59
```
60
61
### Scene Graph Nodes
62
63
Hierarchical scene graph nodes containing transformation data and mesh references.
64
65
```python { .api }
66
class Node:
67
"""
68
Scene graph node representing spatial hierarchy.
69
70
Attributes:
71
- name: str, node name/identifier
72
- transformation: array, 4x4 transformation matrix (numpy array if available)
73
- parent: Node, parent node (None for root)
74
- children: list, child Node objects
75
- meshes: list, mesh references/indices for this node
76
"""
77
name: str
78
transformation: array
79
parent: Node
80
children: list
81
meshes: list
82
```
83
84
Usage examples:
85
86
```python
87
import pyassimp
88
import numpy as np
89
90
scene = pyassimp.load("model.dae")
91
92
def process_node(node):
93
print(f"Processing node: {node.name}")
94
95
# Access transformation matrix
96
if hasattr(node, 'transformation'):
97
transform = node.transformation
98
print(f"Transform matrix shape: {transform.shape if hasattr(transform, 'shape') else len(transform)}")
99
100
# Decompose transformation if needed
101
if isinstance(transform, np.ndarray):
102
# NumPy array - can do matrix operations
103
position = transform[:3, 3] # Translation component
104
print(f"Position: {position}")
105
106
# Process node meshes
107
for mesh_ref in node.meshes:
108
mesh = scene.meshes[mesh_ref] if isinstance(mesh_ref, int) else mesh_ref
109
print(f" Mesh: {len(mesh.vertices)} vertices")
110
111
# Recursively process children
112
for child in node.children:
113
process_node(child)
114
115
process_node(scene.rootnode)
116
pyassimp.release(scene)
117
```
118
119
### Mesh Data
120
121
3D mesh geometry data including vertices, faces, normals, texture coordinates, and vertex attributes.
122
123
```python { .api }
124
class Mesh:
125
"""
126
3D mesh data container.
127
128
Attributes:
129
- vertices: array, vertex positions (Nx3)
130
- normals: array, vertex normals (Nx3)
131
- faces: array, face indices
132
- texturecoords: array, UV coordinates (per texture channel)
133
- colors: array, vertex colors (per color channel)
134
- tangents: array, tangent vectors (Nx3)
135
- bitangents: array, bitangent vectors (Nx3)
136
- materialindex: int, index into scene materials list
137
- name: str, mesh name
138
"""
139
vertices: array
140
normals: array
141
faces: array
142
texturecoords: array
143
colors: array
144
tangents: array
145
bitangents: array
146
materialindex: int
147
name: str
148
```
149
150
Usage examples:
151
152
```python
153
import pyassimp
154
import numpy as np
155
156
scene = pyassimp.load("model.obj", processing=pyassimp.postprocess.aiProcess_Triangulate)
157
158
for i, mesh in enumerate(scene.meshes):
159
print(f"Mesh {i}: {mesh.name}")
160
161
# Vertex data
162
print(f" Vertices: {len(mesh.vertices)} ({mesh.vertices.shape if hasattr(mesh.vertices, 'shape') else 'list'})")
163
164
# Face data
165
print(f" Faces: {len(mesh.faces)}")
166
if mesh.faces:
167
face = mesh.faces[0]
168
print(f" First face indices: {face.indices if hasattr(face, 'indices') else face}")
169
170
# Normal data
171
if hasattr(mesh, 'normals') and mesh.normals is not None:
172
print(f" Normals: {len(mesh.normals)}")
173
174
# UV coordinates
175
if hasattr(mesh, 'texturecoords') and mesh.texturecoords is not None:
176
uv_channels = len(mesh.texturecoords) if isinstance(mesh.texturecoords, list) else 1
177
print(f" UV channels: {uv_channels}")
178
179
# Vertex colors
180
if hasattr(mesh, 'colors') and mesh.colors is not None:
181
color_channels = len(mesh.colors) if isinstance(mesh.colors, list) else 1
182
print(f" Color channels: {color_channels}")
183
184
# Material reference
185
print(f" Material index: {mesh.materialindex}")
186
if mesh.materialindex < len(scene.materials):
187
material = scene.materials[mesh.materialindex]
188
print(f" Material properties: {len(material.properties)}")
189
190
pyassimp.release(scene)
191
```
192
193
### Face Data
194
195
Polygon face definitions with vertex indices.
196
197
```python { .api }
198
class Face:
199
"""
200
Polygon face with vertex indices.
201
202
Attributes:
203
- indices: list, vertex indices forming this face
204
"""
205
indices: list
206
```
207
208
Usage examples:
209
210
```python
211
import pyassimp
212
213
scene = pyassimp.load("model.ply", processing=pyassimp.postprocess.aiProcess_Triangulate)
214
215
mesh = scene.meshes[0]
216
print(f"Mesh has {len(mesh.faces)} faces")
217
218
# Access face data
219
for i, face in enumerate(mesh.faces[:5]): # First 5 faces
220
if hasattr(face, 'indices'):
221
indices = face.indices
222
else:
223
indices = face # May be direct list after processing
224
225
print(f"Face {i}: vertices {indices}")
226
227
# Access vertex positions for this face
228
if hasattr(indices, '__iter__'):
229
for vertex_idx in indices:
230
if vertex_idx < len(mesh.vertices):
231
vertex = mesh.vertices[vertex_idx]
232
print(f" Vertex {vertex_idx}: {vertex}")
233
234
pyassimp.release(scene)
235
```
236
237
### Animation Data
238
239
Animation sequences and keyframe data.
240
241
```python { .api }
242
class Animation:
243
"""
244
Animation sequence data.
245
246
Attributes:
247
- name: str, animation name
248
- duration: float, animation duration
249
- tickspersecond: float, time units per second
250
- channels: list, animation channels for different nodes
251
"""
252
name: str
253
duration: float
254
tickspersecond: float
255
channels: list
256
```
257
258
Usage examples:
259
260
```python
261
import pyassimp
262
263
scene = pyassimp.load("animated_model.dae")
264
265
if scene.animations:
266
for i, animation in enumerate(scene.animations):
267
print(f"Animation {i}: {animation.name}")
268
print(f" Duration: {animation.duration}")
269
print(f" Ticks per second: {animation.tickspersecond}")
270
print(f" Channels: {len(animation.channels)}")
271
272
# Process animation channels
273
for channel in animation.channels:
274
print(f" Channel node: {channel.nodename if hasattr(channel, 'nodename') else 'unknown'}")
275
276
pyassimp.release(scene)
277
```
278
279
### Camera Data
280
281
3D camera definitions with projection parameters.
282
283
```python { .api }
284
class Camera:
285
"""
286
3D camera definition.
287
288
Attributes:
289
- name: str, camera name
290
- position: Vector3D, camera position
291
- lookat: Vector3D, look-at target direction
292
- up: Vector3D, up vector
293
- horizontalfov: float, horizontal field of view
294
- aspect: float, aspect ratio
295
- clipplanenear: float, near clipping plane
296
- clipplanefar: float, far clipping plane
297
"""
298
name: str
299
position: Vector3D
300
lookat: Vector3D
301
up: Vector3D
302
horizontalfov: float
303
aspect: float
304
clipplanenear: float
305
clipplanefar: float
306
```
307
308
Usage examples:
309
310
```python
311
import pyassimp
312
313
scene = pyassimp.load("scene_with_camera.dae")
314
315
if scene.cameras:
316
for i, camera in enumerate(scene.cameras):
317
print(f"Camera {i}: {camera.name}")
318
if hasattr(camera, 'position'):
319
pos = camera.position
320
print(f" Position: ({pos.x}, {pos.y}, {pos.z})")
321
if hasattr(camera, 'horizontalfov'):
322
print(f" FOV: {camera.horizontalfov} radians")
323
if hasattr(camera, 'aspect'):
324
print(f" Aspect ratio: {camera.aspect}")
325
326
pyassimp.release(scene)
327
```
328
329
### Light Data
330
331
Scene lighting definitions.
332
333
```python { .api }
334
class Light:
335
"""
336
Light source definition.
337
338
Attributes:
339
- name: str, light name
340
- type: int, light type (directional, point, spot, etc.)
341
- position: Vector3D, light position
342
- direction: Vector3D, light direction
343
- colorambient: Color3D, ambient color
344
- colordiffuse: Color3D, diffuse color
345
- colorspecular: Color3D, specular color
346
- attenuation*: float, attenuation parameters
347
- angle*: float, spotlight angle parameters
348
"""
349
name: str
350
type: int
351
position: Vector3D
352
direction: Vector3D
353
colorambient: Color3D
354
colordiffuse: Color3D
355
colorspecular: Color3D
356
```
357
358
Usage examples:
359
360
```python
361
import pyassimp
362
363
scene = pyassimp.load("lit_scene.dae")
364
365
if scene.lights:
366
for i, light in enumerate(scene.lights):
367
print(f"Light {i}: {light.name}")
368
if hasattr(light, 'type'):
369
print(f" Type: {light.type}")
370
if hasattr(light, 'colordiffuse'):
371
color = light.colordiffuse
372
print(f" Diffuse color: ({color.r}, {color.g}, {color.b})")
373
374
pyassimp.release(scene)
375
```
376
377
### Metadata
378
379
Key-value metadata storage for additional scene information.
380
381
```python { .api }
382
class Metadata:
383
"""
384
Key-value metadata container.
385
386
Attributes:
387
- keys: list, metadata key names
388
- values: list, MetadataEntry objects with typed values
389
"""
390
keys: list
391
values: list
392
393
class MetadataEntry:
394
"""
395
Individual metadata entry with type information.
396
397
Attributes:
398
- type: int, data type identifier
399
- data: any, typed data value
400
401
Type Constants:
402
- AI_BOOL = 0, boolean value
403
- AI_INT32 = 1, 32-bit integer
404
- AI_UINT64 = 2, 64-bit unsigned integer
405
- AI_FLOAT = 3, floating point number
406
- AI_DOUBLE = 4, double precision float
407
- AI_AISTRING = 5, string value
408
- AI_AIVECTOR3D = 6, 3D vector
409
"""
410
type: int
411
data: any
412
413
AI_BOOL = 0
414
AI_INT32 = 1
415
AI_UINT64 = 2
416
AI_FLOAT = 3
417
AI_DOUBLE = 4
418
AI_AISTRING = 5
419
AI_AIVECTOR3D = 6
420
```
421
422
Usage examples:
423
424
```python
425
import pyassimp
426
427
scene = pyassimp.load("model_with_metadata.dae")
428
429
# Check for metadata on scene root
430
if hasattr(scene.rootnode, 'metadata') and scene.rootnode.metadata:
431
metadata = scene.rootnode.metadata
432
print(f"Metadata entries: {len(metadata.keys)}")
433
434
for key, value_entry in zip(metadata.keys, metadata.values):
435
print(f" {key}: {value_entry.data} (type: {value_entry.type})")
436
437
pyassimp.release(scene)
438
```
439
440
## Data Access Patterns
441
442
### Efficient Vertex Processing
443
444
```python
445
import pyassimp
446
import numpy as np
447
448
scene = pyassimp.load("model.obj")
449
450
for mesh in scene.meshes:
451
# Direct access to vertex arrays
452
vertices = mesh.vertices
453
454
if isinstance(vertices, np.ndarray):
455
# NumPy array - efficient operations
456
centroid = np.mean(vertices, axis=0)
457
bounds_min = np.min(vertices, axis=0)
458
bounds_max = np.max(vertices, axis=0)
459
print(f"Centroid: {centroid}")
460
print(f"Bounds: {bounds_min} to {bounds_max}")
461
else:
462
# Python list - slower but compatible
463
if vertices:
464
centroid = [sum(v[i] for v in vertices)/len(vertices) for i in range(3)]
465
print(f"Centroid: {centroid}")
466
467
pyassimp.release(scene)
468
```
469
470
### Scene Statistics
471
472
```python
473
import pyassimp
474
475
def analyze_scene(filename):
476
scene = pyassimp.load(filename)
477
478
stats = {
479
'nodes': 0,
480
'meshes': len(scene.meshes),
481
'materials': len(scene.materials),
482
'textures': len(scene.textures),
483
'animations': len(scene.animations),
484
'cameras': len(scene.cameras),
485
'lights': len(scene.lights),
486
'total_vertices': 0,
487
'total_faces': 0
488
}
489
490
def count_nodes(node):
491
stats['nodes'] += 1
492
for child in node.children:
493
count_nodes(child)
494
495
count_nodes(scene.rootnode)
496
497
for mesh in scene.meshes:
498
stats['total_vertices'] += len(mesh.vertices) if mesh.vertices else 0
499
stats['total_faces'] += len(mesh.faces) if mesh.faces else 0
500
501
pyassimp.release(scene)
502
return stats
503
504
# Usage
505
stats = analyze_scene("complex_model.dae")
506
for key, value in stats.items():
507
print(f"{key}: {value}")
508
```
509
510
### Memory Usage Optimization
511
512
```python
513
import pyassimp
514
515
def load_geometry_only(filename):
516
"""Load only geometry data, skip animations, cameras, etc."""
517
518
# Use component removal to skip unwanted data
519
processing = (pyassimp.postprocess.aiProcess_Triangulate |
520
pyassimp.postprocess.aiProcess_RemoveComponent)
521
522
# Note: RemoveComponent needs configuration via AI_CONFIG_PP_RVC_FLAGS
523
# This is a simplified example
524
scene = pyassimp.load(filename, processing=processing)
525
526
# Extract only needed data
527
geometry_data = []
528
for mesh in scene.meshes:
529
mesh_data = {
530
'vertices': mesh.vertices,
531
'faces': mesh.faces,
532
'normals': getattr(mesh, 'normals', None),
533
'material_idx': mesh.materialindex
534
}
535
geometry_data.append(mesh_data)
536
537
pyassimp.release(scene)
538
return geometry_data
539
```