Python bindings for the Open Asset Import Library (ASSIMP) enabling 3D model loading, processing, and export
—
Material properties, texture management, and shader parameter access. PyAssimp provides comprehensive access to material systems including property queries, texture mapping, and material type identification with support for various shading models and material workflows.
Material property access through a specialized dictionary interface supporting semantic keys.
class Material:
"""
Material definition with properties and textures.
Attributes:
- properties: PropertyGetter, material property dictionary with semantic access
"""
properties: PropertyGetter
class PropertyGetter(dict):
"""
Material property dictionary with semantic key support.
Supports both simple key access and semantic tuple keys (key, semantic_index).
Material properties are organized by property type and semantic meaning.
"""
def __getitem__(self, key):
"""
Access property by key or (key, semantic) tuple.
Parameters:
- key: str or tuple, property name or (name, semantic_index)
Returns:
Property value (type varies by property)
"""
def keys(self):
"""
Iterate over property keys.
Yields:
str: Property key names
"""
def items(self):
"""
Iterate over property key-value pairs.
Yields:
tuple: (key, value) pairs
"""Usage examples:
import pyassimp
scene = pyassimp.load("textured_model.obj")
for i, material in enumerate(scene.materials):
print(f"Material {i}:")
# Access all properties
for key, value in material.properties.items():
print(f" {key}: {value}")
# Access specific properties
properties = material.properties
# Common material properties
if 'diffuse' in properties:
diffuse_color = properties['diffuse']
print(f" Diffuse color: {diffuse_color}")
if 'specular' in properties:
specular_color = properties['specular']
print(f" Specular color: {specular_color}")
if 'shininess' in properties:
shininess = properties['shininess']
print(f" Shininess: {shininess}")
# Texture properties (using semantic indices)
try:
diffuse_texture = properties[('file', 1)] # Diffuse texture
print(f" Diffuse texture: {diffuse_texture}")
except KeyError:
pass
try:
normal_texture = properties[('file', 2)] # Normal map
print(f" Normal texture: {normal_texture}")
except KeyError:
pass
pyassimp.release(scene)Embedded texture data and texture information.
class Texture:
"""
Embedded texture data.
Attributes:
- achformathint: str, format hint/extension (e.g., "jpg", "png")
- data: array, texture pixel data
- width: int, texture width in pixels
- height: int, texture height in pixels
"""
achformathint: str
data: array
width: int
height: intUsage examples:
import pyassimp
scene = pyassimp.load("model_with_embedded_textures.blend")
if scene.textures:
for i, texture in enumerate(scene.textures):
print(f"Embedded texture {i}:")
print(f" Format hint: {texture.achformathint}")
print(f" Dimensions: {texture.width}x{texture.height}")
print(f" Data size: {len(texture.data) if texture.data else 0}")
# Save embedded texture
if texture.data and texture.achformathint:
filename = f"texture_{i}.{texture.achformathint}"
# Note: texture.data contains pixel data that may need format conversion
print(f" Can be saved as: {filename}")
pyassimp.release(scene)Common material property identification and texture type constants.
# Texture type constants (from pyassimp.material)
aiTextureType_NONE = 0x0 # No texture
aiTextureType_DIFFUSE = 0x1 # Diffuse color texture
aiTextureType_SPECULAR = 0x2 # Specular color texture
aiTextureType_AMBIENT = 0x3 # Ambient color texture
aiTextureType_EMISSIVE = 0x4 # Emissive color texture
aiTextureType_HEIGHT = 0x5 # Height map
aiTextureType_NORMALS = 0x6 # Normal map
aiTextureType_SHININESS = 0x7 # Shininess map
aiTextureType_OPACITY = 0x8 # Opacity map
aiTextureType_DISPLACEMENT = 0x9 # Displacement map
aiTextureType_LIGHTMAP = 0xA # Light map
aiTextureType_REFLECTION = 0xB # Reflection map
aiTextureType_UNKNOWN = 0xC # Unknown texture typeUsage examples:
import pyassimp
from pyassimp.material import *
def analyze_material_textures(material):
"""Analyze texture usage in a material."""
texture_types = {
'diffuse': aiTextureType_DIFFUSE,
'specular': aiTextureType_SPECULAR,
'normal': aiTextureType_NORMALS,
'height': aiTextureType_HEIGHT,
'opacity': aiTextureType_OPACITY,
'emissive': aiTextureType_EMISSIVE
}
found_textures = {}
for name, tex_type in texture_types.items():
try:
# Look for texture file property with semantic index
texture_path = material.properties[('file', tex_type)]
found_textures[name] = texture_path
except KeyError:
pass
return found_textures
# Usage
scene = pyassimp.load("complex_material.dae")
for i, material in enumerate(scene.materials):
print(f"Material {i} textures:")
textures = analyze_material_textures(material)
for tex_type, path in textures.items():
print(f" {tex_type}: {path}")
pyassimp.release(scene)import pyassimp
def extract_material_info(material):
"""Extract common material properties."""
props = material.properties
material_info = {}
# Color properties
color_props = ['diffuse', 'specular', 'ambient', 'emissive']
for prop in color_props:
if prop in props:
material_info[prop + '_color'] = props[prop]
# Scalar properties
scalar_props = ['shininess', 'opacity', 'refracti']
for prop in scalar_props:
if prop in props:
material_info[prop] = props[prop]
# String properties
string_props = ['name']
for prop in string_props:
if prop in props:
material_info[prop] = props[prop]
# Texture paths
texture_semantics = {
'diffuse_map': 1,
'specular_map': 2,
'ambient_map': 3,
'emissive_map': 4,
'height_map': 5,
'normal_map': 6,
'shininess_map': 7,
'opacity_map': 8,
'displacement_map': 9,
'lightmap': 10,
'reflection_map': 11
}
for map_name, semantic in texture_semantics.items():
try:
texture_path = props[('file', semantic)]
material_info[map_name] = texture_path
except KeyError:
pass
return material_info
# Usage
scene = pyassimp.load("pbr_model.gltf")
for i, material in enumerate(scene.materials):
info = extract_material_info(material)
print(f"Material {i}:")
for key, value in info.items():
print(f" {key}: {value}")
pyassimp.release(scene)import pyassimp
def create_material_mesh_mapping(scene):
"""Create mapping between materials and meshes that use them."""
material_usage = {}
for mat_idx in range(len(scene.materials)):
material_usage[mat_idx] = {
'material': scene.materials[mat_idx],
'meshes': []
}
for mesh_idx, mesh in enumerate(scene.meshes):
mat_idx = mesh.materialindex
if mat_idx < len(scene.materials):
material_usage[mat_idx]['meshes'].append({
'index': mesh_idx,
'mesh': mesh,
'vertex_count': len(mesh.vertices) if mesh.vertices else 0,
'face_count': len(mesh.faces) if mesh.faces else 0
})
return material_usage
# Usage
scene = pyassimp.load("multi_material_model.obj")
mapping = create_material_mesh_mapping(scene)
for mat_idx, info in mapping.items():
material = info['material']
meshes = info['meshes']
print(f"Material {mat_idx}: {len(meshes)} meshes")
# Show material properties
if 'diffuse' in material.properties:
print(f" Diffuse: {material.properties['diffuse']}")
# Show mesh usage
total_vertices = sum(mesh['vertex_count'] for mesh in meshes)
total_faces = sum(mesh['face_count'] for mesh in meshes)
print(f" Total vertices: {total_vertices}")
print(f" Total faces: {total_faces}")
pyassimp.release(scene)import pyassimp
def detect_pbr_workflow(material):
"""Detect if material uses PBR workflow and which type."""
props = material.properties
# Look for PBR-specific properties
pbr_indicators = {
'metallic_roughness': ['metallic', 'roughness'],
'specular_glossiness': ['specular', 'glossiness'],
'base_color': ['base_color', 'basecolor']
}
workflow = None
properties_found = {}
for workflow_name, prop_names in pbr_indicators.items():
found_props = []
for prop in prop_names:
if prop in props:
found_props.append(prop)
properties_found[prop] = props[prop]
if found_props:
workflow = workflow_name
break
# Look for PBR texture maps
pbr_textures = {}
pbr_texture_semantics = {
'basecolor_map': ('file', 1),
'metallic_map': ('file', 12), # Assuming extended semantics
'roughness_map': ('file', 13),
'normal_map': ('file', 6),
'occlusion_map': ('file', 14),
'emissive_map': ('file', 4)
}
for tex_name, (key, semantic) in pbr_texture_semantics.items():
try:
texture_path = props[(key, semantic)]
pbr_textures[tex_name] = texture_path
except KeyError:
continue
return {
'workflow': workflow,
'properties': properties_found,
'textures': pbr_textures
}
# Usage
scene = pyassimp.load("pbr_model.gltf")
for i, material in enumerate(scene.materials):
pbr_info = detect_pbr_workflow(material)
print(f"Material {i}:")
print(f" PBR workflow: {pbr_info['workflow']}")
print(f" Properties: {pbr_info['properties']}")
print(f" Textures: {pbr_info['textures']}")
pyassimp.release(scene)import pyassimp
import os
def resolve_texture_paths(scene, model_directory):
"""Resolve relative texture paths to absolute paths."""
resolved_textures = {}
for mat_idx, material in enumerate(scene.materials):
material_textures = {}
# Get all texture properties
for key, value in material.properties.items():
if isinstance(key, tuple) and key[0] == 'file':
texture_path = value
# Resolve relative paths
if not os.path.isabs(texture_path):
resolved_path = os.path.join(model_directory, texture_path)
resolved_path = os.path.normpath(resolved_path)
else:
resolved_path = texture_path
# Check if file exists
exists = os.path.exists(resolved_path)
material_textures[key[1]] = {
'original_path': texture_path,
'resolved_path': resolved_path,
'exists': exists
}
if material_textures:
resolved_textures[mat_idx] = material_textures
return resolved_textures
# Usage
model_path = "models/house/house.obj"
model_dir = os.path.dirname(model_path)
scene = pyassimp.load(model_path)
texture_info = resolve_texture_paths(scene, model_dir)
for mat_idx, textures in texture_info.items():
print(f"Material {mat_idx} textures:")
for semantic, info in textures.items():
status = "✓" if info['exists'] else "✗"
print(f" Semantic {semantic}: {info['original_path']} → {info['resolved_path']} {status}")
pyassimp.release(scene)Common material properties you might encounter:
diffuse: Diffuse color (RGB or RGBA)specular: Specular colorambient: Ambient coloremissive: Emissive/self-illumination colortransparent: Transparency colorshininess: Specular shininess/poweropacity: Material opacity (1.0 = opaque, 0.0 = transparent)refracti: Refractive indexreflectivity: Reflectivity factorname: Material nameshadingm: Shading model identifierInstall with Tessl CLI
npx tessl i tessl/pypi-pyassimp