or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmaterials.mdmath-utilities.mdpost-processing.mdscene-data.mdscene-loading.md

materials.mddocs/

0

# Materials and Textures

1

2

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.

3

4

## Capabilities

5

6

### Material Properties

7

8

Material property access through a specialized dictionary interface supporting semantic keys.

9

10

```python { .api }

11

class Material:

12

"""

13

Material definition with properties and textures.

14

15

Attributes:

16

- properties: PropertyGetter, material property dictionary with semantic access

17

"""

18

properties: PropertyGetter

19

20

class PropertyGetter(dict):

21

"""

22

Material property dictionary with semantic key support.

23

24

Supports both simple key access and semantic tuple keys (key, semantic_index).

25

Material properties are organized by property type and semantic meaning.

26

"""

27

def __getitem__(self, key):

28

"""

29

Access property by key or (key, semantic) tuple.

30

31

Parameters:

32

- key: str or tuple, property name or (name, semantic_index)

33

34

Returns:

35

Property value (type varies by property)

36

"""

37

38

def keys(self):

39

"""

40

Iterate over property keys.

41

42

Yields:

43

str: Property key names

44

"""

45

46

def items(self):

47

"""

48

Iterate over property key-value pairs.

49

50

Yields:

51

tuple: (key, value) pairs

52

"""

53

```

54

55

Usage examples:

56

57

```python

58

import pyassimp

59

60

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

61

62

for i, material in enumerate(scene.materials):

63

print(f"Material {i}:")

64

65

# Access all properties

66

for key, value in material.properties.items():

67

print(f" {key}: {value}")

68

69

# Access specific properties

70

properties = material.properties

71

72

# Common material properties

73

if 'diffuse' in properties:

74

diffuse_color = properties['diffuse']

75

print(f" Diffuse color: {diffuse_color}")

76

77

if 'specular' in properties:

78

specular_color = properties['specular']

79

print(f" Specular color: {specular_color}")

80

81

if 'shininess' in properties:

82

shininess = properties['shininess']

83

print(f" Shininess: {shininess}")

84

85

# Texture properties (using semantic indices)

86

try:

87

diffuse_texture = properties[('file', 1)] # Diffuse texture

88

print(f" Diffuse texture: {diffuse_texture}")

89

except KeyError:

90

pass

91

92

try:

93

normal_texture = properties[('file', 2)] # Normal map

94

print(f" Normal texture: {normal_texture}")

95

except KeyError:

96

pass

97

98

pyassimp.release(scene)

99

```

100

101

### Texture Data

102

103

Embedded texture data and texture information.

104

105

```python { .api }

106

class Texture:

107

"""

108

Embedded texture data.

109

110

Attributes:

111

- achformathint: str, format hint/extension (e.g., "jpg", "png")

112

- data: array, texture pixel data

113

- width: int, texture width in pixels

114

- height: int, texture height in pixels

115

"""

116

achformathint: str

117

data: array

118

width: int

119

height: int

120

```

121

122

Usage examples:

123

124

```python

125

import pyassimp

126

127

scene = pyassimp.load("model_with_embedded_textures.blend")

128

129

if scene.textures:

130

for i, texture in enumerate(scene.textures):

131

print(f"Embedded texture {i}:")

132

print(f" Format hint: {texture.achformathint}")

133

print(f" Dimensions: {texture.width}x{texture.height}")

134

print(f" Data size: {len(texture.data) if texture.data else 0}")

135

136

# Save embedded texture

137

if texture.data and texture.achformathint:

138

filename = f"texture_{i}.{texture.achformathint}"

139

# Note: texture.data contains pixel data that may need format conversion

140

print(f" Can be saved as: {filename}")

141

142

pyassimp.release(scene)

143

```

144

145

### Material Types and Properties

146

147

Common material property identification and texture type constants.

148

149

```python { .api }

150

# Texture type constants (from pyassimp.material)

151

aiTextureType_NONE = 0x0 # No texture

152

aiTextureType_DIFFUSE = 0x1 # Diffuse color texture

153

aiTextureType_SPECULAR = 0x2 # Specular color texture

154

aiTextureType_AMBIENT = 0x3 # Ambient color texture

155

aiTextureType_EMISSIVE = 0x4 # Emissive color texture

156

aiTextureType_HEIGHT = 0x5 # Height map

157

aiTextureType_NORMALS = 0x6 # Normal map

158

aiTextureType_SHININESS = 0x7 # Shininess map

159

aiTextureType_OPACITY = 0x8 # Opacity map

160

aiTextureType_DISPLACEMENT = 0x9 # Displacement map

161

aiTextureType_LIGHTMAP = 0xA # Light map

162

aiTextureType_REFLECTION = 0xB # Reflection map

163

aiTextureType_UNKNOWN = 0xC # Unknown texture type

164

```

165

166

Usage examples:

167

168

```python

169

import pyassimp

170

from pyassimp.material import *

171

172

def analyze_material_textures(material):

173

"""Analyze texture usage in a material."""

174

175

texture_types = {

176

'diffuse': aiTextureType_DIFFUSE,

177

'specular': aiTextureType_SPECULAR,

178

'normal': aiTextureType_NORMALS,

179

'height': aiTextureType_HEIGHT,

180

'opacity': aiTextureType_OPACITY,

181

'emissive': aiTextureType_EMISSIVE

182

}

183

184

found_textures = {}

185

186

for name, tex_type in texture_types.items():

187

try:

188

# Look for texture file property with semantic index

189

texture_path = material.properties[('file', tex_type)]

190

found_textures[name] = texture_path

191

except KeyError:

192

pass

193

194

return found_textures

195

196

# Usage

197

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

198

199

for i, material in enumerate(scene.materials):

200

print(f"Material {i} textures:")

201

textures = analyze_material_textures(material)

202

203

for tex_type, path in textures.items():

204

print(f" {tex_type}: {path}")

205

206

pyassimp.release(scene)

207

```

208

209

## Advanced Material Usage

210

211

### Material Property Extraction

212

213

```python

214

import pyassimp

215

216

def extract_material_info(material):

217

"""Extract common material properties."""

218

219

props = material.properties

220

material_info = {}

221

222

# Color properties

223

color_props = ['diffuse', 'specular', 'ambient', 'emissive']

224

for prop in color_props:

225

if prop in props:

226

material_info[prop + '_color'] = props[prop]

227

228

# Scalar properties

229

scalar_props = ['shininess', 'opacity', 'refracti']

230

for prop in scalar_props:

231

if prop in props:

232

material_info[prop] = props[prop]

233

234

# String properties

235

string_props = ['name']

236

for prop in string_props:

237

if prop in props:

238

material_info[prop] = props[prop]

239

240

# Texture paths

241

texture_semantics = {

242

'diffuse_map': 1,

243

'specular_map': 2,

244

'ambient_map': 3,

245

'emissive_map': 4,

246

'height_map': 5,

247

'normal_map': 6,

248

'shininess_map': 7,

249

'opacity_map': 8,

250

'displacement_map': 9,

251

'lightmap': 10,

252

'reflection_map': 11

253

}

254

255

for map_name, semantic in texture_semantics.items():

256

try:

257

texture_path = props[('file', semantic)]

258

material_info[map_name] = texture_path

259

except KeyError:

260

pass

261

262

return material_info

263

264

# Usage

265

scene = pyassimp.load("pbr_model.gltf")

266

267

for i, material in enumerate(scene.materials):

268

info = extract_material_info(material)

269

print(f"Material {i}:")

270

for key, value in info.items():

271

print(f" {key}: {value}")

272

273

pyassimp.release(scene)

274

```

275

276

### Material-Mesh Mapping

277

278

```python

279

import pyassimp

280

281

def create_material_mesh_mapping(scene):

282

"""Create mapping between materials and meshes that use them."""

283

284

material_usage = {}

285

286

for mat_idx in range(len(scene.materials)):

287

material_usage[mat_idx] = {

288

'material': scene.materials[mat_idx],

289

'meshes': []

290

}

291

292

for mesh_idx, mesh in enumerate(scene.meshes):

293

mat_idx = mesh.materialindex

294

if mat_idx < len(scene.materials):

295

material_usage[mat_idx]['meshes'].append({

296

'index': mesh_idx,

297

'mesh': mesh,

298

'vertex_count': len(mesh.vertices) if mesh.vertices else 0,

299

'face_count': len(mesh.faces) if mesh.faces else 0

300

})

301

302

return material_usage

303

304

# Usage

305

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

306

307

mapping = create_material_mesh_mapping(scene)

308

309

for mat_idx, info in mapping.items():

310

material = info['material']

311

meshes = info['meshes']

312

313

print(f"Material {mat_idx}: {len(meshes)} meshes")

314

315

# Show material properties

316

if 'diffuse' in material.properties:

317

print(f" Diffuse: {material.properties['diffuse']}")

318

319

# Show mesh usage

320

total_vertices = sum(mesh['vertex_count'] for mesh in meshes)

321

total_faces = sum(mesh['face_count'] for mesh in meshes)

322

print(f" Total vertices: {total_vertices}")

323

print(f" Total faces: {total_faces}")

324

325

pyassimp.release(scene)

326

```

327

328

### PBR Material Detection

329

330

```python

331

import pyassimp

332

333

def detect_pbr_workflow(material):

334

"""Detect if material uses PBR workflow and which type."""

335

336

props = material.properties

337

338

# Look for PBR-specific properties

339

pbr_indicators = {

340

'metallic_roughness': ['metallic', 'roughness'],

341

'specular_glossiness': ['specular', 'glossiness'],

342

'base_color': ['base_color', 'basecolor']

343

}

344

345

workflow = None

346

properties_found = {}

347

348

for workflow_name, prop_names in pbr_indicators.items():

349

found_props = []

350

for prop in prop_names:

351

if prop in props:

352

found_props.append(prop)

353

properties_found[prop] = props[prop]

354

355

if found_props:

356

workflow = workflow_name

357

break

358

359

# Look for PBR texture maps

360

pbr_textures = {}

361

pbr_texture_semantics = {

362

'basecolor_map': ('file', 1),

363

'metallic_map': ('file', 12), # Assuming extended semantics

364

'roughness_map': ('file', 13),

365

'normal_map': ('file', 6),

366

'occlusion_map': ('file', 14),

367

'emissive_map': ('file', 4)

368

}

369

370

for tex_name, (key, semantic) in pbr_texture_semantics.items():

371

try:

372

texture_path = props[(key, semantic)]

373

pbr_textures[tex_name] = texture_path

374

except KeyError:

375

continue

376

377

return {

378

'workflow': workflow,

379

'properties': properties_found,

380

'textures': pbr_textures

381

}

382

383

# Usage

384

scene = pyassimp.load("pbr_model.gltf")

385

386

for i, material in enumerate(scene.materials):

387

pbr_info = detect_pbr_workflow(material)

388

389

print(f"Material {i}:")

390

print(f" PBR workflow: {pbr_info['workflow']}")

391

print(f" Properties: {pbr_info['properties']}")

392

print(f" Textures: {pbr_info['textures']}")

393

394

pyassimp.release(scene)

395

```

396

397

### Texture Path Resolution

398

399

```python

400

import pyassimp

401

import os

402

403

def resolve_texture_paths(scene, model_directory):

404

"""Resolve relative texture paths to absolute paths."""

405

406

resolved_textures = {}

407

408

for mat_idx, material in enumerate(scene.materials):

409

material_textures = {}

410

411

# Get all texture properties

412

for key, value in material.properties.items():

413

if isinstance(key, tuple) and key[0] == 'file':

414

texture_path = value

415

416

# Resolve relative paths

417

if not os.path.isabs(texture_path):

418

resolved_path = os.path.join(model_directory, texture_path)

419

resolved_path = os.path.normpath(resolved_path)

420

else:

421

resolved_path = texture_path

422

423

# Check if file exists

424

exists = os.path.exists(resolved_path)

425

426

material_textures[key[1]] = {

427

'original_path': texture_path,

428

'resolved_path': resolved_path,

429

'exists': exists

430

}

431

432

if material_textures:

433

resolved_textures[mat_idx] = material_textures

434

435

return resolved_textures

436

437

# Usage

438

model_path = "models/house/house.obj"

439

model_dir = os.path.dirname(model_path)

440

441

scene = pyassimp.load(model_path)

442

texture_info = resolve_texture_paths(scene, model_dir)

443

444

for mat_idx, textures in texture_info.items():

445

print(f"Material {mat_idx} textures:")

446

for semantic, info in textures.items():

447

status = "✓" if info['exists'] else "✗"

448

print(f" Semantic {semantic}: {info['original_path']} → {info['resolved_path']} {status}")

449

450

pyassimp.release(scene)

451

```

452

453

## Material Property Reference

454

455

Common material properties you might encounter:

456

457

### Color Properties

458

- `diffuse`: Diffuse color (RGB or RGBA)

459

- `specular`: Specular color

460

- `ambient`: Ambient color

461

- `emissive`: Emissive/self-illumination color

462

- `transparent`: Transparency color

463

464

### Scalar Properties

465

- `shininess`: Specular shininess/power

466

- `opacity`: Material opacity (1.0 = opaque, 0.0 = transparent)

467

- `refracti`: Refractive index

468

- `reflectivity`: Reflectivity factor

469

470

### String Properties

471

- `name`: Material name

472

- `shadingm`: Shading model identifier

473

474

### Texture Properties (by semantic index)

475

- Semantic 1: Diffuse texture

476

- Semantic 2: Specular texture

477

- Semantic 3: Ambient texture

478

- Semantic 4: Emissive texture

479

- Semantic 5: Height map

480

- Semantic 6: Normal map

481

- Semantic 7: Shininess map

482

- Semantic 8: Opacity map

483

- Semantic 9: Displacement map

484

- Semantic 10: Light map

485

- Semantic 11: Reflection map

486

487

## Performance Considerations

488

489

1. **Property Access**: Use direct key lookup rather than iteration when possible

490

2. **Memory Usage**: Material properties are loaded into memory; large property sets increase RAM usage

491

3. **Texture Loading**: Embedded textures are loaded into memory; external textures are referenced by path

492

4. **Property Iteration**: Iterating over all properties can be slow for materials with many properties

493

5. **Semantic Indices**: Using semantic indices is more reliable than key names across different file formats