/** * @author sunag / http://www.sunag.com.br/ */ THREE.NodeMaterialLoader = function ( manager, library ) { this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; this.nodes = {}; this.materials = {}; this.passes = {}; this.names = {}; this.library = library || {}; }; THREE.NodeMaterialLoaderUtils = { replaceUUIDObject: function ( object, uuid, value, recursive ) { recursive = recursive !== undefined ? recursive : true; if ( typeof uuid === "object" ) uuid = uuid.uuid; if ( typeof object === "object" ) { var keys = Object.keys( object ); for ( var i = 0; i < keys.length; i ++ ) { var key = keys[ i ]; if ( recursive ) { object[ key ] = this.replaceUUIDObject( object[ key ], uuid, value ); } if ( key === uuid ) { object[ uuid ] = object[ key ]; delete object[ key ]; } } } return object === uuid ? value : object; }, replaceUUID: function ( json, uuid, value ) { this.replaceUUIDObject( json, uuid, value, false ); this.replaceUUIDObject( json.nodes, uuid, value ); this.replaceUUIDObject( json.materials, uuid, value ); this.replaceUUIDObject( json.passes, uuid, value ); this.replaceUUIDObject( json.library, uuid, value, false ); return json; } }; Object.assign( THREE.NodeMaterialLoader.prototype, { load: function ( url, onLoad, onProgress, onError ) { var scope = this; var loader = new THREE.FileLoader( scope.manager ); loader.load( url, function ( text ) { onLoad( scope.parse( JSON.parse( text ) ) ); }, onProgress, onError ); return this; }, getObjectByName: function ( uuid ) { return this.names[ uuid ]; }, getObjectById: function ( uuid ) { return this.library[ uuid ] || this.nodes[ uuid ] || this.names[ uuid ]; }, getNode: function ( uuid ) { var object = this.getObjectById( uuid ); if ( ! object ) { console.warn( "Node \"" + uuid + "\" not found." ); } return object; }, parse: function ( json ) { var uuid, node, object, prop, i; for ( uuid in json.nodes ) { node = json.nodes[ uuid ]; object = new THREE[ node.type ](); if ( node.name ) { object.name = node.name; this.names[ object.name ] = object; } else { // ignore "uniform" shader input ( for optimization ) object.readonly = true; } if ( node.readonly !== undefined ) object.readonly = node.readonly; this.nodes[ uuid ] = object; } for ( uuid in json.materials ) { node = json.materials[ uuid ]; object = new THREE[ node.type ](); if ( node.name ) { object.name = node.name; this.names[ object.name ] = object; } this.materials[ uuid ] = object; } for ( uuid in json.passes ) { node = json.passes[ uuid ]; object = new THREE[ node.type ](); if ( node.name ) { object.name = node.name; this.names[ object.name ] = object; } this.passes[ uuid ] = object; } if ( json.material ) this.material = this.materials[ uuid ]; if ( json.pass ) this.pass = this.passes[ uuid ]; for ( uuid in json.nodes ) { node = json.nodes[ uuid ]; object = this.nodes[ uuid ]; switch ( node.type ) { case "IntNode": case "FloatNode": object.value = node.value; break; case "ColorNode": object.value.copy( node ); break; case "Vector2Node": object.x = node.x; object.y = node.y; break; case "Vector3Node": object.x = node.x; object.y = node.y; object.z = node.z; break; case "Vector4Node": object.x = node.x; object.y = node.y; object.z = node.z; object.w = node.w; break; case "Matrix3Node": case "Matrix4Node": object.value.fromArray( node.elements ); break; case "OperatorNode": object.a = this.getNode( node.a ); object.b = this.getNode( node.b ); object.op = node.op; break; case "Math1Node": object.a = this.getNode( node.a ); object.method = node.method; break; case "Math2Node": object.a = this.getNode( node.a ); object.b = this.getNode( node.b ); object.method = node.method; break; case "Math3Node": object.a = this.getNode( node.a ); object.b = this.getNode( node.b ); object.c = this.getNode( node.c ); object.method = node.method; break; case "UVNode": case "ColorsNode": object.index = node.index; break; case "LuminanceNode": object.rgb = this.getNode( node.rgb ); break; case "PositionNode": case "NormalNode": case "ReflectNode": case "LightNode": object.scope = node.scope; break; case "SwitchNode": object.node = this.getNode( node.node ); object.components = node.components; break; case "JoinNode": for ( prop in node.inputs ) { object[ prop ] = this.getNode( node.inputs[ prop ] ); } break; case "CameraNode": object.setScope( node.scope ); if ( node.camera ) object.setCamera( this.getNode( node.camera ) ); switch ( node.scope ) { case THREE.CameraNode.DEPTH: object.near.number = node.near; object.far.number = node.far; break; } break; case "ColorAdjustmentNode": object.rgb = this.getNode( node.rgb ); object.adjustment = this.getNode( node.adjustment ); object.method = node.method; break; case "UVTransformNode": object.uv = this.getNode( node.uv ); object.transform = this.getNode( node.transform ); break; case "BumpNode": object.value = this.getNode( node.value ); object.coord = this.getNode( node.coord ); object.scale = this.getNode( node.scale ); break; case "BlurNode": object.value = this.getNode( node.value ); object.coord = this.getNode( node.coord ); object.scale = this.getNode( node.scale ); object.value = this.getNode( node.value ); object.coord = this.getNode( node.coord ); object.radius = this.getNode( node.radius ); if ( node.size !== undefined ) object.size = new THREE.Vector2( node.size.x, node.size.y ); object.blurX = node.blurX; object.blurY = node.blurY; break; case "ResolutionNode": object.renderer = this.getNode( node.renderer ); break; case "ScreenUVNode": object.resolution = this.getNode( node.resolution ); break; case "VelocityNode": if ( node.target ) object.setTarget( this.getNode( node.target ) ); object.setParams( node.params ); break; case "TimerNode": object.scope = node.scope; object.scale = node.scale; break; case "ConstNode": object.name = node.name; object.type = node.out; object.value = node.value; object.useDefine = node.useDefine === true; break; case "AttributeNode": case "VarNode": object.type = node.out; break; case "ReflectorNode": object.setMirror( this.getNode( node.mirror ) ); if ( node.offset ) object.offset = this.getNode( node.offset ); break; case "NoiseNode": object.coord = this.getNode( node.coord ); break; case "FunctionNode": object.isMethod = node.isMethod; object.useKeywords = node.useKeywords; object.extensions = node.extensions; object.keywords = {}; for ( prop in node.keywords ) { object.keywords[ prop ] = this.getNode( node.keywords[ prop ] ); } if ( node.includes ) { for ( i = 0; i < node.includes.length; i ++ ) { object.includes.push( this.getNode( node.includes[ i ] ) ); } } object.eval( node.src, object.includes, object.extensions, object.keywords ); if ( ! object.isMethod ) object.type = node.out; break; case "FunctionCallNode": for ( prop in node.inputs ) { object.inputs[ prop ] = this.getNode( node.inputs[ prop ] ); } object.value = this.getNode( node.value ); break; case "TextureNode": case "CubeTextureNode": case "ScreenNode": if ( node.value ) object.value = this.getNode( node.value ); object.coord = this.getNode( node.coord ); if ( node.bias ) object.bias = this.getNode( node.bias ); if ( object.project !== undefined ) object.project = node.project; break; case "RoughnessToBlinnExponentNode": break; case "RawNode": object.value = this.getNode( node.value ); break; case "StandardNode": case "PhongNode": case "SpriteNode": object.color = this.getNode( node.color ); if ( node.alpha ) object.alpha = this.getNode( node.alpha ); if ( node.specular ) object.specular = this.getNode( node.specular ); if ( node.shininess ) object.shininess = this.getNode( node.shininess ); if ( node.roughness ) object.roughness = this.getNode( node.roughness ); if ( node.metalness ) object.metalness = this.getNode( node.metalness ); if ( node.reflectivity ) object.reflectivity = this.getNode( node.reflectivity ); if ( node.clearCoat ) object.clearCoat = this.getNode( node.clearCoat ); if ( node.clearCoatRoughness ) object.clearCoatRoughness = this.getNode( node.clearCoatRoughness ); if ( node.normal ) object.normal = this.getNode( node.normal ); if ( node.normalScale ) object.normalScale = this.getNode( node.normalScale ); if ( node.emissive ) object.emissive = this.getNode( node.emissive ); if ( node.ambient ) object.ambient = this.getNode( node.ambient ); if ( node.shadow ) object.shadow = this.getNode( node.shadow ); if ( node.light ) object.light = this.getNode( node.light ); if ( node.ao ) object.ao = this.getNode( node.ao ); if ( node.environment ) object.environment = this.getNode( node.environment ); if ( node.environmentAlpha ) object.environmentAlpha = this.getNode( node.environmentAlpha ); if ( node.transform ) object.transform = this.getNode( node.transform ); if ( node.spherical === false ) object.spherical = false; break; default: console.warn( node.type, "not supported." ); } } for ( uuid in json.materials ) { node = json.materials[ uuid ]; object = this.materials[ uuid ]; if ( node.name !== undefined ) object.name = node.name; if ( node.blending !== undefined ) object.blending = node.blending; if ( node.flatShading !== undefined ) object.flatShading = node.flatShading; if ( node.side !== undefined ) object.side = node.side; object.depthFunc = node.depthFunc; object.depthTest = node.depthTest; object.depthWrite = node.depthWrite; if ( node.wireframe !== undefined ) object.wireframe = node.wireframe; if ( node.wireframeLinewidth !== undefined ) object.wireframeLinewidth = node.wireframeLinewidth; if ( node.wireframeLinecap !== undefined ) object.wireframeLinecap = node.wireframeLinecap; if ( node.wireframeLinejoin !== undefined ) object.wireframeLinejoin = node.wireframeLinejoin; if ( node.skinning !== undefined ) object.skinning = node.skinning; if ( node.morphTargets !== undefined ) object.morphTargets = node.morphTargets; if ( node.visible !== undefined ) object.visible = node.visible; if ( node.userData !== undefined ) object.userData = node.userData; object.vertex = this.getNode( node.vertex ); object.fragment = this.getNode( node.fragment ); if ( object.vertex === object.fragment ) { // replace main node object.node = object.vertex; } object.build(); if ( node.fog !== undefined ) object.fog = node.fog; if ( node.lights !== undefined ) object.lights = node.lights; if ( node.transparent !== undefined ) object.transparent = node.transparent; } for ( uuid in json.passes ) { node = json.passes[ uuid ]; object = this.passes[ uuid ]; object.value = this.getNode( node.value ); object.build(); } return this.material || this.pass || this; } } );