/** * * Usage: * var loader = new THREE.ESDLoader(); * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) { * scene.add( new THREE.Mesh( geometry ) ); * }); * * For binary STLs geometry might contain colors for vertices. To use it: * // use the same code to load STL as above * if (geometry.hasColors) { * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true }); * } else { .... } * var mesh = new THREE.Mesh( geometry, material ); * * var mesh = new THREE.Mesh( geometry, material ); * * For example: * * var materials = []; * var nGeometryGroups = geometry.groups.length; * * var colorMap = ...; // Some logic to index colors. * * for (var i = 0; i < nGeometryGroups; i++) { * * var material = new THREE.MeshPhongMaterial({ * color: colorMap[i], * wireframe: false * }); * * } * * materials.push(material); * var mesh = new THREE.Mesh(geometry, materials); */ THREE.ESDLoader = function ( manager ) { THREE.Loader.call( this, manager ); }; THREE.ESDLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), { constructor: THREE.ESDLoader, load: function ( url, onLoad, onProgress, onError ) { var scope = this; var loader = new THREE.FileLoader( scope.manager ); var scope = this; var path = ( this.path === '' ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path; this.resourcePath = this.resourcePath || path; var loader = new THREE.FileLoader( scope.manager ); loader.setPath( this.path ); loader.load( url, function ( text ) { var json = null; try { json = JSON.parse( text ); } catch ( error ) { if ( onError !== undefined ) { onError( error ); } console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); return; } var metadata = json.metadata; if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); return; } scope.parse( json, onLoad ); }, onProgress, onError ); }, loadDATA: function (json,onLoad) { var scope = this; var metadata = json.metadata; if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { console.error( 'THREE.ObjectLoader: Can\'t load '); return; } scope.parse( json, onLoad ); }, parse: function ( json, onLoad ) { var shapes = this.parseShape( json.shapes ); var geometries = this.parseGeometries( json.geometries, shapes ); var images = this.parseImages( json.images, function () { if ( onLoad !== undefined ) { onLoad( object ); } } ); var textures = this.parseTextures( json.textures, images ); var materials = this.parseMaterials( json.materials, textures ); var object = this.parseObject( json.object, geometries, materials ); if ( onLoad !== undefined ) { onLoad( object ); } return object; }, parseShape: function ( json ) { var shapes = {}; if ( json !== undefined ) { for ( var i = 0, l = json.length; i < l; i ++ ) { var shape = new THREE.Shape().fromJSON( json[ i ] ); shapes[ shape.uuid ] = shape; } } return shapes; }, parseGeometries: function ( json, shapes ) { var geometries = {}; var geometryShapes; if ( json !== undefined ) { var bufferGeometryLoader = new THREE.BufferGeometryLoader(); for ( var i = 0, l = json.length; i < l; i ++ ) { var geometry = (void 0); var data = json[ i ]; switch ( data.type ) { case 'PlaneGeometry': case 'PlaneBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.width, data.height, data.widthSegments, data.heightSegments ); break; case 'BoxGeometry': case 'BoxBufferGeometry': case 'CubeGeometry': // backwards compatible geometry = new THREE.Geometries[ data.type ]( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); break; case 'CircleGeometry': case 'CircleBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.radius, data.segments, data.thetaStart, data.thetaLength ); break; case 'CylinderGeometry': case 'CylinderBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); break; case 'ConeGeometry': case 'ConeBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); break; case 'SphereGeometry': case 'SphereBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); break; case 'DodecahedronGeometry': case 'DodecahedronBufferGeometry': case 'IcosahedronGeometry': case 'IcosahedronBufferGeometry': case 'OctahedronGeometry': case 'OctahedronBufferGeometry': case 'TetrahedronGeometry': case 'TetrahedronBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.radius, data.detail ); break; case 'RingGeometry': case 'RingBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); break; case 'TorusGeometry': case 'TorusBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); break; case 'TorusKnotGeometry': case 'TorusKnotBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); break; case 'TubeGeometry': case 'TubeBufferGeometry': // This only works for built-in curves (e.g. CatmullRomCurve3). // User defined curves or instances of CurvePath will not be deserialized. geometry = new Geometries[ data.type ]( new Curves[ data.path.type ]().fromJSON( data.path ), data.tubularSegments, data.radius, data.radialSegments, data.closed ); break; case 'LatheGeometry': case 'LatheBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.points, data.segments, data.phiStart, data.phiLength ); break; case 'PolyhedronGeometry': case 'PolyhedronBufferGeometry': geometry = new THREE.Geometries[ data.type ]( data.vertices, data.indices, data.radius, data.details ); break; case 'ShapeGeometry': case 'ShapeBufferGeometry': geometryShapes = []; for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) { var shape = shapes[ data.shapes[ j ] ]; geometryShapes.push( shape ); } geometry = new THREE.Geometries[ data.type ]( geometryShapes, data.curveSegments ); break; case 'ExtrudeGeometry': case 'ExtrudeBufferGeometry': geometryShapes = []; for ( var j$1 = 0, jl$1 = data.shapes.length; j$1 < jl$1; j$1 ++ ) { var shape$1 = shapes[ data.shapes[ j$1 ] ]; geometryShapes.push( shape$1 ); } var extrudePath = data.options.extrudePath; if ( extrudePath !== undefined ) { data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath ); } geometry = new THREE.Geometries[ data.type ]( geometryShapes, data.options ); break; case 'BufferGeometry': case 'InstancedBufferGeometry': geometry = bufferGeometryLoader.parse( data ); break; case 'Geometry': console.error( 'THREE.ObjectLoader: Loading "Geometry" is not supported anymore.' ); break; default: console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' ); continue; } geometry.uuid = data.uuid; if ( data.name !== undefined ) { geometry.name = data.name; } if ( geometry.isBufferGeometry === true && data.userData !== undefined ) { geometry.userData = data.userData; } geometries[ data.uuid ] = geometry; } } return geometries; }, parseImages: function ( json, onLoad ) { var scope = this; var images = {}; var loader; function loadImage( url ) { scope.manager.itemStart( url ); return loader.load( url, function () { scope.manager.itemEnd( url ); }, undefined, function () { scope.manager.itemError( url ); scope.manager.itemEnd( url ); } ); } if ( json !== undefined && json.length > 0 ) { var manager = new THREE.LoadingManager( onLoad ); loader = new THREE.ImageLoader( manager ); loader.setCrossOrigin( this.crossOrigin ); for ( var i = 0, il = json.length; i < il; i ++ ) { var image = json[ i ]; var url = image.url; if ( Array.isArray( url ) ) { // load array of images e.g CubeTexture images[ image.uuid ] = []; for ( var j = 0, jl = url.length; j < jl; j ++ ) { var currentUrl = url[ j ]; var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl; images[ image.uuid ].push( loadImage( path ) ); } } else { // load single image var path$1 = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url; images[ image.uuid ] = loadImage( path$1 ); } } } return images; }, parseMaterials: function ( json, textures ) { var cache = {}; // MultiMaterial var materials = {}; if ( json !== undefined ) { var loader = new THREE.MaterialLoader(); loader.setTextures( textures ); for ( var i = 0, l = json.length; i < l; i ++ ) { var data = json[ i ]; if ( data.type === 'MultiMaterial' ) { // Deprecated var array = []; for ( var j = 0; j < data.materials.length; j ++ ) { var material = data.materials[ j ]; if ( cache[ material.uuid ] === undefined ) { cache[ material.uuid ] = loader.parse( material ); } array.push( cache[ material.uuid ] ); } materials[ data.uuid ] = array; } else { if ( cache[ data.uuid ] === undefined ) { cache[ data.uuid ] = loader.parse( data ); } materials[ data.uuid ] = cache[ data.uuid ]; } } } return materials; }, parseTextures: function ( json, images ) { function parseConstant( value, type ) { if ( typeof value === 'number' ) { return value; } console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); return type[ value ]; } var textures = {}; if ( json !== undefined ) { for ( var i = 0, l = json.length; i < l; i ++ ) { var data = json[ i ]; if ( data.image === undefined ) { console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); } if ( images[ data.image ] === undefined ) { console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); } var texture = (void 0); if ( Array.isArray( images[ data.image ] ) ) { texture = new THREE.CubeTexture( images[ data.image ] ); } else { texture = new THREE.Texture( images[ data.image ] ); } texture.needsUpdate = true; texture.uuid = data.uuid; if ( data.name !== undefined ) { texture.name = data.name; } if ( data.mapping !== undefined ) { texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); } if ( data.offset !== undefined ) { texture.offset.fromArray( data.offset ); } if ( data.repeat !== undefined ) { texture.repeat.fromArray( data.repeat ); } if ( data.center !== undefined ) { texture.center.fromArray( data.center ); } if ( data.rotation !== undefined ) { texture.rotation = data.rotation; } if ( data.wrap !== undefined ) { texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); } if ( data.format !== undefined ) { texture.format = data.format; } if ( data.type !== undefined ) { texture.type = data.type; } if ( data.encoding !== undefined ) { texture.encoding = data.encoding; } if ( data.minFilter !== undefined ) { texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); } if ( data.magFilter !== undefined ) { texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); } if ( data.anisotropy !== undefined ) { texture.anisotropy = data.anisotropy; } if ( data.flipY !== undefined ) { texture.flipY = data.flipY; } if ( data.premultiplyAlpha !== undefined ) { texture.premultiplyAlpha = data.premultiplyAlpha; } if ( data.unpackAlignment !== undefined ) { texture.unpackAlignment = data.unpackAlignment; } textures[ data.uuid ] = texture; } } return textures; }, parseObject: function ( data, geometries, materials ) { var object; function getGeometry( name ) { if ( geometries[ name ] === undefined ) { console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); } return geometries[ name ]; } function getMaterial( name ) { if ( name === undefined ) { return undefined; } if ( Array.isArray( name ) ) { var array = []; for ( var i = 0, l = name.length; i < l; i ++ ) { var uuid = name[ i ]; if ( materials[ uuid ] === undefined ) { console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); } array.push( materials[ uuid ] ); } return array; } if ( materials[ name ] === undefined ) { console.warn( 'THREE.ObjectLoader: Undefined material', name ); } return materials[ name ]; } var geometry, material; switch ( data.type ) { case 'Scene': object = new THREE.Scene(); if ( data.background !== undefined ) { if ( Number.isInteger( data.background ) ) { object.background = new THREE.Color( data.background ); } } if ( data.fog !== undefined ) { if ( data.fog.type === 'Fog' ) { object.fog = new THREE.Fog( data.fog.color, data.fog.near, data.fog.far ); } else if ( data.fog.type === 'FogExp2' ) { object.fog = new THREE.FogExp2( data.fog.color, data.fog.density ); } } break; case 'PerspectiveCamera': object = new THREE.PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); if ( data.focus !== undefined ) { object.focus = data.focus; } if ( data.zoom !== undefined ) { object.zoom = data.zoom; } if ( data.filmGauge !== undefined ) { object.filmGauge = data.filmGauge; } if ( data.filmOffset !== undefined ) { object.filmOffset = data.filmOffset; } if ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); } break; case 'OrthographicCamera': object = new THREE.OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); if ( data.zoom !== undefined ) { object.zoom = data.zoom; } if ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); } break; case 'AmbientLight': object = new THREE.AmbientLight( data.color, data.intensity ); break; case 'DirectionalLight': object = new THREE.DirectionalLight( data.color, data.intensity ); break; case 'PointLight': object = new THREE.PointLight( data.color, data.intensity, data.distance, data.decay ); break; case 'RectAreaLight': object = new THREE.RectAreaLight( data.color, data.intensity, data.width, data.height ); break; case 'SpotLight': object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); break; case 'HemisphereLight': object = new THREE.HemisphereLight( data.color, data.groundColor, data.intensity ); break; case 'LightProbe': object = new THREE.LightProbe().fromJSON( data ); break; case 'SkinnedMesh': console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' ); case 'Mesh': geometry = getGeometry( data.geometry ); material = getMaterial( data.material ); object = new THREE.Mesh( geometry, material ); break; case 'InstancedMesh': geometry = getGeometry( data.geometry ); material = getMaterial( data.material ); var count = data.count; var instanceMatrix = data.instanceMatrix; object = new THREE.InstancedMesh( geometry, material, count ); object.instanceMatrix = new THREE.BufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); break; case 'LOD': object = new THREE.LOD(); break; case 'Line': object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); break; case 'LineLoop': object = new THREE.LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); break; case 'LineSegments': object = new THREE.LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); break; case 'PointCloud': case 'Points': object = new THREE.Points( getGeometry( data.geometry ), getMaterial( data.material ) ); break; case 'Sprite': object = new THREE.Sprite( getMaterial( data.material ) ); break; case 'Group': object = new THREE.Group(); break; default: object = new THREE.Object3D(); } object.uuid = data.uuid; if ( data.name !== undefined ) { object.name = data.name; } if ( data.matrix !== undefined ) { object.matrix.fromArray( data.matrix ); if ( data.matrixAutoUpdate !== undefined ) { object.matrixAutoUpdate = data.matrixAutoUpdate; } if ( object.matrixAutoUpdate ) { object.matrix.decompose( object.position, object.quaternion, object.scale ); } } else { if ( data.position !== undefined ) { object.position.fromArray( data.position ); } if ( data.rotation !== undefined ) { object.rotation.fromArray( data.rotation ); } if ( data.quaternion !== undefined ) { object.quaternion.fromArray( data.quaternion ); } if ( data.scale !== undefined ) { object.scale.fromArray( data.scale ); } } if ( data.castShadow !== undefined ) { object.castShadow = data.castShadow; } if ( data.receiveShadow !== undefined ) { object.receiveShadow = data.receiveShadow; } if ( data.shadow ) { if ( data.shadow.bias !== undefined ) { object.shadow.bias = data.shadow.bias; } if ( data.shadow.normalBias !== undefined ) { object.shadow.normalBias = data.shadow.normalBias; } if ( data.shadow.radius !== undefined ) { object.shadow.radius = data.shadow.radius; } if ( data.shadow.mapSize !== undefined ) { object.shadow.mapSize.fromArray( data.shadow.mapSize ); } if ( data.shadow.camera !== undefined ) { object.shadow.camera = this.parseObject( data.shadow.camera ); } } if ( data.visible !== undefined ) { object.visible = data.visible; } if ( data.frustumCulled !== undefined ) { object.frustumCulled = data.frustumCulled; } if ( data.renderOrder !== undefined ) { object.renderOrder = data.renderOrder; } if ( data.userData !== undefined ) { object.userData = data.userData; } if ( data.layers !== undefined ) { object.layers.mask = data.layers; } if ( data.children !== undefined ) { var children = data.children; for ( var i = 0; i < children.length; i ++ ) { object.add( this.parseObject( children[ i ], geometries, materials ) ); } } if ( data.type === 'LOD' ) { if ( data.autoUpdate !== undefined ) { object.autoUpdate = data.autoUpdate; } var levels = data.levels; for ( var l = 0; l < levels.length; l ++ ) { var level = levels[ l ]; var child = object.getObjectByProperty( 'uuid', level.object ); if ( child !== undefined ) { object.addLevel( child, level.distance ); } } } return object; } } );