0
# Materials and Textures
1
2
Material properties, texture management, and vertex data organization. Materials contain interleaved vertex arrays formatted for direct use with OpenGL rendering pipelines.
3
4
## Capabilities
5
6
### Material Objects
7
8
Materials store both visual properties and vertex geometry data in a format optimized for modern rendering.
9
10
```python { .api }
11
class Material:
12
def __init__(
13
self,
14
name: str,
15
is_default: bool = False,
16
has_faces: bool = False
17
):
18
"""
19
Create a new material object.
20
21
Parameters:
22
- name: Material name as defined in .mtl file
23
- is_default: Whether this is an auto-generated default material
24
- has_faces: Whether to collect face topology data
25
26
Attributes:
27
- name: str - Material name
28
- vertex_format: str - Vertex data format (e.g., "T2F_N3F_V3F")
29
- vertices: List[float] - Interleaved vertex data array
30
- diffuse: List[float] - Diffuse color [r, g, b, a] (0.0-1.0)
31
- ambient: List[float] - Ambient color [r, g, b, a] (0.0-1.0)
32
- specular: List[float] - Specular color [r, g, b, a] (0.0-1.0)
33
- emissive: List[float] - Emissive color [r, g, b, a] (0.0-1.0)
34
- transparency: float - Transparency value (0.0=opaque, 1.0=transparent)
35
- shininess: float - Specular shininess factor
36
- optical_density: float - Optical density for refraction
37
- illumination_model: int - Illumination model (0-10)
38
- texture: Texture - Diffuse texture map
39
- texture_ambient: Texture - Ambient texture map
40
- texture_specular_color: Texture - Specular color texture
41
- texture_specular_highlight: Texture - Specular highlight texture
42
- texture_alpha: Texture - Alpha/transparency texture
43
- texture_bump: Texture - Bump/normal map texture
44
"""
45
46
@property
47
def has_normals(self) -> bool:
48
"""Check if vertex data contains normal vectors."""
49
50
@property
51
def has_uvs(self) -> bool:
52
"""Check if vertex data contains texture coordinates."""
53
54
@property
55
def has_colors(self) -> bool:
56
"""Check if vertex data contains vertex colors."""
57
58
@property
59
def vertex_size(self) -> int:
60
"""Calculate how many float values each vertex contains in the interleaved data."""
61
62
def pad_light(self, values: List[float]) -> List[float]:
63
"""
64
Accept an array of up to 4 values, and return an array of 4 values.
65
Pads with zeroes to length 4 if input is shorter.
66
"""
67
68
def set_alpha(self, alpha: float) -> None:
69
"""Set alpha/transparency value on all four lighting attributes."""
70
71
def set_diffuse(self, values: List[float] = None) -> None:
72
"""Set diffuse color with automatic padding to 4 values."""
73
74
def set_ambient(self, values: List[float] = None) -> None:
75
"""Set ambient color with automatic padding to 4 values."""
76
77
def set_specular(self, values: List[float] = None) -> None:
78
"""Set specular color with automatic padding to 4 values."""
79
80
def set_emissive(self, values: List[float] = None) -> None:
81
"""Set emissive color with automatic padding to 4 values."""
82
83
def set_texture(self, name: str, search_path: str) -> None:
84
"""Set diffuse texture map."""
85
86
def set_texture_ambient(self, name: str, search_path: str) -> None:
87
"""Set ambient texture map."""
88
89
def set_texture_specular_color(self, name: str, search_path: str) -> None:
90
"""Set specular color texture map."""
91
92
def set_texture_specular_highlight(self, name: str, search_path: str) -> None:
93
"""Set specular highlight texture map."""
94
95
def set_texture_alpha(self, name: str, search_path: str) -> None:
96
"""Set alpha/transparency texture map."""
97
98
def set_texture_bump(self, name: str, search_path: str) -> None:
99
"""Set bump/normal map texture."""
100
101
def unset_texture(self) -> None:
102
"""Remove the diffuse texture reference."""
103
```
104
105
### Vertex Data Formats
106
107
Materials organize vertex data in interleaved arrays optimized for GPU rendering:
108
109
**Supported Vertex Formats:**
110
- `V3F` - Positions only (x, y, z)
111
- `T2F_V3F` - Texture coordinates + positions (u, v, x, y, z)
112
- `N3F_V3F` - Normals + positions (nx, ny, nz, x, y, z)
113
- `T2F_N3F_V3F` - Texture coords + normals + positions (u, v, nx, ny, nz, x, y, z)
114
- `C3F_V3F` - Vertex colors + positions (r, g, b, x, y, z)
115
- `T2F_C3F_V3F` - Texture coords + colors + positions (u, v, r, g, b, x, y, z)
116
117
The vertex format string describes the exact layout of the interleaved vertex array, allowing direct use with OpenGL vertex buffer objects (VBOs).
118
119
### Material Properties
120
121
Materials support the full range of Wavefront material properties:
122
123
**Color Properties:**
124
- Diffuse color (`Kd`) - Base surface color
125
- Ambient color (`Ka`) - Ambient lighting response
126
- Specular color (`Ks`) - Specular highlight color
127
- Emissive color (`Ke`) - Self-illumination color
128
129
**Surface Properties:**
130
- Transparency (`d` or `Tr`) - Surface transparency (0.0-1.0)
131
- Shininess (`Ns`) - Specular exponent for highlights
132
- Optical density (`Ni`) - Index of refraction for transparent materials
133
- Illumination model (`illum`) - Lighting calculation method (0-10)
134
135
**Illumination Models:**
136
- 0: Color on, Ambient off
137
- 1: Color on, Ambient on
138
- 2: Highlight on
139
- 3: Reflection on, Ray trace on
140
- 4: Transparency: Glass on, Reflection: Ray trace on
141
- 5: Reflection: Fresnel on, Ray trace on
142
- 6: Transparency: Refraction on, Reflection: Fresnel off, Ray trace on
143
- 7: Transparency: Refraction on, Reflection: Fresnel on, Ray trace on
144
- 8: Reflection on, Ray trace off
145
- 9: Transparency: Glass on, Reflection: Ray trace off
146
- 10: Casts shadows onto invisible surfaces
147
148
### Texture Management
149
150
```python { .api }
151
class Texture:
152
def __init__(self, name: str, search_path: str):
153
"""
154
Create a texture.
155
156
Parameters:
157
- name: Texture name possibly with path and options as it appears in the material
158
- search_path: Absolute or relative path where the texture might be located
159
160
Attributes:
161
- path: str - File path to texture image
162
- options: TextureOptions - Texture loading and sampling options
163
- image: Any - Used externally by visualization module
164
"""
165
166
@property
167
def name(self) -> str:
168
"""The texture path as it appears in the material."""
169
170
@name.setter
171
def name(self, value: str) -> None:
172
"""Set the texture name."""
173
174
@property
175
def options(self) -> 'TextureOptions':
176
"""Options for this texture."""
177
178
@property
179
def file_name(self) -> str:
180
"""
181
Obtain the file name of the texture.
182
Handles Windows/relative paths and extracts just the filename.
183
"""
184
185
@property
186
def path(self) -> str:
187
"""Full path: search_path + name."""
188
189
@path.setter
190
def path(self, value: str) -> None:
191
"""Set the texture path."""
192
193
@property
194
def image_name(self) -> str:
195
"""Legacy property name for texture path as it appears in material."""
196
197
@image_name.setter
198
def image_name(self, value: str) -> None:
199
"""Legacy setter for texture name."""
200
201
def find(self, path: str = None) -> str:
202
"""
203
Find the texture in the configured search path.
204
Searches recursively in subdirectories if texture not found at direct path.
205
206
Parameters:
207
- path: Override the search path
208
209
Returns:
210
- str: Full path to found texture file
211
212
Raises:
213
- FileNotFoundError: If texture cannot be located
214
"""
215
216
def exists(self) -> bool:
217
"""Check if the texture file exists at the configured path."""
218
219
class TextureOptions:
220
def __init__(self):
221
"""
222
Container for texture loading options and parameters with default values.
223
224
Attributes:
225
- name: str - Texture name (default: "default")
226
- blendu: str - U-direction blending ("on"/"off", default: "on")
227
- blendv: str - V-direction blending ("on"/"off", default: "on")
228
- bm: float - Bump multiplier for bump maps (default: 1.0)
229
- boost: float - Boost factor for mip-mapping (default: 0.0)
230
- cc: str - Color correction ("on"/"off", default: "off")
231
- clamp: str - Clamping mode ("on"/"off", default: "off")
232
- imfchan: str - Channel for scalar/bump textures (default: "l")
233
- mm: Tuple[float, float] - Range modification (base, gain, default: (0.0, 1.0))
234
- o: Tuple[float, float, float] - Origin offset (u, v, w, default: (0.0, 0.0, 0.0))
235
- s: Tuple[float, float, float] - Scale factors (u, v, w, default: (1.0, 1.0, 1.0))
236
- t: Tuple[float, float, float] - Turbulence factors (u, v, w, default: (0.0, 0.0, 0.0))
237
- texres: str - Texture resolution specification
238
"""
239
```
240
241
**Texture Types:**
242
- `map_Kd` - Diffuse color texture (most common)
243
- `map_Ka` - Ambient color texture
244
- `map_Ks` - Specular color texture
245
- `map_Ns` - Specular highlight texture
246
- `map_d` - Alpha/transparency texture
247
- `map_bump` or `bump` - Bump/normal map texture
248
249
### Material Parser
250
251
```python { .api }
252
class MaterialParser:
253
"""
254
Parser for .mtl material library files.
255
Automatically invoked when processing mtllib statements in .obj files.
256
"""
257
```
258
259
The MaterialParser handles:
260
- Material property parsing from .mtl files
261
- Texture path resolution and loading
262
- Color and numeric value conversion
263
- Material validation and error handling
264
265
### Usage Examples
266
267
```python
268
# Access material properties
269
for name, material in scene.materials.items():
270
print(f"Material: {name}")
271
print(f"Diffuse color: {material.diffuse}")
272
print(f"Has texture: {material.texture is not None}")
273
print(f"Transparency: {material.transparency}")
274
print(f"Illumination model: {material.illumination_model}")
275
276
# Check vertex data format and content
277
material = scene.materials['wood_material']
278
print(f"Vertex format: {material.vertex_format}")
279
print(f"Has normals: {material.has_normals}")
280
print(f"Has UVs: {material.has_uvs}")
281
print(f"Has colors: {material.has_colors}")
282
print(f"Vertex count: {len(material.vertices)}")
283
284
# Access interleaved vertex data for rendering
285
if material.vertex_format == "T2F_N3F_V3F":
286
# Data layout: [u, v, nx, ny, nz, x, y, z, u, v, nx, ny, nz, x, y, z, ...]
287
vertices = material.vertices
288
vertex_size = material.vertex_size # Automatically calculated: 8 floats per vertex
289
290
for i in range(0, len(vertices), vertex_size):
291
u, v = vertices[i], vertices[i+1] # Texture coordinates
292
nx, ny, nz = vertices[i+2], vertices[i+3], vertices[i+4] # Normal
293
x, y, z = vertices[i+5], vertices[i+6], vertices[i+7] # Position
294
295
# Material property modification
296
material.diffuse = [1.0, 0.5, 0.2, 1.0] # Set orange diffuse color
297
material.shininess = 128.0 # Increase shininess
298
material.transparency = 0.8 # Make semi-transparent
299
300
# Working with textures
301
if material.texture:
302
print(f"Diffuse texture: {material.texture.path}")
303
print(f"Texture exists: {material.texture.exists()}")
304
print(f"Texture filename: {material.texture.file_name}")
305
306
if material.texture_bump:
307
print(f"Bump map: {material.texture_bump.path}")
308
309
# Material property setters with validation
310
material.set_diffuse([0.8, 0.2, 0.1]) # Will be padded to [0.8, 0.2, 0.1, 0.0]
311
material.set_ambient([0.1, 0.1, 0.1, 1.0]) # Full RGBA specification
312
material.set_alpha(0.75) # Sets alpha on all lighting properties
313
314
# Texture management
315
material.set_texture("wood_diffuse.jpg", "/path/to/textures")
316
material.set_texture_bump("wood_normal.jpg", "/path/to/textures")
317
318
# Calculate vertex size dynamically
319
vertex_size = material.vertex_size
320
triangles_count = len(material.vertices) // vertex_size // 3
321
print(f"Material has {triangles_count} triangles")
322
323
# Working with texture options
324
if material.texture:
325
options = material.texture.options
326
print(f"Texture clamp mode: {options.clamp}")
327
print(f"Bump multiplier: {options.bm}")
328
329
# Find texture file in search paths
330
try:
331
texture_path = material.texture.find()
332
print(f"Found texture at: {texture_path}")
333
except FileNotFoundError:
334
print("Texture file not found in search paths")
335
```