|
@@ -0,0 +1,587 @@
|
|
|
+/**
|
|
|
+ * @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;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 "FloatNode":
|
|
|
+
|
|
|
+ object.number = node.number;
|
|
|
+
|
|
|
+ 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 "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":
|
|
|
+
|
|
|
+ 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.value.fromArray( node.elements );
|
|
|
+
|
|
|
+ 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.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 "ScreenNode":
|
|
|
+
|
|
|
+ if ( node.value ) object.value = this.getNode( node.value );
|
|
|
+
|
|
|
+ object.coord = this.getNode( node.coord );
|
|
|
+ object.project = node.project;
|
|
|
+
|
|
|
+ if ( node.bias ) object.bias = this.getNode( node.bias );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "CubeTextureNode":
|
|
|
+
|
|
|
+ object.value = this.getNode( node.value );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "LightNode":
|
|
|
+ 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;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+} );
|