853 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			853 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
									FileLoader,
							 | 
						||
| 
								 | 
							
									Loader,
							 | 
						||
| 
								 | 
							
									TextureLoader,
							 | 
						||
| 
								 | 
							
									RepeatWrapping
							 | 
						||
| 
								 | 
							
								} from 'three';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
									MeshBasicNodeMaterial, MeshPhysicalNodeMaterial,
							 | 
						||
| 
								 | 
							
									float, bool, int, vec2, vec3, vec4, color, texture,
							 | 
						||
| 
								 | 
							
									positionLocal, positionWorld, uv, vertexColor,
							 | 
						||
| 
								 | 
							
									normalLocal, normalWorld, tangentLocal, tangentWorld,
							 | 
						||
| 
								 | 
							
									add, sub, mul, div, mod, abs, sign, floor, ceil, round, pow, sin, cos, tan,
							 | 
						||
| 
								 | 
							
									asin, acos, atan2, sqrt, exp, clamp, min, max, normalize, length, dot, cross, normalMap,
							 | 
						||
| 
								 | 
							
									remap, smoothstep, luminance, mx_rgbtohsv, mx_hsvtorgb,
							 | 
						||
| 
								 | 
							
									mix,
							 | 
						||
| 
								 | 
							
									mx_ramplr, mx_ramptb, mx_splitlr, mx_splittb,
							 | 
						||
| 
								 | 
							
									mx_fractal_noise_float, mx_noise_float, mx_cell_noise_float, mx_worley_noise_float,
							 | 
						||
| 
								 | 
							
									mx_transform_uv,
							 | 
						||
| 
								 | 
							
									mx_safepower, mx_contrast,
							 | 
						||
| 
								 | 
							
									mx_srgb_texture_to_lin_rec709,
							 | 
						||
| 
								 | 
							
									saturation
							 | 
						||
| 
								 | 
							
								} from '../nodes/Nodes.js';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const colorSpaceLib = {
							 | 
						||
| 
								 | 
							
									mx_srgb_texture_to_lin_rec709
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class MXElement {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( name, nodeFunc, params = null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.name = name;
							 | 
						||
| 
								 | 
							
										this.nodeFunc = nodeFunc;
							 | 
						||
| 
								 | 
							
										this.params = params;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Ref: https://github.com/mrdoob/three.js/issues/24674
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const mx_add = ( in1, in2 = float( 0 ) ) => add( in1, in2 );
							 | 
						||
| 
								 | 
							
								const mx_subtract = ( in1, in2 = float( 0 ) ) => sub( in1, in2 );
							 | 
						||
| 
								 | 
							
								const mx_multiply = ( in1, in2 = float( 1 ) ) => mul( in1, in2 );
							 | 
						||
| 
								 | 
							
								const mx_divide = ( in1, in2 = float( 1 ) ) => div( in1, in2 );
							 | 
						||
| 
								 | 
							
								const mx_modulo = ( in1, in2 = float( 1 ) ) => mod( in1, in2 );
							 | 
						||
| 
								 | 
							
								const mx_power = ( in1, in2 = float( 1 ) ) => pow( in1, in2 );
							 | 
						||
| 
								 | 
							
								const mx_atan2 = ( in1 = float( 0 ), in2 = float( 1 ) ) => atan2( in1, in2 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const MXElements = [
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// << Math >>
							 | 
						||
| 
								 | 
							
									new MXElement( 'add', mx_add, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'subtract', mx_subtract, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'multiply', mx_multiply, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'divide', mx_divide, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'modulo', mx_modulo, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'absval', abs, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'sign', sign, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'floor', floor, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'ceil', ceil, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'round', round, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'power', mx_power, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'sin', sin, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'cos', cos, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'tan', tan, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'asin', asin, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'acos', acos, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'atan2', mx_atan2, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'sqrt', sqrt, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'ln', ... ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'exp', exp, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'clamp', clamp, [ 'in', 'low', 'high' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'min', min, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'max', max, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'normalize', normalize, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'magnitude', length, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'dotproduct', dot, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'crossproduct', cross, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'transformpoint', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'transformvector', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'transformnormal', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'transformmatrix', ... ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'normalmap', normalMap, [ 'in', 'scale' ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'transpose', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'determinant', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'invertmatrix', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'rotate2d', rotateUV, [ 'in', radians( 'amount' )** ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'rotate3d', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'arrayappend', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'dot', ... ),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// << Adjustment >>
							 | 
						||
| 
								 | 
							
									new MXElement( 'remap', remap, [ 'in', 'inlow', 'inhigh', 'outlow', 'outhigh' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'smoothstep', smoothstep, [ 'in', 'low', 'high' ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'curveadjust', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'curvelookup', ... ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'luminance', luminance, [ 'in', 'lumacoeffs' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'rgbtohsv', mx_rgbtohsv, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'hsvtorgb', mx_hsvtorgb, [ 'in' ] ),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// << Mix >>
							 | 
						||
| 
								 | 
							
									new MXElement( 'mix', mix, [ 'bg', 'fg', 'mix' ] ),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// << Channel >>
							 | 
						||
| 
								 | 
							
									new MXElement( 'combine2', vec2, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'combine3', vec3, [ 'in1', 'in2', 'in3' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'combine4', vec4, [ 'in1', 'in2', 'in3', 'in4' ] ),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// << Procedural >>
							 | 
						||
| 
								 | 
							
									new MXElement( 'ramplr', mx_ramplr, [ 'valuel', 'valuer', 'texcoord' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'ramptb', mx_ramptb, [ 'valuet', 'valueb', 'texcoord' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'splitlr', mx_splitlr, [ 'valuel', 'valuer', 'texcoord' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'splittb', mx_splittb, [ 'valuet', 'valueb', 'texcoord' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'noise2d', mx_noise_float, [ 'texcoord', 'amplitude', 'pivot' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'noise3d', mx_noise_float, [ 'texcoord', 'amplitude', 'pivot' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'fractal3d', mx_fractal_noise_float, [ 'position', 'octaves', 'lacunarity', 'diminish', 'amplitude' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'cellnoise2d', mx_cell_noise_float, [ 'texcoord' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'cellnoise3d', mx_cell_noise_float, [ 'texcoord' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'worleynoise2d', mx_worley_noise_float, [ 'texcoord', 'jitter' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'worleynoise3d', mx_worley_noise_float, [ 'texcoord', 'jitter' ] ),
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// << Supplemental >>
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'tiledimage', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'triplanarprojection', triplanarTextures, [ 'filex', 'filey', 'filez' ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'ramp4', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'place2d', mx_place2d, [ 'texcoord', 'pivot', 'scale', 'rotate', 'offset' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'safepower', mx_safepower, [ 'in1', 'in2' ] ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'contrast', mx_contrast, [ 'in', 'amount', 'pivot' ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'hsvadjust', ... ),
							 | 
						||
| 
								 | 
							
									new MXElement( 'saturate', saturation, [ 'in', 'amount' ] ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'extract', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'separate2', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'separate3', ... ),
							 | 
						||
| 
								 | 
							
									//new MtlXElement( 'separate4', ... )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const MtlXLibrary = {};
							 | 
						||
| 
								 | 
							
								MXElements.forEach( element => MtlXLibrary[ element.name ] = element );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class MaterialXLoader extends Loader {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( manager ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										super( manager );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									load( url, onLoad, onProgress, onError ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const _onError = function ( e ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( onError ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												onError( e );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												console.error( e );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										new FileLoader( this.manager )
							 | 
						||
| 
								 | 
							
											.setPath( this.path )
							 | 
						||
| 
								 | 
							
											.load( url, async ( text ) => {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												try {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													onLoad( this.parse( text ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} catch ( e ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													_onError( e );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}, onProgress, _onError );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									parse( text ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return new MaterialX( this.manager, this.path ).parse( text );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class MaterialXNode {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( materialX, nodeXML, nodePath = '' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.materialX = materialX;
							 | 
						||
| 
								 | 
							
										this.nodeXML = nodeXML;
							 | 
						||
| 
								 | 
							
										this.nodePath = nodePath ? nodePath + '/' + this.name : this.name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.parent = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.node = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.children = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get element() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.nodeXML.nodeName;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get nodeGraph() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.getAttribute( 'nodegraph' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get nodeName() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.getAttribute( 'nodename' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get interfaceName() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.getAttribute( 'interfacename' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get output() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.getAttribute( 'output' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get name() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.getAttribute( 'name' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get type() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.getAttribute( 'type' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get value() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.getAttribute( 'value' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getNodeGraph() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let nodeX = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										while ( nodeX !== null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( nodeX.element === 'nodegraph' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											nodeX = nodeX.parent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return nodeX;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getRoot() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let nodeX = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										while ( nodeX.parent !== null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											nodeX = nodeX.parent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return nodeX;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get referencePath() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let referencePath = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( this.nodeGraph !== null && this.output !== null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											referencePath = this.nodeGraph + '/' + this.output;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else if ( this.nodeName !== null || this.interfaceName !== null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											referencePath = this.getNodeGraph().nodePath + '/' + ( this.nodeName || this.interfaceName );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return referencePath;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get hasReference() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.referencePath !== null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									get isConst() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.element === 'input' && this.value !== null && this.type !== 'filename';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getColorSpaceNode() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const csSource = this.getAttribute( 'colorspace' );
							 | 
						||
| 
								 | 
							
										const csTarget = this.getRoot().getAttribute( 'colorspace' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const nodeName = `mx_${ csSource }_to_${ csTarget }`;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return colorSpaceLib[ nodeName ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getTexture() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const filePrefix = this.getRecursiveAttribute( 'fileprefix' ) || '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let loader = this.materialX.textureLoader;
							 | 
						||
| 
								 | 
							
										const uri = filePrefix + this.value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( uri ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const handler = this.materialX.manager.getHandler( uri );
							 | 
						||
| 
								 | 
							
											if ( handler !== null ) loader = handler;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const texture = loader.load( uri );
							 | 
						||
| 
								 | 
							
										texture.wrapS = texture.wrapT = RepeatWrapping;
							 | 
						||
| 
								 | 
							
										texture.flipY = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return texture;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getClassFromType( type ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let nodeClass = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( type === 'integer' ) nodeClass = int;
							 | 
						||
| 
								 | 
							
										else if ( type === 'float' ) nodeClass = float;
							 | 
						||
| 
								 | 
							
										else if ( type === 'vector2' ) nodeClass = vec2;
							 | 
						||
| 
								 | 
							
										else if ( type === 'vector3' ) nodeClass = vec3;
							 | 
						||
| 
								 | 
							
										else if ( type === 'vector4' || type === 'color4' ) nodeClass = vec4;
							 | 
						||
| 
								 | 
							
										else if ( type === 'color3' ) nodeClass = color;
							 | 
						||
| 
								 | 
							
										else if ( type === 'boolean' ) nodeClass = bool;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return nodeClass;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getNode() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let node = this.node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( node !== null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const type = this.type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( this.isConst ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const nodeClass = this.getClassFromType( type );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											node = nodeClass( ...this.getVector() );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else if ( this.hasReference ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											node = this.materialX.getMaterialXNode( this.referencePath ).getNode();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const element = this.element;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( element === 'convert' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const nodeClass = this.getClassFromType( type );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												node = nodeClass( this.getNodeByName( 'in' ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'constant' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												node = this.getNodeByName( 'value' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'position' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const space = this.getAttribute( 'space' );
							 | 
						||
| 
								 | 
							
												node = space === 'world' ? positionWorld : positionLocal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'normal' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const space = this.getAttribute( 'space' );
							 | 
						||
| 
								 | 
							
												node = space === 'world' ? normalWorld : normalLocal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'tangent' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const space = this.getAttribute( 'space' );
							 | 
						||
| 
								 | 
							
												node = space === 'world' ? tangentWorld : tangentLocal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'texcoord' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const indexNode = this.getChildByName( 'index' );
							 | 
						||
| 
								 | 
							
												const index = indexNode ? parseInt( indexNode.value ) : 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												node = uv( index );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'geomcolor' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const indexNode = this.getChildByName( 'index' );
							 | 
						||
| 
								 | 
							
												const index = indexNode ? parseInt( indexNode.value ) : 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												node = vertexColor( index );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'tiledimage' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const file = this.getChildByName( 'file' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const textureFile = file.getTexture();
							 | 
						||
| 
								 | 
							
												const uvTiling = mx_transform_uv( ...this.getNodesByNames( [ 'uvtiling', 'uvoffset' ] ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												node = texture( textureFile, uvTiling );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const colorSpaceNode = file.getColorSpaceNode();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( colorSpaceNode ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													node = colorSpaceNode( node );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( element === 'image' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const file = this.getChildByName( 'file' );
							 | 
						||
| 
								 | 
							
												const uvNode = this.getNodeByName( 'texcoord' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const textureFile = file.getTexture();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												node = texture( textureFile, uvNode );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const colorSpaceNode = file.getColorSpaceNode();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( colorSpaceNode ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													node = colorSpaceNode( node );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											} else if ( MtlXLibrary[ element ] !== undefined ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const nodeElement = MtlXLibrary[ element ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												node = nodeElement.nodeFunc( ...this.getNodesByNames( ...nodeElement.params ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( node === null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											console.warn( `THREE.MaterialXLoader: Unexpected node ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											node = float( 0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const nodeToTypeClass = this.getClassFromType( type );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( nodeToTypeClass !== null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											node = nodeToTypeClass( node );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										node.name = this.name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.node = node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getChildByName( name ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const input of this.children ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( input.name === name ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return input;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getNodes() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const nodes = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const input of this.children ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const node = input.getNode();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											nodes[ node.name ] = node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return nodes;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getNodeByName( name ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const child = this.getChildByName( name );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return child ? child.getNode() : undefined;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getNodesByNames( ...names ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const nodes = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const name of names ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const node = this.getNodeByName( name );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( node ) nodes.push( node );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return nodes;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getValue() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.value.trim();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getVector() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const vector = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const val of this.getValue().split( /[,|\s]/ ) ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( val !== '' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												vector.push( Number( val.trim() ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return vector;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getAttribute( name ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.nodeXML.getAttribute( name );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getRecursiveAttribute( name ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let attribute = this.nodeXML.getAttribute( name );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( attribute === null && this.parent !== null ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											attribute = this.parent.getRecursiveAttribute( name );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return attribute;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									setStandardSurfaceToGltfPBR( material ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const inputs = this.getNodes();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let colorNode = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( inputs.base && inputs.base_color ) colorNode = mul( inputs.base, inputs.base_color );
							 | 
						||
| 
								 | 
							
										else if ( inputs.base ) colorNode = inputs.base;
							 | 
						||
| 
								 | 
							
										else if ( inputs.base_color ) colorNode = inputs.base_color;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let roughnessNode = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( inputs.specular_roughness ) roughnessNode = inputs.specular_roughness;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let metalnessNode = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( inputs.metalness ) metalnessNode = inputs.metalness;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let clearcoatNode = null;
							 | 
						||
| 
								 | 
							
										let clearcoatRoughnessNode = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( inputs.coat ) clearcoatNode = inputs.coat;
							 | 
						||
| 
								 | 
							
										if ( inputs.coat_roughness ) clearcoatRoughnessNode = inputs.coat_roughness;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( inputs.coat_color ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											colorNode = colorNode ? mul( colorNode, inputs.coat_color ) : colorNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let normalNode = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( inputs.normal ) normalNode = inputs.normal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let emissiveNode = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( inputs.emission ) emissiveNode = inputs.emission;
							 | 
						||
| 
								 | 
							
										if ( inputs.emissionColor ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											emissiveNode = emissiveNode ? mul( emissiveNode, inputs.emissionColor ) : emissiveNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										material.colorNode = colorNode || color( 0.8, 0.8, 0.8 );
							 | 
						||
| 
								 | 
							
										material.roughnessNode = roughnessNode || float( 0.2 );
							 | 
						||
| 
								 | 
							
										material.metalnessNode = metalnessNode || float( 0 );
							 | 
						||
| 
								 | 
							
										material.clearcoatNode = clearcoatNode || float( 0 );
							 | 
						||
| 
								 | 
							
										material.clearcoatRoughnessNode = clearcoatRoughnessNode || float( 0 );
							 | 
						||
| 
								 | 
							
										if ( normalNode ) material.normalNode = normalNode;
							 | 
						||
| 
								 | 
							
										if ( emissiveNode ) material.emissiveNode = emissiveNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*setGltfPBR( material ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const inputs = this.getNodes();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										console.log( inputs );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									setMaterial( material ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const element = this.element;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( element === 'gltf_pbr' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//this.setGltfPBR( material );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else if ( element === 'standard_surface' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											this.setStandardSurfaceToGltfPBR( material );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									toBasicMaterial() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const material = new MeshBasicNodeMaterial();
							 | 
						||
| 
								 | 
							
										material.name = this.name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const nodeX of this.children.toReversed() ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( nodeX.name === 'out' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												material.colorNode = nodeX.getNode();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return material;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									toPhysicalMaterial() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const material = new MeshPhysicalNodeMaterial();
							 | 
						||
| 
								 | 
							
										material.name = this.name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const nodeX of this.children ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const shaderProperties = this.materialX.getMaterialXNode( nodeX.nodeName );
							 | 
						||
| 
								 | 
							
											shaderProperties.setMaterial( material );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return material;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									toMaterials() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const materials = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let isUnlit = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const nodeX of this.children ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( nodeX.element === 'surfacematerial' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const material = nodeX.toPhysicalMaterial();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												materials[ material.name ] = material;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												isUnlit = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( isUnlit ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for ( const nodeX of this.children ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( nodeX.element === 'nodegraph' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													const material = nodeX.toBasicMaterial();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													materials[ material.name ] = material;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return materials;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									add( materialXNode ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										materialXNode.parent = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.children.push( materialXNode );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class MaterialX {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( manager, path ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.manager = manager;
							 | 
						||
| 
								 | 
							
										this.path = path;
							 | 
						||
| 
								 | 
							
										this.resourcePath = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.nodesXLib = new Map();
							 | 
						||
| 
								 | 
							
										//this.nodesXRefLib = new WeakMap();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.textureLoader = new TextureLoader( manager );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									addMaterialXNode( materialXNode ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.nodesXLib.set( materialXNode.nodePath, materialXNode );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*getMaterialXNodeFromXML( xmlNode ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return this.nodesXRefLib.get( xmlNode );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									getMaterialXNode( ...names ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return this.nodesXLib.get( names.join( '/' ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									parseNode( nodeXML, nodePath = '' ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const materialXNode = new MaterialXNode( this, nodeXML, nodePath );
							 | 
						||
| 
								 | 
							
										if ( materialXNode.nodePath ) this.addMaterialXNode( materialXNode );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for ( const childNodeXML of nodeXML.children ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const childMXNode = this.parseNode( childNodeXML, materialXNode.nodePath );
							 | 
						||
| 
								 | 
							
											materialXNode.add( childMXNode );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return materialXNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									parse( text ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const rootXML = new DOMParser().parseFromString( text, 'application/xml' ).documentElement;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.textureLoader.setPath( this.path );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const materials = this.parseNode( rootXML ).toMaterials();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return { materials };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export { MaterialXLoader };
							 |