PageSourceSearch

https://torqit.com.au/wp-content/plugins/woo-3d-viewer/includes/ext/threejs/js/loaders/MTLLoader.js?ver=1.8.7

js torqit.com.au collected 2026-09-24 13:09:41 UTC 11,522 bytes, 584 lines download raw bytes

1/**
2 * Loads a Wavefront .mtl file specifying materials
3 *
4 * @author angelxuanchang
5 */
6
7THREEW.MTLLoader = function ( manager ) {
8
9	this.manager = ( manager !== undefined ) ? manager : THREEW.DefaultLoadingManager;
10
11};
12
13THREEW.MTLLoader.prototype = {
14
15	constructor: THREEW.MTLLoader,
16
17	/**
18	 * Loads and parses a MTL asset from a URL.
19	 *
20	 * @param {String} url - URL to the MTL file.
21	 * @param {Function} [onLoad] - Callback invoked with the loaded object.
22	 * @param {Function} [onProgress] - Callback for download progress.
23	 * @param {Function} [onError] - Callback for download errors.
24	 *
25	 * @see setPath setResourcePath
26	 *
27	 * @note In order for relative texture references to resolve correctly
28	 * you must call setResourcePath() explicitly prior to load.
29	 */
30	load: function ( url, onLoad, onProgress, onError ) {
31
32		var scope = this;
33
34		var path = ( this.path === undefined ) ? THREEW.LoaderUtils.extractUrlBase( url ) : this.path;
35
36		var loader = new THREEW.FileLoader( this.manager );
37		loader.setPath( this.path );
38		loader.load( url, function ( text ) {
39
40			onLoad( scope.parse( text, path ) );
41
42		}, onProgress, onError );
43
44	},
45
46	/**
47	 * Set base path for resolving references.
48	 * If set this path will be prepended to each loaded and found reference.
49	 *
50	 * @see setResourcePath
51	 * @param {String} path
52	 * @return {THREEW.MTLLoader}
53	 *
54	 * @example
55	 *     mtlLoader.setPath( 'assets/obj/' );
56	 *     mtlLoader.load( 'my.mtl', ... );
57	 */
58	setPath: function ( path ) {
59
60		this.path = path;
61		return this;
62
63	},
64
65	/**
66	 * Set base path for additional resources like textures.
67	 *
68	 * @see setPath
69	 * @param {String} path
70	 * @return {THREEW.MTLLoader}
71	 *
72	 * @example
73	 *     mtlLoader.setPath( 'assets/obj/' );
74	 *     mtlLoader.setResourcePath( 'assets/textures/' );
75	 *     mtlLoader.load( 'my.mtl', ... );
76	 */
77	setResourcePath: function ( path ) {
78
79		this.resourcePath = path;
80		return this;
81
82	},
83
84	setTexturePath: function ( path ) {
85
86		console.warn( 'THREEW.MTLLoader: .setTexturePath() has been renamed to .setResourcePath().' );
87		return this.setResourcePath( path );
88
89	},
90
91	setCrossOrigin: function ( value ) {
92
93		this.crossOrigin = value;
94		return this;
95
96	},
97
98	setMaterialOptions: function ( value ) {
99
100		this.materialOptions = value;
101		return this;
102
103	},
104
105	/**
106	 * Parses a MTL file.
107	 *
108	 * @param {String} text - Content of MTL file
109	 * @return {THREEW.MTLLoader.MaterialCreator}
110	 *
111	 * @see setPath setResourcePath
112	 *
113	 * @note In order for relative texture references to resolve correctly
114	 * you must call setResourcePath() explicitly prior to parse.
115	 */
116	parse: function ( text, path ) {
117
118		var lines = text.split( '\n' );
119		var info = {};
120		var delimiter_pattern = /\s+/;
121		var materialsInfo = {};
122
123		for ( var i = 0; i < lines.length; i ++ ) {
124
125			var line = lines[ i ];
126			line = line.trim();
127
128			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
129
130				// Blank line or comment ignore
131				continue;
132
133			}
134
135			var pos = line.indexOf( ' ' );
136
137			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
138			key = key.toLowerCase();
139
140			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
141			value = value.trim();
142
143			if ( key === 'newmtl' ) {
144
145				// New material
146
147				info = { name: value };
148				materialsInfo[ value ] = info;
149
150			} else {
151
152				if ( key === 'ka' || key === 'kd' || key === 'ks' || key ==='ke' ) {
153
154					var ss = value.split( delimiter_pattern, 3 );
155					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
156
157				} else {
158
159					info[ key ] = value;
160
161				}
162
163			}
164
165		}
166
167		var materialCreator = new THREEW.MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions );
168		materialCreator.setCrossOrigin( this.crossOrigin );
169		materialCreator.setManager( this.manager );
170		materialCreator.setMaterials( materialsInfo );
171
172		return materialCreator;
173
174	}
175
176};
177
178/**
179 * Create a new THREE-MTLLoader.MaterialCreator
180 * @param baseUrl - Url relative to which textures are loaded
181 * @param options - Set of options on how to construct the materials
182 *                  side: Which side to apply the material
183 *                        THREEW.FrontSide (default), THREEW.BackSide, THREEW.DoubleSide
184 *                  wrap: What type of wrapping to apply for textures
185 *                        THREEW.RepeatWrapping (default), THREEW.ClampToEdgeWrapping, THREEW.MirroredRepeatWrapping
186 *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
187 *                                Default: false, assumed to be already normalized
188 *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
189 *                                  Default: false
190 * @constructor
191 */
192
193THREEW.MTLLoader.MaterialCreator = function ( baseUrl, options ) {
194
195	this.baseUrl = baseUrl || '';
196	this.options = options;
197	this.materialsInfo = {};
198	this.materials = {};
199	this.materialsArray = [];
200	this.nameLookup = {};
201
202	this.side = ( this.options && this.options.side ) ? this.options.side : THREEW.FrontSide;
203	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREEW.RepeatWrapping;
204
205};
206
207THREEW.MTLLoader.MaterialCreator.prototype = {
208
209	constructor: THREEW.MTLLoader.MaterialCreator,
210
211	crossOrigin: 'anonymous',
212
213	setCrossOrigin: function ( value ) {
214
215		this.crossOrigin = value;
216		return this;
217
218	},
219
220	setManager: function ( value ) {
221
222		this.manager = value;
223
224	},
225
226	setMaterials: function ( materialsInfo ) {
227
228		this.materialsInfo = this.convert( materialsInfo );
229		this.materials = {};
230		this.materialsArray = [];
231		this.nameLookup = {};
232
233	},
234
235	convert: function ( materialsInfo ) {
236
237		if ( ! this.options ) return materialsInfo;
238
239		var converted = {};
240
241		for ( var mn in materialsInfo ) {
242
243			// Convert materials info into normalized form based on options
244
245			var mat = materialsInfo[ mn ];
246
247			var covmat = {};
248
249			converted[ mn ] = covmat;
250
251			for ( var prop in mat ) {
252
253				var save = true;
254				var value = mat[ prop ];
255				var lprop = prop.toLowerCase();
256
257				switch ( lprop ) {
258
259					case 'kd':
260					case 'ka':
261					case 'ks':
262
263						// Diffuse color (color under white light) using RGB values
264
265						if ( this.options && this.options.normalizeRGB ) {
266
267							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];
268
269						}
270
271						if ( this.options && this.options.ignoreZeroRGBs ) {
272
273							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {
274
275								// ignore
276
277								save = false;
278
279							}
280
281						}
282
283						break;
284
285					default:
286
287						break;
288
289				}
290
291				if ( save ) {
292
293					covmat[ lprop ] = value;
294
295				}
296
297			}
298
299		}
300
301		return converted;
302
303	},
304
305	preload: function () {
306
307		for ( var mn in this.materialsInfo ) {
308
309			this.create( mn );
310
311		}
312
313	},
314
315	getIndex: function ( materialName ) {
316
317		return this.nameLookup[ materialName ];
318
319	},
320
321	getAsArray: function () {
322
323		var index = 0;
324
325		for ( var mn in this.materialsInfo ) {
326
327			this.materialsArray[ index ] = this.create( mn );
328			this.nameLookup[ mn ] = index;
329			index ++;
330
331		}
332
333		return this.materialsArray;
334
335	},
336
337	create: function ( materialName ) {
338
339		if ( this.materials[ materialName ] === undefined ) {
340
341			this.createMaterial_( materialName );
342
343		}
344
345		return this.materials[ materialName ];
346
347	},
348
349	createMaterial_: function ( materialName ) {
350
351		// Create material
352
353		var scope = this;
354		var mat = this.materialsInfo[ materialName ];
355		var params = {
356
357			name: materialName,
358			side: this.side
359
360		};
361
362		function resolveURL( baseUrl, url ) {
363
364			if ( typeof url !== 'string' || url === '' )
365				return '';
366
367			// Absolute URL
368			if ( /^https?:\/\//i.test( url ) ) return url;
369
370			return baseUrl + url;
371
372		}
373
374		function setMapForType( mapType, value ) {
375
376			if ( params[ mapType ] ) return; // Keep the first encountered texture
377
378			var texParams = scope.getTextureParams( value, params );
379			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
380
381			map.repeat.copy( texParams.scale );
382			map.offset.copy( texParams.offset );
383
384			map.wrapS = scope.wrap;
385			map.wrapT = scope.wrap;
386
387			params[ mapType ] = map;
388
389		}
390
391		for ( var prop in mat ) {
392
393			var value = mat[ prop ];
394			var n;
395
396			if ( value === '' ) continue;
397
398			switch ( prop.toLowerCase() ) {
399
400				// Ns is material specular exponent
401
402				case 'kd':
403
404					// Diffuse color (color under white light) using RGB values
405
406					params.color = new THREEW.Color().fromArray( value );
407
408					break;
409
410				case 'ks':
411
412					// Specular color (color when light is reflected from shiny surface) using RGB values
413					params.specular = new THREEW.Color().fromArray( value );
414
415					break;
416
417				case 'ke':
418
419					// Emissive using RGB values
420					params.emissive = new THREEW.Color().fromArray( value );
421
422					break;
423
424				case 'map_kd':
425
426					// Diffuse texture map
427
428					setMapForType( "map", value );
429
430					break;
431
432				case 'map_ks':
433
434					// Specular map
435
436					setMapForType( "specularMap", value );
437
438					break;
439
440				case 'map_ke':
441
442					// Emissive map
443
444					setMapForType( "emissiveMap", value );
445
446					break;
447
448				case 'norm':
449
450					setMapForType( "normalMap", value );
451
452					break;
453
454				case 'map_bump':
455				case 'bump':
456
457					// Bump texture map
458
459					setMapForType( "bumpMap", value );
460
461					break;
462
463				case 'map_d':
464
465					// Alpha map
466
467					setMapForType( "alphaMap", value );
468					params.transparent = true;
469
470					break;
471
472				case 'ns':
473
474					// The specular exponent (defines the focus of the specular highlight)
475					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
476
477					params.shininess = parseFloat( value );
478
479					break;
480
481				case 'd':
482					n = parseFloat( value );
483
484					if ( n < 1 ) {
485
486						params.opacity = n;
487						params.transparent = true;
488
489					}
490
491					break;
492
493				case 'tr':
494					n = parseFloat( value );
495
496					if ( this.options && this.options.invertTrProperty ) n = 1 - n;
497
498					if ( n > 0 ) {
499
500						params.opacity = 1 - n;
501						params.transparent = true;
502
503					}
504
505					break;
506
507				default:
508					break;
509
510			}
511
512		}
513		params.precision='mediump';
514		this.materials[ materialName ] = new THREEW.MeshPhongMaterial( params );
515		return this.materials[ materialName ];
516
517	},
518
519	getTextureParams: function ( value, matParams ) {
520
521		var texParams = {
522
523			scale: new THREEW.Vector2( 1, 1 ),
524			offset: new THREEW.Vector2( 0, 0 )
525
526		 };
527
528		var items = value.split( /\s+/ );
529		var pos;
530
531		pos = items.indexOf( '-bm' );
532
533		if ( pos >= 0 ) {
534
535			matParams.bumpScale = parseFloat( items[ pos + 1 ] );
536			items.splice( pos, 2 );
537
538		}
539
540		pos = items.indexOf( '-s' );
541
542		if ( pos >= 0 ) {
543
544			texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
545			items.splice( pos, 4 ); // we expect 3 parameters here!
546
547		}
548
549		pos = items.indexOf( '-o' );
550
551		if ( pos >= 0 ) {
552
553			texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
554			items.splice( pos, 4 ); // we expect 3 parameters here!
555
556		}
557
558		texParams.url = items.join( ' ' ).trim();
559		return texParams;
560
561	},
562
563	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
564
565		var texture;
566		var loader = THREEW.Loader.Handlers.get( url );
567		var manager = ( this.manager !== undefined ) ? this.manager : THREEW.DefaultLoadingManager;
568
569		if ( loader === null ) {
570
571			loader = new THREEW.TextureLoader( manager );
572
573		}
574
575		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
576		texture = loader.load( url, onLoad, onProgress, onError );
577
578		if ( mapping !== undefined ) texture.mapping = mapping;
579
580		return texture;
581
582	}
583
584};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.