CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyassimp

Python bindings for the Open Asset Import Library (ASSIMP) enabling 3D model loading, processing, and export

Pending
Overview
Eval results
Files

scene-data.mddocs/

Scene Data Structures

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.

Capabilities

Scene Container

Root container for all 3D scene data and resources.

class Scene:
    """
    Root scene container holding all 3D data.
    
    Attributes:
    - rootnode: Node, root node of scene hierarchy
    - meshes: list, list of Mesh objects
    - materials: list, list of Material objects  
    - textures: list, list of embedded Texture objects
    - animations: list, list of Animation sequences
    - cameras: list, list of Camera objects
    - lights: list, list of Light objects
    """
    rootnode: Node
    meshes: list
    materials: list
    textures: list
    animations: list
    cameras: list
    lights: list

Usage examples:

import pyassimp

scene = pyassimp.load("model.dae")

# Access scene components
print(f"Scene has {len(scene.meshes)} meshes")
print(f"Scene has {len(scene.materials)} materials")
print(f"Scene has {len(scene.textures)} embedded textures")
print(f"Scene has {len(scene.animations)} animations")

# Traverse scene hierarchy
def print_node_hierarchy(node, depth=0):
    indent = "  " * depth
    print(f"{indent}Node: {node.name}")
    print(f"{indent}  Meshes: {len(node.meshes)}")
    print(f"{indent}  Children: {len(node.children)}")
    
    for child in node.children:
        print_node_hierarchy(child, depth + 1)

print_node_hierarchy(scene.rootnode)

pyassimp.release(scene)

Scene Graph Nodes

Hierarchical scene graph nodes containing transformation data and mesh references.

class Node:
    """
    Scene graph node representing spatial hierarchy.
    
    Attributes:
    - name: str, node name/identifier
    - transformation: array, 4x4 transformation matrix (numpy array if available)
    - parent: Node, parent node (None for root)
    - children: list, child Node objects
    - meshes: list, mesh references/indices for this node
    """
    name: str
    transformation: array
    parent: Node
    children: list
    meshes: list

Usage examples:

import pyassimp
import numpy as np

scene = pyassimp.load("model.dae")

def process_node(node):
    print(f"Processing node: {node.name}")
    
    # Access transformation matrix
    if hasattr(node, 'transformation'):
        transform = node.transformation
        print(f"Transform matrix shape: {transform.shape if hasattr(transform, 'shape') else len(transform)}")
        
        # Decompose transformation if needed
        if isinstance(transform, np.ndarray):
            # NumPy array - can do matrix operations
            position = transform[:3, 3]  # Translation component
            print(f"Position: {position}")
    
    # Process node meshes
    for mesh_ref in node.meshes:
        mesh = scene.meshes[mesh_ref] if isinstance(mesh_ref, int) else mesh_ref
        print(f"  Mesh: {len(mesh.vertices)} vertices")
    
    # Recursively process children
    for child in node.children:
        process_node(child)

process_node(scene.rootnode)
pyassimp.release(scene)

Mesh Data

3D mesh geometry data including vertices, faces, normals, texture coordinates, and vertex attributes.

class Mesh:
    """
    3D mesh data container.
    
    Attributes:
    - vertices: array, vertex positions (Nx3)
    - normals: array, vertex normals (Nx3)
    - faces: array, face indices
    - texturecoords: array, UV coordinates (per texture channel)
    - colors: array, vertex colors (per color channel)
    - tangents: array, tangent vectors (Nx3)
    - bitangents: array, bitangent vectors (Nx3)
    - materialindex: int, index into scene materials list
    - name: str, mesh name
    """
    vertices: array
    normals: array
    faces: array
    texturecoords: array
    colors: array
    tangents: array
    bitangents: array
    materialindex: int
    name: str

Usage examples:

import pyassimp
import numpy as np

scene = pyassimp.load("model.obj", processing=pyassimp.postprocess.aiProcess_Triangulate)

for i, mesh in enumerate(scene.meshes):
    print(f"Mesh {i}: {mesh.name}")
    
    # Vertex data
    print(f"  Vertices: {len(mesh.vertices)} ({mesh.vertices.shape if hasattr(mesh.vertices, 'shape') else 'list'})")
    
    # Face data
    print(f"  Faces: {len(mesh.faces)}")
    if mesh.faces:
        face = mesh.faces[0]
        print(f"  First face indices: {face.indices if hasattr(face, 'indices') else face}")
    
    # Normal data
    if hasattr(mesh, 'normals') and mesh.normals is not None:
        print(f"  Normals: {len(mesh.normals)}")
    
    # UV coordinates
    if hasattr(mesh, 'texturecoords') and mesh.texturecoords is not None:
        uv_channels = len(mesh.texturecoords) if isinstance(mesh.texturecoords, list) else 1
        print(f"  UV channels: {uv_channels}")
    
    # Vertex colors
    if hasattr(mesh, 'colors') and mesh.colors is not None:
        color_channels = len(mesh.colors) if isinstance(mesh.colors, list) else 1
        print(f"  Color channels: {color_channels}")
    
    # Material reference
    print(f"  Material index: {mesh.materialindex}")
    if mesh.materialindex < len(scene.materials):
        material = scene.materials[mesh.materialindex]
        print(f"  Material properties: {len(material.properties)}")

pyassimp.release(scene)

Face Data

Polygon face definitions with vertex indices.

class Face:
    """
    Polygon face with vertex indices.
    
    Attributes:
    - indices: list, vertex indices forming this face
    """
    indices: list

Usage examples:

import pyassimp

scene = pyassimp.load("model.ply", processing=pyassimp.postprocess.aiProcess_Triangulate)

mesh = scene.meshes[0]
print(f"Mesh has {len(mesh.faces)} faces")

# Access face data
for i, face in enumerate(mesh.faces[:5]):  # First 5 faces
    if hasattr(face, 'indices'):
        indices = face.indices
    else:
        indices = face  # May be direct list after processing
    
    print(f"Face {i}: vertices {indices}")
    
    # Access vertex positions for this face
    if hasattr(indices, '__iter__'):
        for vertex_idx in indices:
            if vertex_idx < len(mesh.vertices):
                vertex = mesh.vertices[vertex_idx]
                print(f"  Vertex {vertex_idx}: {vertex}")

pyassimp.release(scene)

Animation Data

Animation sequences and keyframe data.

class Animation:
    """
    Animation sequence data.
    
    Attributes:
    - name: str, animation name
    - duration: float, animation duration
    - tickspersecond: float, time units per second
    - channels: list, animation channels for different nodes
    """
    name: str
    duration: float
    tickspersecond: float
    channels: list

Usage examples:

import pyassimp

scene = pyassimp.load("animated_model.dae")

if scene.animations:
    for i, animation in enumerate(scene.animations):
        print(f"Animation {i}: {animation.name}")
        print(f"  Duration: {animation.duration}")
        print(f"  Ticks per second: {animation.tickspersecond}")
        print(f"  Channels: {len(animation.channels)}")
        
        # Process animation channels
        for channel in animation.channels:
            print(f"    Channel node: {channel.nodename if hasattr(channel, 'nodename') else 'unknown'}")

pyassimp.release(scene)

Camera Data

3D camera definitions with projection parameters.

class Camera:
    """
    3D camera definition.
    
    Attributes:
    - name: str, camera name
    - position: Vector3D, camera position
    - lookat: Vector3D, look-at target direction
    - up: Vector3D, up vector
    - horizontalfov: float, horizontal field of view
    - aspect: float, aspect ratio
    - clipplanenear: float, near clipping plane
    - clipplanefar: float, far clipping plane
    """
    name: str
    position: Vector3D
    lookat: Vector3D  
    up: Vector3D
    horizontalfov: float
    aspect: float
    clipplanenear: float
    clipplanefar: float

Usage examples:

import pyassimp

scene = pyassimp.load("scene_with_camera.dae")

if scene.cameras:
    for i, camera in enumerate(scene.cameras):
        print(f"Camera {i}: {camera.name}")
        if hasattr(camera, 'position'):
            pos = camera.position
            print(f"  Position: ({pos.x}, {pos.y}, {pos.z})")
        if hasattr(camera, 'horizontalfov'):
            print(f"  FOV: {camera.horizontalfov} radians")
        if hasattr(camera, 'aspect'):
            print(f"  Aspect ratio: {camera.aspect}")

pyassimp.release(scene)

Light Data

Scene lighting definitions.

class Light:
    """
    Light source definition.
    
    Attributes:
    - name: str, light name
    - type: int, light type (directional, point, spot, etc.)
    - position: Vector3D, light position
    - direction: Vector3D, light direction
    - colorambient: Color3D, ambient color
    - colordiffuse: Color3D, diffuse color  
    - colorspecular: Color3D, specular color
    - attenuation*: float, attenuation parameters
    - angle*: float, spotlight angle parameters
    """
    name: str
    type: int
    position: Vector3D
    direction: Vector3D
    colorambient: Color3D
    colordiffuse: Color3D
    colorspecular: Color3D

Usage examples:

import pyassimp

scene = pyassimp.load("lit_scene.dae")

if scene.lights:
    for i, light in enumerate(scene.lights):
        print(f"Light {i}: {light.name}")
        if hasattr(light, 'type'):
            print(f"  Type: {light.type}")
        if hasattr(light, 'colordiffuse'):
            color = light.colordiffuse
            print(f"  Diffuse color: ({color.r}, {color.g}, {color.b})")

pyassimp.release(scene)

Metadata

Key-value metadata storage for additional scene information.

class Metadata:
    """
    Key-value metadata container.
    
    Attributes:
    - keys: list, metadata key names
    - values: list, MetadataEntry objects with typed values
    """
    keys: list
    values: list

class MetadataEntry:
    """
    Individual metadata entry with type information.
    
    Attributes:
    - type: int, data type identifier
    - data: any, typed data value
    
    Type Constants:
    - AI_BOOL = 0, boolean value
    - AI_INT32 = 1, 32-bit integer
    - AI_UINT64 = 2, 64-bit unsigned integer
    - AI_FLOAT = 3, floating point number
    - AI_DOUBLE = 4, double precision float
    - AI_AISTRING = 5, string value
    - AI_AIVECTOR3D = 6, 3D vector
    """
    type: int
    data: any
    
    AI_BOOL = 0
    AI_INT32 = 1
    AI_UINT64 = 2
    AI_FLOAT = 3
    AI_DOUBLE = 4
    AI_AISTRING = 5
    AI_AIVECTOR3D = 6

Usage examples:

import pyassimp

scene = pyassimp.load("model_with_metadata.dae")

# Check for metadata on scene root
if hasattr(scene.rootnode, 'metadata') and scene.rootnode.metadata:
    metadata = scene.rootnode.metadata
    print(f"Metadata entries: {len(metadata.keys)}")
    
    for key, value_entry in zip(metadata.keys, metadata.values):
        print(f"  {key}: {value_entry.data} (type: {value_entry.type})")

pyassimp.release(scene)

Data Access Patterns

Efficient Vertex Processing

import pyassimp
import numpy as np

scene = pyassimp.load("model.obj")

for mesh in scene.meshes:
    # Direct access to vertex arrays
    vertices = mesh.vertices
    
    if isinstance(vertices, np.ndarray):
        # NumPy array - efficient operations
        centroid = np.mean(vertices, axis=0)
        bounds_min = np.min(vertices, axis=0)
        bounds_max = np.max(vertices, axis=0)
        print(f"Centroid: {centroid}")
        print(f"Bounds: {bounds_min} to {bounds_max}")
    else:
        # Python list - slower but compatible
        if vertices:
            centroid = [sum(v[i] for v in vertices)/len(vertices) for i in range(3)]
            print(f"Centroid: {centroid}")

pyassimp.release(scene)

Scene Statistics

import pyassimp

def analyze_scene(filename):
    scene = pyassimp.load(filename)
    
    stats = {
        'nodes': 0,
        'meshes': len(scene.meshes),
        'materials': len(scene.materials),
        'textures': len(scene.textures),
        'animations': len(scene.animations),
        'cameras': len(scene.cameras),
        'lights': len(scene.lights),
        'total_vertices': 0,
        'total_faces': 0
    }
    
    def count_nodes(node):
        stats['nodes'] += 1
        for child in node.children:
            count_nodes(child)
    
    count_nodes(scene.rootnode)
    
    for mesh in scene.meshes:
        stats['total_vertices'] += len(mesh.vertices) if mesh.vertices else 0
        stats['total_faces'] += len(mesh.faces) if mesh.faces else 0
    
    pyassimp.release(scene)
    return stats

# Usage
stats = analyze_scene("complex_model.dae")
for key, value in stats.items():
    print(f"{key}: {value}")

Memory Usage Optimization

import pyassimp

def load_geometry_only(filename):
    """Load only geometry data, skip animations, cameras, etc."""
    
    # Use component removal to skip unwanted data
    processing = (pyassimp.postprocess.aiProcess_Triangulate |
                 pyassimp.postprocess.aiProcess_RemoveComponent)
    
    # Note: RemoveComponent needs configuration via AI_CONFIG_PP_RVC_FLAGS
    # This is a simplified example
    scene = pyassimp.load(filename, processing=processing)
    
    # Extract only needed data
    geometry_data = []
    for mesh in scene.meshes:
        mesh_data = {
            'vertices': mesh.vertices,
            'faces': mesh.faces,
            'normals': getattr(mesh, 'normals', None),
            'material_idx': mesh.materialindex
        }
        geometry_data.append(mesh_data)
    
    pyassimp.release(scene)
    return geometry_data

Install with Tessl CLI

npx tessl i tessl/pypi-pyassimp

docs

index.md

materials.md

math-utilities.md

post-processing.md

scene-data.md

scene-loading.md

tile.json