From bb043702ed4a1a921c9eb8b1bc3854516c3c412e Mon Sep 17 00:00:00 2001 From: Tariq Soliman Date: Thu, 27 Jan 2022 14:01:44 -0800 Subject: [PATCH] 1.2.0 (#18) * 1.0.5 * Fix tiles misaligning on maps w/ unusual bounds * Add case for default projection to invertY * Final (hopefully) changes to invertY * #2 Add Model Layer part 1 * #2 Add Model Layer part 2 - functional, no docs yet, zoom with keys * #2 Finish Model Layer, bearing, docs * #2 Model and bearing touchups * #2 Arrayed model layers and other touchups * Update Changelog v1.1.0 * Update changelog and readme * #15 Filters and Blend Modes (#17) * #15 Early Brightness, Contrast, Saturation * #15 setLayerFilterEffect * #15 Add color blend mode * #15 Touch ups and docs Co-authored-by: Cameron Fraser Co-authored-by: Cameron Fraser --- CHANGELOG.md | 18 + README.md | 4 +- dist/lithosphere.js | 80 ++++- dist/src/constants.d.ts | 1 + dist/src/controls/altitude.d.ts | 0 dist/src/controls/compass.d.ts | 15 + dist/src/controls/controls.d.ts | 0 dist/src/controls/coordinates.d.ts | 19 ++ dist/src/controls/crop.d.ts | 0 dist/src/controls/exaggerate.d.ts | 18 + dist/src/controls/home.d.ts | 13 + dist/src/controls/index.d.ts | 29 ++ dist/src/controls/layers.d.ts | 17 + dist/src/controls/link.d.ts | 29 ++ dist/src/controls/observe.d.ts | 23 ++ dist/src/controls/walk.d.ts | 16 + dist/src/core/events.d.ts | 1 + dist/src/core/renderer.d.ts | 8 + dist/src/core/shaders.d.ts | 7 + dist/src/core/tiledWorld.d.ts | 1 + dist/src/layers/curtain.d.ts | 0 dist/src/layers/index.d.ts | 5 + dist/src/layers/model.d.ts | 14 + dist/src/layers/overlay.d.ts | 0 dist/src/layers/tile.d.ts | 9 + dist/src/layers/vector.d.ts | 11 + dist/src/lithosphere.d.ts | 4 + dist/src/parsers/demt.d.ts | 0 dist/src/parsers/rgba.d.ts | 1 + dist/src/parsers/tif.d.ts | 1 + dist/src/secondary/OrbitControls.d.ts | 5 + dist/src/secondary/PNG/png.d.ts | 16 + dist/src/secondary/PNG/zlib.d.ts | 4 + dist/src/secondary/PointerLockControls.d.ts | 1 + dist/src/secondary/loadingScreen.d.ts | 7 + dist/src/secondary/sprites.d.ts | 8 + dist/src/utils/index.d.ts | 2 + docs/pages/Constructor/constructor.markdown | 44 +-- docs/pages/Functions/functions.markdown | 60 +++- docs/pages/Layers/Clamped/clamped.markdown | 12 +- docs/pages/Layers/Model/model.markdown | 53 +++ docs/pages/Layers/Tile/tile.markdown | 7 + docs/pages/Layers/layers.markdown | 2 + examples/example.html | 310 +++++++++++++---- examples/exampleProj.html | 2 +- package.json | 3 +- src/core/events.ts | 67 ++++ src/core/projection.ts | 12 +- src/core/shaders.ts | 160 +++++++-- src/core/tiledWorld.ts | 76 ++++- src/layers/clamped.ts | 74 +++- src/layers/index.ts | 67 +++- src/layers/model.ts | 353 ++++++++++++++++++++ src/layers/tile.ts | 19 ++ src/layers/tile3d.ts | 70 +++- src/lithosphere.ts | 17 +- src/utils/index.ts | 26 ++ 57 files changed, 1676 insertions(+), 145 deletions(-) create mode 100644 dist/src/constants.d.ts create mode 100644 dist/src/controls/altitude.d.ts create mode 100644 dist/src/controls/compass.d.ts create mode 100644 dist/src/controls/controls.d.ts create mode 100644 dist/src/controls/coordinates.d.ts create mode 100644 dist/src/controls/crop.d.ts create mode 100644 dist/src/controls/exaggerate.d.ts create mode 100644 dist/src/controls/home.d.ts create mode 100644 dist/src/controls/index.d.ts create mode 100644 dist/src/controls/layers.d.ts create mode 100644 dist/src/controls/link.d.ts create mode 100644 dist/src/controls/observe.d.ts create mode 100644 dist/src/controls/walk.d.ts create mode 100644 dist/src/core/renderer.d.ts create mode 100644 dist/src/core/shaders.d.ts create mode 100644 dist/src/layers/curtain.d.ts create mode 100644 dist/src/layers/model.d.ts create mode 100644 dist/src/layers/overlay.d.ts create mode 100644 dist/src/layers/tile.d.ts create mode 100644 dist/src/layers/vector.d.ts create mode 100644 dist/src/parsers/demt.d.ts create mode 100644 dist/src/parsers/rgba.d.ts create mode 100644 dist/src/parsers/tif.d.ts create mode 100644 dist/src/secondary/OrbitControls.d.ts create mode 100644 dist/src/secondary/PNG/png.d.ts create mode 100644 dist/src/secondary/PNG/zlib.d.ts create mode 100644 dist/src/secondary/PointerLockControls.d.ts create mode 100644 dist/src/secondary/loadingScreen.d.ts create mode 100644 dist/src/secondary/sprites.d.ts create mode 100644 docs/pages/Layers/Model/model.markdown diff --git a/CHANGELOG.md b/CHANGELOG.md index 05fba9e..4eca851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,3 +18,21 @@ LithoSphere's first release! ### Changed - PNG.js and zlib.js are now modules instead of globals + +## v1.0.3 + +#### Added + +- {constructor}.demFallback + +#### Fixed + +- {vector/clamped layer}.letPropertiesStyleOverride + +## v1.1.0 + +#### Added + +- Model layer type (.dae, .gltf, .obj) +- Bearings (directional arrows) for clamped vector points +- Keyboard navigation controls (wasd = pan, qe = rotate, rf = dolly, tg: zoom) diff --git a/README.md b/README.md index 4e041d8..1891769 100644 --- a/README.md +++ b/README.md @@ -38,13 +38,13 @@ Head over to the **[Documentation](https://nasa-ammos.github.io/LithoSphere/)** - Overlay (upcoming) - Tile - Tile3d - - Model (upcoming) + - Model - Adjustable planetary radii - Scripts for tiling Digital Elevation Maps (DEM) and custom projections - Various tile formats: - TMS - WMTS - - WMS (upcoming) + - WMS - Full Proj4 support to render tile sets of any projection - A suite of pluginable UI controls: - Compass diff --git a/dist/lithosphere.js b/dist/lithosphere.js index c63dd8d..6369224 100644 --- a/dist/lithosphere.js +++ b/dist/lithosphere.js @@ -1712,6 +1712,18 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /***/ }), +/***/ "./node_modules/three/examples/jsm/loaders/ColladaLoader.js": +/*!******************************************************************!*\ + !*** ./node_modules/three/examples/jsm/loaders/ColladaLoader.js ***! + \******************************************************************/ +/*! exports provided: ColladaLoader */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColladaLoader\", function() { return ColladaLoader; });\n/* harmony import */ var _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../build/three.module.js */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _loaders_TGALoader_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../loaders/TGALoader.js */ \"./node_modules/three/examples/jsm/loaders/TGALoader.js\");\n\n\n\nvar ColladaLoader = function ( manager ) {\n\n\t_build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].call( this, manager );\n\n};\n\nColladaLoader.prototype = Object.assign( Object.create( _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].prototype ), {\n\n\tconstructor: ColladaLoader,\n\n\tload: function ( url, onLoad, onProgress, onError ) {\n\n\t\tvar scope = this;\n\n\t\tvar path = ( scope.path === '' ) ? _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LoaderUtils\"].extractUrlBase( url ) : scope.path;\n\n\t\tvar loader = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"FileLoader\"]( scope.manager );\n\t\tloader.setPath( scope.path );\n\t\tloader.setRequestHeader( scope.requestHeader );\n\t\tloader.setWithCredentials( scope.withCredentials );\n\t\tloader.load( url, function ( text ) {\n\n\t\t\ttry {\n\n\t\t\t\tonLoad( scope.parse( text, path ) );\n\n\t\t\t} catch ( e ) {\n\n\t\t\t\tif ( onError ) {\n\n\t\t\t\t\tonError( e );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( e );\n\n\t\t\t\t}\n\n\t\t\t\tscope.manager.itemError( url );\n\n\t\t\t}\n\n\t\t}, onProgress, onError );\n\n\t},\n\n\toptions: {\n\n\t\tset convertUpAxis( value ) {\n\n\t\t\tconsole.warn( 'THREE.ColladaLoader: options.convertUpAxis() has been removed. Up axis is converted automatically.' );\n\n\t\t}\n\n\t},\n\n\tparse: function ( text, path ) {\n\n\t\tfunction getElementsByTagName( xml, name ) {\n\n\t\t\t// Non recursive xml.getElementsByTagName() ...\n\n\t\t\tvar array = [];\n\t\t\tvar childNodes = xml.childNodes;\n\n\t\t\tfor ( var i = 0, l = childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = childNodes[ i ];\n\n\t\t\t\tif ( child.nodeName === name ) {\n\n\t\t\t\t\tarray.push( child );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn array;\n\n\t\t}\n\n\t\tfunction parseStrings( text ) {\n\n\t\t\tif ( text.length === 0 ) return [];\n\n\t\t\tvar parts = text.trim().split( /\\s+/ );\n\t\t\tvar array = new Array( parts.length );\n\n\t\t\tfor ( var i = 0, l = parts.length; i < l; i ++ ) {\n\n\t\t\t\tarray[ i ] = parts[ i ];\n\n\t\t\t}\n\n\t\t\treturn array;\n\n\t\t}\n\n\t\tfunction parseFloats( text ) {\n\n\t\t\tif ( text.length === 0 ) return [];\n\n\t\t\tvar parts = text.trim().split( /\\s+/ );\n\t\t\tvar array = new Array( parts.length );\n\n\t\t\tfor ( var i = 0, l = parts.length; i < l; i ++ ) {\n\n\t\t\t\tarray[ i ] = parseFloat( parts[ i ] );\n\n\t\t\t}\n\n\t\t\treturn array;\n\n\t\t}\n\n\t\tfunction parseInts( text ) {\n\n\t\t\tif ( text.length === 0 ) return [];\n\n\t\t\tvar parts = text.trim().split( /\\s+/ );\n\t\t\tvar array = new Array( parts.length );\n\n\t\t\tfor ( var i = 0, l = parts.length; i < l; i ++ ) {\n\n\t\t\t\tarray[ i ] = parseInt( parts[ i ] );\n\n\t\t\t}\n\n\t\t\treturn array;\n\n\t\t}\n\n\t\tfunction parseId( text ) {\n\n\t\t\treturn text.substring( 1 );\n\n\t\t}\n\n\t\tfunction generateId() {\n\n\t\t\treturn 'three_default_' + ( count ++ );\n\n\t\t}\n\n\t\tfunction isEmpty( object ) {\n\n\t\t\treturn Object.keys( object ).length === 0;\n\n\t\t}\n\n\t\t// asset\n\n\t\tfunction parseAsset( xml ) {\n\n\t\t\treturn {\n\t\t\t\tunit: parseAssetUnit( getElementsByTagName( xml, 'unit' )[ 0 ] ),\n\t\t\t\tupAxis: parseAssetUpAxis( getElementsByTagName( xml, 'up_axis' )[ 0 ] )\n\t\t\t};\n\n\t\t}\n\n\t\tfunction parseAssetUnit( xml ) {\n\n\t\t\tif ( ( xml !== undefined ) && ( xml.hasAttribute( 'meter' ) === true ) ) {\n\n\t\t\t\treturn parseFloat( xml.getAttribute( 'meter' ) );\n\n\t\t\t} else {\n\n\t\t\t\treturn 1; // default 1 meter\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction parseAssetUpAxis( xml ) {\n\n\t\t\treturn xml !== undefined ? xml.textContent : 'Y_UP';\n\n\t\t}\n\n\t\t// library\n\n\t\tfunction parseLibrary( xml, libraryName, nodeName, parser ) {\n\n\t\t\tvar library = getElementsByTagName( xml, libraryName )[ 0 ];\n\n\t\t\tif ( library !== undefined ) {\n\n\t\t\t\tvar elements = getElementsByTagName( library, nodeName );\n\n\t\t\t\tfor ( var i = 0; i < elements.length; i ++ ) {\n\n\t\t\t\t\tparser( elements[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction buildLibrary( data, builder ) {\n\n\t\t\tfor ( var name in data ) {\n\n\t\t\t\tvar object = data[ name ];\n\t\t\t\tobject.build = builder( data[ name ] );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// get\n\n\t\tfunction getBuild( data, builder ) {\n\n\t\t\tif ( data.build !== undefined ) return data.build;\n\n\t\t\tdata.build = builder( data );\n\n\t\t\treturn data.build;\n\n\t\t}\n\n\t\t// animation\n\n\t\tfunction parseAnimation( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tsources: {},\n\t\t\t\tsamplers: {},\n\t\t\t\tchannels: {}\n\t\t\t};\n\n\t\t\tvar hasChildren = false;\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tvar id;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'source':\n\t\t\t\t\t\tid = child.getAttribute( 'id' );\n\t\t\t\t\t\tdata.sources[ id ] = parseSource( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'sampler':\n\t\t\t\t\t\tid = child.getAttribute( 'id' );\n\t\t\t\t\t\tdata.samplers[ id ] = parseAnimationSampler( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'channel':\n\t\t\t\t\t\tid = child.getAttribute( 'target' );\n\t\t\t\t\t\tdata.channels[ id ] = parseAnimationChannel( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'animation':\n\t\t\t\t\t\t// hierarchy of related animations\n\t\t\t\t\t\tparseAnimation( child );\n\t\t\t\t\t\thasChildren = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tconsole.log( child );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( hasChildren === false ) {\n\n\t\t\t\t// since 'id' attributes can be optional, it's necessary to generate a UUID for unqiue assignment\n\n\t\t\t\tlibrary.animations[ xml.getAttribute( 'id' ) || _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MathUtils\"].generateUUID() ] = data;\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction parseAnimationSampler( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tinputs: {},\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'input':\n\t\t\t\t\t\tvar id = parseId( child.getAttribute( 'source' ) );\n\t\t\t\t\t\tvar semantic = child.getAttribute( 'semantic' );\n\t\t\t\t\t\tdata.inputs[ semantic ] = id;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseAnimationChannel( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tvar target = xml.getAttribute( 'target' );\n\n\t\t\t// parsing SID Addressing Syntax\n\n\t\t\tvar parts = target.split( '/' );\n\n\t\t\tvar id = parts.shift();\n\t\t\tvar sid = parts.shift();\n\n\t\t\t// check selection syntax\n\n\t\t\tvar arraySyntax = ( sid.indexOf( '(' ) !== - 1 );\n\t\t\tvar memberSyntax = ( sid.indexOf( '.' ) !== - 1 );\n\n\t\t\tif ( memberSyntax ) {\n\n\t\t\t\t// member selection access\n\n\t\t\t\tparts = sid.split( '.' );\n\t\t\t\tsid = parts.shift();\n\t\t\t\tdata.member = parts.shift();\n\n\t\t\t} else if ( arraySyntax ) {\n\n\t\t\t\t// array-access syntax. can be used to express fields in one-dimensional vectors or two-dimensional matrices.\n\n\t\t\t\tvar indices = sid.split( '(' );\n\t\t\t\tsid = indices.shift();\n\n\t\t\t\tfor ( var i = 0; i < indices.length; i ++ ) {\n\n\t\t\t\t\tindices[ i ] = parseInt( indices[ i ].replace( /\\)/, '' ) );\n\n\t\t\t\t}\n\n\t\t\t\tdata.indices = indices;\n\n\t\t\t}\n\n\t\t\tdata.id = id;\n\t\t\tdata.sid = sid;\n\n\t\t\tdata.arraySyntax = arraySyntax;\n\t\t\tdata.memberSyntax = memberSyntax;\n\n\t\t\tdata.sampler = parseId( xml.getAttribute( 'source' ) );\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction buildAnimation( data ) {\n\n\t\t\tvar tracks = [];\n\n\t\t\tvar channels = data.channels;\n\t\t\tvar samplers = data.samplers;\n\t\t\tvar sources = data.sources;\n\n\t\t\tfor ( var target in channels ) {\n\n\t\t\t\tif ( channels.hasOwnProperty( target ) ) {\n\n\t\t\t\t\tvar channel = channels[ target ];\n\t\t\t\t\tvar sampler = samplers[ channel.sampler ];\n\n\t\t\t\t\tvar inputId = sampler.inputs.INPUT;\n\t\t\t\t\tvar outputId = sampler.inputs.OUTPUT;\n\n\t\t\t\t\tvar inputSource = sources[ inputId ];\n\t\t\t\t\tvar outputSource = sources[ outputId ];\n\n\t\t\t\t\tvar animation = buildAnimationChannel( channel, inputSource, outputSource );\n\n\t\t\t\t\tcreateKeyframeTracks( animation, tracks );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn tracks;\n\n\t\t}\n\n\t\tfunction getAnimation( id ) {\n\n\t\t\treturn getBuild( library.animations[ id ], buildAnimation );\n\n\t\t}\n\n\t\tfunction buildAnimationChannel( channel, inputSource, outputSource ) {\n\n\t\t\tvar node = library.nodes[ channel.id ];\n\t\t\tvar object3D = getNode( node.id );\n\n\t\t\tvar transform = node.transforms[ channel.sid ];\n\t\t\tvar defaultMatrix = node.matrix.clone().transpose();\n\n\t\t\tvar time, stride;\n\t\t\tvar i, il, j, jl;\n\n\t\t\tvar data = {};\n\n\t\t\t// the collada spec allows the animation of data in various ways.\n\t\t\t// depending on the transform type (matrix, translate, rotate, scale), we execute different logic\n\n\t\t\tswitch ( transform ) {\n\n\t\t\t\tcase 'matrix':\n\n\t\t\t\t\tfor ( i = 0, il = inputSource.array.length; i < il; i ++ ) {\n\n\t\t\t\t\t\ttime = inputSource.array[ i ];\n\t\t\t\t\t\tstride = i * outputSource.stride;\n\n\t\t\t\t\t\tif ( data[ time ] === undefined ) data[ time ] = {};\n\n\t\t\t\t\t\tif ( channel.arraySyntax === true ) {\n\n\t\t\t\t\t\t\tvar value = outputSource.array[ stride ];\n\t\t\t\t\t\t\tvar index = channel.indices[ 0 ] + 4 * channel.indices[ 1 ];\n\n\t\t\t\t\t\t\tdata[ time ][ index ] = value;\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tfor ( j = 0, jl = outputSource.stride; j < jl; j ++ ) {\n\n\t\t\t\t\t\t\t\tdata[ time ][ j ] = outputSource.array[ stride + j ];\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'translate':\n\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Animation transform type \"%s\" not yet implemented.', transform );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'rotate':\n\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Animation transform type \"%s\" not yet implemented.', transform );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'scale':\n\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Animation transform type \"%s\" not yet implemented.', transform );\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tvar keyframes = prepareAnimationData( data, defaultMatrix );\n\n\t\t\tvar animation = {\n\t\t\t\tname: object3D.uuid,\n\t\t\t\tkeyframes: keyframes\n\t\t\t};\n\n\t\t\treturn animation;\n\n\t\t}\n\n\t\tfunction prepareAnimationData( data, defaultMatrix ) {\n\n\t\t\tvar keyframes = [];\n\n\t\t\t// transfer data into a sortable array\n\n\t\t\tfor ( var time in data ) {\n\n\t\t\t\tkeyframes.push( { time: parseFloat( time ), value: data[ time ] } );\n\n\t\t\t}\n\n\t\t\t// ensure keyframes are sorted by time\n\n\t\t\tkeyframes.sort( ascending );\n\n\t\t\t// now we clean up all animation data, so we can use them for keyframe tracks\n\n\t\t\tfor ( var i = 0; i < 16; i ++ ) {\n\n\t\t\t\ttransformAnimationData( keyframes, i, defaultMatrix.elements[ i ] );\n\n\t\t\t}\n\n\t\t\treturn keyframes;\n\n\t\t\t// array sort function\n\n\t\t\tfunction ascending( a, b ) {\n\n\t\t\t\treturn a.time - b.time;\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar position = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\t\tvar scale = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\t\tvar quaternion = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Quaternion\"]();\n\n\t\tfunction createKeyframeTracks( animation, tracks ) {\n\n\t\t\tvar keyframes = animation.keyframes;\n\t\t\tvar name = animation.name;\n\n\t\t\tvar times = [];\n\t\t\tvar positionData = [];\n\t\t\tvar quaternionData = [];\n\t\t\tvar scaleData = [];\n\n\t\t\tfor ( var i = 0, l = keyframes.length; i < l; i ++ ) {\n\n\t\t\t\tvar keyframe = keyframes[ i ];\n\n\t\t\t\tvar time = keyframe.time;\n\t\t\t\tvar value = keyframe.value;\n\n\t\t\t\tmatrix.fromArray( value ).transpose();\n\t\t\t\tmatrix.decompose( position, quaternion, scale );\n\n\t\t\t\ttimes.push( time );\n\t\t\t\tpositionData.push( position.x, position.y, position.z );\n\t\t\t\tquaternionData.push( quaternion.x, quaternion.y, quaternion.z, quaternion.w );\n\t\t\t\tscaleData.push( scale.x, scale.y, scale.z );\n\n\t\t\t}\n\n\t\t\tif ( positionData.length > 0 ) tracks.push( new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"VectorKeyframeTrack\"]( name + '.position', times, positionData ) );\n\t\t\tif ( quaternionData.length > 0 ) tracks.push( new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"QuaternionKeyframeTrack\"]( name + '.quaternion', times, quaternionData ) );\n\t\t\tif ( scaleData.length > 0 ) tracks.push( new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"VectorKeyframeTrack\"]( name + '.scale', times, scaleData ) );\n\n\t\t\treturn tracks;\n\n\t\t}\n\n\t\tfunction transformAnimationData( keyframes, property, defaultValue ) {\n\n\t\t\tvar keyframe;\n\n\t\t\tvar empty = true;\n\t\t\tvar i, l;\n\n\t\t\t// check, if values of a property are missing in our keyframes\n\n\t\t\tfor ( i = 0, l = keyframes.length; i < l; i ++ ) {\n\n\t\t\t\tkeyframe = keyframes[ i ];\n\n\t\t\t\tif ( keyframe.value[ property ] === undefined ) {\n\n\t\t\t\t\tkeyframe.value[ property ] = null; // mark as missing\n\n\t\t\t\t} else {\n\n\t\t\t\t\tempty = false;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( empty === true ) {\n\n\t\t\t\t// no values at all, so we set a default value\n\n\t\t\t\tfor ( i = 0, l = keyframes.length; i < l; i ++ ) {\n\n\t\t\t\t\tkeyframe = keyframes[ i ];\n\n\t\t\t\t\tkeyframe.value[ property ] = defaultValue;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// filling gaps\n\n\t\t\t\tcreateMissingKeyframes( keyframes, property );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction createMissingKeyframes( keyframes, property ) {\n\n\t\t\tvar prev, next;\n\n\t\t\tfor ( var i = 0, l = keyframes.length; i < l; i ++ ) {\n\n\t\t\t\tvar keyframe = keyframes[ i ];\n\n\t\t\t\tif ( keyframe.value[ property ] === null ) {\n\n\t\t\t\t\tprev = getPrev( keyframes, i, property );\n\t\t\t\t\tnext = getNext( keyframes, i, property );\n\n\t\t\t\t\tif ( prev === null ) {\n\n\t\t\t\t\t\tkeyframe.value[ property ] = next.value[ property ];\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( next === null ) {\n\n\t\t\t\t\t\tkeyframe.value[ property ] = prev.value[ property ];\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tinterpolate( keyframe, prev, next, property );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction getPrev( keyframes, i, property ) {\n\n\t\t\twhile ( i >= 0 ) {\n\n\t\t\t\tvar keyframe = keyframes[ i ];\n\n\t\t\t\tif ( keyframe.value[ property ] !== null ) return keyframe;\n\n\t\t\t\ti --;\n\n\t\t\t}\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tfunction getNext( keyframes, i, property ) {\n\n\t\t\twhile ( i < keyframes.length ) {\n\n\t\t\t\tvar keyframe = keyframes[ i ];\n\n\t\t\t\tif ( keyframe.value[ property ] !== null ) return keyframe;\n\n\t\t\t\ti ++;\n\n\t\t\t}\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tfunction interpolate( key, prev, next, property ) {\n\n\t\t\tif ( ( next.time - prev.time ) === 0 ) {\n\n\t\t\t\tkey.value[ property ] = prev.value[ property ];\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t\tkey.value[ property ] = ( ( key.time - prev.time ) * ( next.value[ property ] - prev.value[ property ] ) / ( next.time - prev.time ) ) + prev.value[ property ];\n\n\t\t}\n\n\t\t// animation clips\n\n\t\tfunction parseAnimationClip( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'id' ) || 'default',\n\t\t\t\tstart: parseFloat( xml.getAttribute( 'start' ) || 0 ),\n\t\t\t\tend: parseFloat( xml.getAttribute( 'end' ) || 0 ),\n\t\t\t\tanimations: []\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'instance_animation':\n\t\t\t\t\t\tdata.animations.push( parseId( child.getAttribute( 'url' ) ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.clips[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction buildAnimationClip( data ) {\n\n\t\t\tvar tracks = [];\n\n\t\t\tvar name = data.name;\n\t\t\tvar duration = ( data.end - data.start ) || - 1;\n\t\t\tvar animations = data.animations;\n\n\t\t\tfor ( var i = 0, il = animations.length; i < il; i ++ ) {\n\n\t\t\t\tvar animationTracks = getAnimation( animations[ i ] );\n\n\t\t\t\tfor ( var j = 0, jl = animationTracks.length; j < jl; j ++ ) {\n\n\t\t\t\t\ttracks.push( animationTracks[ j ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"AnimationClip\"]( name, duration, tracks );\n\n\t\t}\n\n\t\tfunction getAnimationClip( id ) {\n\n\t\t\treturn getBuild( library.clips[ id ], buildAnimationClip );\n\n\t\t}\n\n\t\t// controller\n\n\t\tfunction parseController( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'skin':\n\t\t\t\t\t\t// there is exactly one skin per controller\n\t\t\t\t\t\tdata.id = parseId( child.getAttribute( 'source' ) );\n\t\t\t\t\t\tdata.skin = parseSkin( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'morph':\n\t\t\t\t\t\tdata.id = parseId( child.getAttribute( 'source' ) );\n\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Morph target animation not supported yet.' );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.controllers[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction parseSkin( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tsources: {}\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'bind_shape_matrix':\n\t\t\t\t\t\tdata.bindShapeMatrix = parseFloats( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'source':\n\t\t\t\t\t\tvar id = child.getAttribute( 'id' );\n\t\t\t\t\t\tdata.sources[ id ] = parseSource( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'joints':\n\t\t\t\t\t\tdata.joints = parseJoints( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'vertex_weights':\n\t\t\t\t\t\tdata.vertexWeights = parseVertexWeights( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseJoints( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tinputs: {}\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'input':\n\t\t\t\t\t\tvar semantic = child.getAttribute( 'semantic' );\n\t\t\t\t\t\tvar id = parseId( child.getAttribute( 'source' ) );\n\t\t\t\t\t\tdata.inputs[ semantic ] = id;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseVertexWeights( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tinputs: {}\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'input':\n\t\t\t\t\t\tvar semantic = child.getAttribute( 'semantic' );\n\t\t\t\t\t\tvar id = parseId( child.getAttribute( 'source' ) );\n\t\t\t\t\t\tvar offset = parseInt( child.getAttribute( 'offset' ) );\n\t\t\t\t\t\tdata.inputs[ semantic ] = { id: id, offset: offset };\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'vcount':\n\t\t\t\t\t\tdata.vcount = parseInts( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'v':\n\t\t\t\t\t\tdata.v = parseInts( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction buildController( data ) {\n\n\t\t\tvar build = {\n\t\t\t\tid: data.id\n\t\t\t};\n\n\t\t\tvar geometry = library.geometries[ build.id ];\n\n\t\t\tif ( data.skin !== undefined ) {\n\n\t\t\t\tbuild.skin = buildSkin( data.skin );\n\n\t\t\t\t// we enhance the 'sources' property of the corresponding geometry with our skin data\n\n\t\t\t\tgeometry.sources.skinIndices = build.skin.indices;\n\t\t\t\tgeometry.sources.skinWeights = build.skin.weights;\n\n\t\t\t}\n\n\t\t\treturn build;\n\n\t\t}\n\n\t\tfunction buildSkin( data ) {\n\n\t\t\tvar BONE_LIMIT = 4;\n\n\t\t\tvar build = {\n\t\t\t\tjoints: [], // this must be an array to preserve the joint order\n\t\t\t\tindices: {\n\t\t\t\t\tarray: [],\n\t\t\t\t\tstride: BONE_LIMIT\n\t\t\t\t},\n\t\t\t\tweights: {\n\t\t\t\t\tarray: [],\n\t\t\t\t\tstride: BONE_LIMIT\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tvar sources = data.sources;\n\t\t\tvar vertexWeights = data.vertexWeights;\n\n\t\t\tvar vcount = vertexWeights.vcount;\n\t\t\tvar v = vertexWeights.v;\n\t\t\tvar jointOffset = vertexWeights.inputs.JOINT.offset;\n\t\t\tvar weightOffset = vertexWeights.inputs.WEIGHT.offset;\n\n\t\t\tvar jointSource = data.sources[ data.joints.inputs.JOINT ];\n\t\t\tvar inverseSource = data.sources[ data.joints.inputs.INV_BIND_MATRIX ];\n\n\t\t\tvar weights = sources[ vertexWeights.inputs.WEIGHT.id ].array;\n\t\t\tvar stride = 0;\n\n\t\t\tvar i, j, l;\n\n\t\t\t// procces skin data for each vertex\n\n\t\t\tfor ( i = 0, l = vcount.length; i < l; i ++ ) {\n\n\t\t\t\tvar jointCount = vcount[ i ]; // this is the amount of joints that affect a single vertex\n\t\t\t\tvar vertexSkinData = [];\n\n\t\t\t\tfor ( j = 0; j < jointCount; j ++ ) {\n\n\t\t\t\t\tvar skinIndex = v[ stride + jointOffset ];\n\t\t\t\t\tvar weightId = v[ stride + weightOffset ];\n\t\t\t\t\tvar skinWeight = weights[ weightId ];\n\n\t\t\t\t\tvertexSkinData.push( { index: skinIndex, weight: skinWeight } );\n\n\t\t\t\t\tstride += 2;\n\n\t\t\t\t}\n\n\t\t\t\t// we sort the joints in descending order based on the weights.\n\t\t\t\t// this ensures, we only procced the most important joints of the vertex\n\n\t\t\t\tvertexSkinData.sort( descending );\n\n\t\t\t\t// now we provide for each vertex a set of four index and weight values.\n\t\t\t\t// the order of the skin data matches the order of vertices\n\n\t\t\t\tfor ( j = 0; j < BONE_LIMIT; j ++ ) {\n\n\t\t\t\t\tvar d = vertexSkinData[ j ];\n\n\t\t\t\t\tif ( d !== undefined ) {\n\n\t\t\t\t\t\tbuild.indices.array.push( d.index );\n\t\t\t\t\t\tbuild.weights.array.push( d.weight );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tbuild.indices.array.push( 0 );\n\t\t\t\t\t\tbuild.weights.array.push( 0 );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// setup bind matrix\n\n\t\t\tif ( data.bindShapeMatrix ) {\n\n\t\t\t\tbuild.bindMatrix = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]().fromArray( data.bindShapeMatrix ).transpose();\n\n\t\t\t} else {\n\n\t\t\t\tbuild.bindMatrix = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]().identity();\n\n\t\t\t}\n\n\t\t\t// process bones and inverse bind matrix data\n\n\t\t\tfor ( i = 0, l = jointSource.array.length; i < l; i ++ ) {\n\n\t\t\t\tvar name = jointSource.array[ i ];\n\t\t\t\tvar boneInverse = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]().fromArray( inverseSource.array, i * inverseSource.stride ).transpose();\n\n\t\t\t\tbuild.joints.push( { name: name, boneInverse: boneInverse } );\n\n\t\t\t}\n\n\t\t\treturn build;\n\n\t\t\t// array sort function\n\n\t\t\tfunction descending( a, b ) {\n\n\t\t\t\treturn b.weight - a.weight;\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction getController( id ) {\n\n\t\t\treturn getBuild( library.controllers[ id ], buildController );\n\n\t\t}\n\n\t\t// image\n\n\t\tfunction parseImage( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tinit_from: getElementsByTagName( xml, 'init_from' )[ 0 ].textContent\n\t\t\t};\n\n\t\t\tlibrary.images[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction buildImage( data ) {\n\n\t\t\tif ( data.build !== undefined ) return data.build;\n\n\t\t\treturn data.init_from;\n\n\t\t}\n\n\t\tfunction getImage( id ) {\n\n\t\t\tvar data = library.images[ id ];\n\n\t\t\tif ( data !== undefined ) {\n\n\t\t\t\treturn getBuild( data, buildImage );\n\n\t\t\t}\n\n\t\t\tconsole.warn( 'THREE.ColladaLoader: Couldn\\'t find image with ID:', id );\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// effect\n\n\t\tfunction parseEffect( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'profile_COMMON':\n\t\t\t\t\t\tdata.profile = parseEffectProfileCOMMON( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.effects[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction parseEffectProfileCOMMON( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tsurfaces: {},\n\t\t\t\tsamplers: {}\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'newparam':\n\t\t\t\t\t\tparseEffectNewparam( child, data );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'technique':\n\t\t\t\t\t\tdata.technique = parseEffectTechnique( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'extra':\n\t\t\t\t\t\tdata.extra = parseEffectExtra( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectNewparam( xml, data ) {\n\n\t\t\tvar sid = xml.getAttribute( 'sid' );\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'surface':\n\t\t\t\t\t\tdata.surfaces[ sid ] = parseEffectSurface( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'sampler2D':\n\t\t\t\t\t\tdata.samplers[ sid ] = parseEffectSampler( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction parseEffectSurface( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'init_from':\n\t\t\t\t\t\tdata.init_from = child.textContent;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectSampler( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'source':\n\t\t\t\t\t\tdata.source = child.textContent;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectTechnique( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'constant':\n\t\t\t\t\tcase 'lambert':\n\t\t\t\t\tcase 'blinn':\n\t\t\t\t\tcase 'phong':\n\t\t\t\t\t\tdata.type = child.nodeName;\n\t\t\t\t\t\tdata.parameters = parseEffectParameters( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectParameters( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'emission':\n\t\t\t\t\tcase 'diffuse':\n\t\t\t\t\tcase 'specular':\n\t\t\t\t\tcase 'bump':\n\t\t\t\t\tcase 'ambient':\n\t\t\t\t\tcase 'shininess':\n\t\t\t\t\tcase 'transparency':\n\t\t\t\t\t\tdata[ child.nodeName ] = parseEffectParameter( child );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'transparent':\n\t\t\t\t\t\tdata[ child.nodeName ] = {\n\t\t\t\t\t\t\topaque: child.getAttribute( 'opaque' ),\n\t\t\t\t\t\t\tdata: parseEffectParameter( child )\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectParameter( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'color':\n\t\t\t\t\t\tdata[ child.nodeName ] = parseFloats( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'float':\n\t\t\t\t\t\tdata[ child.nodeName ] = parseFloat( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'texture':\n\t\t\t\t\t\tdata[ child.nodeName ] = { id: child.getAttribute( 'texture' ), extra: parseEffectParameterTexture( child ) };\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectParameterTexture( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\ttechnique: {}\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'extra':\n\t\t\t\t\t\tparseEffectParameterTextureExtra( child, data );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectParameterTextureExtra( xml, data ) {\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'technique':\n\t\t\t\t\t\tparseEffectParameterTextureExtraTechnique( child, data );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction parseEffectParameterTextureExtraTechnique( xml, data ) {\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'repeatU':\n\t\t\t\t\tcase 'repeatV':\n\t\t\t\t\tcase 'offsetU':\n\t\t\t\t\tcase 'offsetV':\n\t\t\t\t\t\tdata.technique[ child.nodeName ] = parseFloat( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'wrapU':\n\t\t\t\t\tcase 'wrapV':\n\n\t\t\t\t\t\t// some files have values for wrapU/wrapV which become NaN via parseInt\n\n\t\t\t\t\t\tif ( child.textContent.toUpperCase() === 'TRUE' ) {\n\n\t\t\t\t\t\t\tdata.technique[ child.nodeName ] = 1;\n\n\t\t\t\t\t\t} else if ( child.textContent.toUpperCase() === 'FALSE' ) {\n\n\t\t\t\t\t\t\tdata.technique[ child.nodeName ] = 0;\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tdata.technique[ child.nodeName ] = parseInt( child.textContent );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction parseEffectExtra( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'technique':\n\t\t\t\t\t\tdata.technique = parseEffectExtraTechnique( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseEffectExtraTechnique( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'double_sided':\n\t\t\t\t\t\tdata[ child.nodeName ] = parseInt( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction buildEffect( data ) {\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction getEffect( id ) {\n\n\t\t\treturn getBuild( library.effects[ id ], buildEffect );\n\n\t\t}\n\n\t\t// material\n\n\t\tfunction parseMaterial( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'name' )\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'instance_effect':\n\t\t\t\t\t\tdata.url = parseId( child.getAttribute( 'url' ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.materials[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction getTextureLoader( image ) {\n\n\t\t\tvar loader;\n\n\t\t\tvar extension = image.slice( ( image.lastIndexOf( '.' ) - 1 >>> 0 ) + 2 ); // http://www.jstips.co/en/javascript/get-file-extension/\n\t\t\textension = extension.toLowerCase();\n\n\t\t\tswitch ( extension ) {\n\n\t\t\t\tcase 'tga':\n\t\t\t\t\tloader = tgaLoader;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tloader = textureLoader;\n\n\t\t\t}\n\n\t\t\treturn loader;\n\n\t\t}\n\n\t\tfunction buildMaterial( data ) {\n\n\t\t\tvar effect = getEffect( data.url );\n\t\t\tvar technique = effect.profile.technique;\n\t\t\tvar extra = effect.profile.extra;\n\n\t\t\tvar material;\n\n\t\t\tswitch ( technique.type ) {\n\n\t\t\t\tcase 'phong':\n\t\t\t\tcase 'blinn':\n\t\t\t\t\tmaterial = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MeshPhongMaterial\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'lambert':\n\t\t\t\t\tmaterial = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MeshLambertMaterial\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tmaterial = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MeshBasicMaterial\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tmaterial.name = data.name || '';\n\n\t\t\tfunction getTexture( textureObject ) {\n\n\t\t\t\tvar sampler = effect.profile.samplers[ textureObject.id ];\n\t\t\t\tvar image = null;\n\n\t\t\t\t// get image\n\n\t\t\t\tif ( sampler !== undefined ) {\n\n\t\t\t\t\tvar surface = effect.profile.surfaces[ sampler.source ];\n\t\t\t\t\timage = getImage( surface.init_from );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Undefined sampler. Access image directly (see #12530).' );\n\t\t\t\t\timage = getImage( textureObject.id );\n\n\t\t\t\t}\n\n\t\t\t\t// create texture if image is avaiable\n\n\t\t\t\tif ( image !== null ) {\n\n\t\t\t\t\tvar loader = getTextureLoader( image );\n\n\t\t\t\t\tif ( loader !== undefined ) {\n\n\t\t\t\t\t\tvar texture = loader.load( image );\n\n\t\t\t\t\t\tvar extra = textureObject.extra;\n\n\t\t\t\t\t\tif ( extra !== undefined && extra.technique !== undefined && isEmpty( extra.technique ) === false ) {\n\n\t\t\t\t\t\t\tvar technique = extra.technique;\n\n\t\t\t\t\t\t\ttexture.wrapS = technique.wrapU ? _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"RepeatWrapping\"] : _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"ClampToEdgeWrapping\"];\n\t\t\t\t\t\t\ttexture.wrapT = technique.wrapV ? _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"RepeatWrapping\"] : _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"ClampToEdgeWrapping\"];\n\n\t\t\t\t\t\t\ttexture.offset.set( technique.offsetU || 0, technique.offsetV || 0 );\n\t\t\t\t\t\t\ttexture.repeat.set( technique.repeatU || 1, technique.repeatV || 1 );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\ttexture.wrapS = _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"RepeatWrapping\"];\n\t\t\t\t\t\t\ttexture.wrapT = _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"RepeatWrapping\"];\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn texture;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Loader for texture %s not found.', image );\n\n\t\t\t\t\t\treturn null;\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Couldn\\'t create texture with ID:', textureObject.id );\n\n\t\t\t\t\treturn null;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar parameters = technique.parameters;\n\n\t\t\tfor ( var key in parameters ) {\n\n\t\t\t\tvar parameter = parameters[ key ];\n\n\t\t\t\tswitch ( key ) {\n\n\t\t\t\t\tcase 'diffuse':\n\t\t\t\t\t\tif ( parameter.color ) material.color.fromArray( parameter.color );\n\t\t\t\t\t\tif ( parameter.texture ) material.map = getTexture( parameter.texture );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'specular':\n\t\t\t\t\t\tif ( parameter.color && material.specular ) material.specular.fromArray( parameter.color );\n\t\t\t\t\t\tif ( parameter.texture ) material.specularMap = getTexture( parameter.texture );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'bump':\n\t\t\t\t\t\tif ( parameter.texture ) material.normalMap = getTexture( parameter.texture );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'ambient':\n\t\t\t\t\t\tif ( parameter.texture ) material.lightMap = getTexture( parameter.texture );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'shininess':\n\t\t\t\t\t\tif ( parameter.float && material.shininess ) material.shininess = parameter.float;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'emission':\n\t\t\t\t\t\tif ( parameter.color && material.emissive ) material.emissive.fromArray( parameter.color );\n\t\t\t\t\t\tif ( parameter.texture ) material.emissiveMap = getTexture( parameter.texture );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t//\n\n\t\t\tvar transparent = parameters[ 'transparent' ];\n\t\t\tvar transparency = parameters[ 'transparency' ];\n\n\t\t\t// does not exist but \n\n\t\t\tif ( transparency === undefined && transparent ) {\n\n\t\t\t\ttransparency = {\n\t\t\t\t\tfloat: 1\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t\t// does not exist but \n\n\t\t\tif ( transparent === undefined && transparency ) {\n\n\t\t\t\ttransparent = {\n\t\t\t\t\topaque: 'A_ONE',\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcolor: [ 1, 1, 1, 1 ]\n\t\t\t\t\t} };\n\n\t\t\t}\n\n\t\t\tif ( transparent && transparency ) {\n\n\t\t\t\t// handle case if a texture exists but no color\n\n\t\t\t\tif ( transparent.data.texture ) {\n\n\t\t\t\t\t// we do not set an alpha map (see #13792)\n\n\t\t\t\t\tmaterial.transparent = true;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tvar color = transparent.data.color;\n\n\t\t\t\t\tswitch ( transparent.opaque ) {\n\n\t\t\t\t\t\tcase 'A_ONE':\n\t\t\t\t\t\t\tmaterial.opacity = color[ 3 ] * transparency.float;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'RGB_ZERO':\n\t\t\t\t\t\t\tmaterial.opacity = 1 - ( color[ 0 ] * transparency.float );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'A_ZERO':\n\t\t\t\t\t\t\tmaterial.opacity = 1 - ( color[ 3 ] * transparency.float );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'RGB_ONE':\n\t\t\t\t\t\t\tmaterial.opacity = color[ 0 ] * transparency.float;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Invalid opaque type \"%s\" of transparent tag.', transparent.opaque );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( material.opacity < 1 ) material.transparent = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t//\n\n\t\t\tif ( extra !== undefined && extra.technique !== undefined && extra.technique.double_sided === 1 ) {\n\n\t\t\t\tmaterial.side = _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"DoubleSide\"];\n\n\t\t\t}\n\n\t\t\treturn material;\n\n\t\t}\n\n\t\tfunction getMaterial( id ) {\n\n\t\t\treturn getBuild( library.materials[ id ], buildMaterial );\n\n\t\t}\n\n\t\t// camera\n\n\t\tfunction parseCamera( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'name' )\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'optics':\n\t\t\t\t\t\tdata.optics = parseCameraOptics( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.cameras[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction parseCameraOptics( xml ) {\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'technique_common':\n\t\t\t\t\t\treturn parseCameraTechnique( child );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn {};\n\n\t\t}\n\n\t\tfunction parseCameraTechnique( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'perspective':\n\t\t\t\t\tcase 'orthographic':\n\n\t\t\t\t\t\tdata.technique = child.nodeName;\n\t\t\t\t\t\tdata.parameters = parseCameraParameters( child );\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseCameraParameters( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'xfov':\n\t\t\t\t\tcase 'yfov':\n\t\t\t\t\tcase 'xmag':\n\t\t\t\t\tcase 'ymag':\n\t\t\t\t\tcase 'znear':\n\t\t\t\t\tcase 'zfar':\n\t\t\t\t\tcase 'aspect_ratio':\n\t\t\t\t\t\tdata[ child.nodeName ] = parseFloat( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction buildCamera( data ) {\n\n\t\t\tvar camera;\n\n\t\t\tswitch ( data.optics.technique ) {\n\n\t\t\t\tcase 'perspective':\n\t\t\t\t\tcamera = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"PerspectiveCamera\"](\n\t\t\t\t\t\tdata.optics.parameters.yfov,\n\t\t\t\t\t\tdata.optics.parameters.aspect_ratio,\n\t\t\t\t\t\tdata.optics.parameters.znear,\n\t\t\t\t\t\tdata.optics.parameters.zfar\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'orthographic':\n\t\t\t\t\tvar ymag = data.optics.parameters.ymag;\n\t\t\t\t\tvar xmag = data.optics.parameters.xmag;\n\t\t\t\t\tvar aspectRatio = data.optics.parameters.aspect_ratio;\n\n\t\t\t\t\txmag = ( xmag === undefined ) ? ( ymag * aspectRatio ) : xmag;\n\t\t\t\t\tymag = ( ymag === undefined ) ? ( xmag / aspectRatio ) : ymag;\n\n\t\t\t\t\txmag *= 0.5;\n\t\t\t\t\tymag *= 0.5;\n\n\t\t\t\t\tcamera = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"OrthographicCamera\"](\n\t\t\t\t\t\t- xmag, xmag, ymag, - ymag, // left, right, top, bottom\n\t\t\t\t\t\tdata.optics.parameters.znear,\n\t\t\t\t\t\tdata.optics.parameters.zfar\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tcamera = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"PerspectiveCamera\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tcamera.name = data.name || '';\n\n\t\t\treturn camera;\n\n\t\t}\n\n\t\tfunction getCamera( id ) {\n\n\t\t\tvar data = library.cameras[ id ];\n\n\t\t\tif ( data !== undefined ) {\n\n\t\t\t\treturn getBuild( data, buildCamera );\n\n\t\t\t}\n\n\t\t\tconsole.warn( 'THREE.ColladaLoader: Couldn\\'t find camera with ID:', id );\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// light\n\n\t\tfunction parseLight( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'technique_common':\n\t\t\t\t\t\tdata = parseLightTechnique( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.lights[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction parseLightTechnique( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'directional':\n\t\t\t\t\tcase 'point':\n\t\t\t\t\tcase 'spot':\n\t\t\t\t\tcase 'ambient':\n\n\t\t\t\t\t\tdata.technique = child.nodeName;\n\t\t\t\t\t\tdata.parameters = parseLightParameters( child );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseLightParameters( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'color':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tdata.color = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Color\"]().fromArray( array );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'falloff_angle':\n\t\t\t\t\t\tdata.falloffAngle = parseFloat( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'quadratic_attenuation':\n\t\t\t\t\t\tvar f = parseFloat( child.textContent );\n\t\t\t\t\t\tdata.distance = f ? Math.sqrt( 1 / f ) : 0;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction buildLight( data ) {\n\n\t\t\tvar light;\n\n\t\t\tswitch ( data.technique ) {\n\n\t\t\t\tcase 'directional':\n\t\t\t\t\tlight = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"DirectionalLight\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'point':\n\t\t\t\t\tlight = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"PointLight\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'spot':\n\t\t\t\t\tlight = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"SpotLight\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'ambient':\n\t\t\t\t\tlight = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"AmbientLight\"]();\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( data.parameters.color ) light.color.copy( data.parameters.color );\n\t\t\tif ( data.parameters.distance ) light.distance = data.parameters.distance;\n\n\t\t\treturn light;\n\n\t\t}\n\n\t\tfunction getLight( id ) {\n\n\t\t\tvar data = library.lights[ id ];\n\n\t\t\tif ( data !== undefined ) {\n\n\t\t\t\treturn getBuild( data, buildLight );\n\n\t\t\t}\n\n\t\t\tconsole.warn( 'THREE.ColladaLoader: Couldn\\'t find light with ID:', id );\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// geometry\n\n\t\tfunction parseGeometry( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'name' ),\n\t\t\t\tsources: {},\n\t\t\t\tvertices: {},\n\t\t\t\tprimitives: []\n\t\t\t};\n\n\t\t\tvar mesh = getElementsByTagName( xml, 'mesh' )[ 0 ];\n\n\t\t\t// the following tags inside geometry are not supported yet (see https://github.com/mrdoob/three.js/pull/12606): convex_mesh, spline, brep\n\t\t\tif ( mesh === undefined ) return;\n\n\t\t\tfor ( var i = 0; i < mesh.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = mesh.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tvar id = child.getAttribute( 'id' );\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'source':\n\t\t\t\t\t\tdata.sources[ id ] = parseSource( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'vertices':\n\t\t\t\t\t\t// data.sources[ id ] = data.sources[ parseId( getElementsByTagName( child, 'input' )[ 0 ].getAttribute( 'source' ) ) ];\n\t\t\t\t\t\tdata.vertices = parseGeometryVertices( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'polygons':\n\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Unsupported primitive type: ', child.nodeName );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'lines':\n\t\t\t\t\tcase 'linestrips':\n\t\t\t\t\tcase 'polylist':\n\t\t\t\t\tcase 'triangles':\n\t\t\t\t\t\tdata.primitives.push( parseGeometryPrimitive( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tconsole.log( child );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.geometries[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction parseSource( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tarray: [],\n\t\t\t\tstride: 3\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'float_array':\n\t\t\t\t\t\tdata.array = parseFloats( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'Name_array':\n\t\t\t\t\t\tdata.array = parseStrings( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'technique_common':\n\t\t\t\t\t\tvar accessor = getElementsByTagName( child, 'accessor' )[ 0 ];\n\n\t\t\t\t\t\tif ( accessor !== undefined ) {\n\n\t\t\t\t\t\t\tdata.stride = parseInt( accessor.getAttribute( 'stride' ) );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseGeometryVertices( xml ) {\n\n\t\t\tvar data = {};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tdata[ child.getAttribute( 'semantic' ) ] = parseId( child.getAttribute( 'source' ) );\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseGeometryPrimitive( xml ) {\n\n\t\t\tvar primitive = {\n\t\t\t\ttype: xml.nodeName,\n\t\t\t\tmaterial: xml.getAttribute( 'material' ),\n\t\t\t\tcount: parseInt( xml.getAttribute( 'count' ) ),\n\t\t\t\tinputs: {},\n\t\t\t\tstride: 0,\n\t\t\t\thasUV: false\n\t\t\t};\n\n\t\t\tfor ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'input':\n\t\t\t\t\t\tvar id = parseId( child.getAttribute( 'source' ) );\n\t\t\t\t\t\tvar semantic = child.getAttribute( 'semantic' );\n\t\t\t\t\t\tvar offset = parseInt( child.getAttribute( 'offset' ) );\n\t\t\t\t\t\tvar set = parseInt( child.getAttribute( 'set' ) );\n\t\t\t\t\t\tvar inputname = ( set > 0 ? semantic + set : semantic );\n\t\t\t\t\t\tprimitive.inputs[ inputname ] = { id: id, offset: offset };\n\t\t\t\t\t\tprimitive.stride = Math.max( primitive.stride, offset + 1 );\n\t\t\t\t\t\tif ( semantic === 'TEXCOORD' ) primitive.hasUV = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'vcount':\n\t\t\t\t\t\tprimitive.vcount = parseInts( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'p':\n\t\t\t\t\t\tprimitive.p = parseInts( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn primitive;\n\n\t\t}\n\n\t\tfunction groupPrimitives( primitives ) {\n\n\t\t\tvar build = {};\n\n\t\t\tfor ( var i = 0; i < primitives.length; i ++ ) {\n\n\t\t\t\tvar primitive = primitives[ i ];\n\n\t\t\t\tif ( build[ primitive.type ] === undefined ) build[ primitive.type ] = [];\n\n\t\t\t\tbuild[ primitive.type ].push( primitive );\n\n\t\t\t}\n\n\t\t\treturn build;\n\n\t\t}\n\n\t\tfunction checkUVCoordinates( primitives ) {\n\n\t\t\tvar count = 0;\n\n\t\t\tfor ( var i = 0, l = primitives.length; i < l; i ++ ) {\n\n\t\t\t\tvar primitive = primitives[ i ];\n\n\t\t\t\tif ( primitive.hasUV === true ) {\n\n\t\t\t\t\tcount ++;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( count > 0 && count < primitives.length ) {\n\n\t\t\t\tprimitives.uvsNeedsFix = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction buildGeometry( data ) {\n\n\t\t\tvar build = {};\n\n\t\t\tvar sources = data.sources;\n\t\t\tvar vertices = data.vertices;\n\t\t\tvar primitives = data.primitives;\n\n\t\t\tif ( primitives.length === 0 ) return {};\n\n\t\t\t// our goal is to create one buffer geometry for a single type of primitives\n\t\t\t// first, we group all primitives by their type\n\n\t\t\tvar groupedPrimitives = groupPrimitives( primitives );\n\n\t\t\tfor ( var type in groupedPrimitives ) {\n\n\t\t\t\tvar primitiveType = groupedPrimitives[ type ];\n\n\t\t\t\t// second, ensure consistent uv coordinates for each type of primitives (polylist,triangles or lines)\n\n\t\t\t\tcheckUVCoordinates( primitiveType );\n\n\t\t\t\t// third, create a buffer geometry for each type of primitives\n\n\t\t\t\tbuild[ type ] = buildGeometryType( primitiveType, sources, vertices );\n\n\t\t\t}\n\n\t\t\treturn build;\n\n\t\t}\n\n\t\tfunction buildGeometryType( primitives, sources, vertices ) {\n\n\t\t\tvar build = {};\n\n\t\t\tvar position = { array: [], stride: 0 };\n\t\t\tvar normal = { array: [], stride: 0 };\n\t\t\tvar uv = { array: [], stride: 0 };\n\t\t\tvar uv2 = { array: [], stride: 0 };\n\t\t\tvar color = { array: [], stride: 0 };\n\n\t\t\tvar skinIndex = { array: [], stride: 4 };\n\t\t\tvar skinWeight = { array: [], stride: 4 };\n\n\t\t\tvar geometry = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"BufferGeometry\"]();\n\n\t\t\tvar materialKeys = [];\n\n\t\t\tvar start = 0;\n\n\t\t\tfor ( var p = 0; p < primitives.length; p ++ ) {\n\n\t\t\t\tvar primitive = primitives[ p ];\n\t\t\t\tvar inputs = primitive.inputs;\n\n\t\t\t\t// groups\n\n\t\t\t\tvar count = 0;\n\n\t\t\t\tswitch ( primitive.type ) {\n\n\t\t\t\t\tcase 'lines':\n\t\t\t\t\tcase 'linestrips':\n\t\t\t\t\t\tcount = primitive.count * 2;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'triangles':\n\t\t\t\t\t\tcount = primitive.count * 3;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'polylist':\n\n\t\t\t\t\t\tfor ( var g = 0; g < primitive.count; g ++ ) {\n\n\t\t\t\t\t\t\tvar vc = primitive.vcount[ g ];\n\n\t\t\t\t\t\t\tswitch ( vc ) {\n\n\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\tcount += 3; // single triangle\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\t\tcount += 6; // quad, subdivided into two triangles\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tcount += ( vc - 2 ) * 3; // polylist with more than four vertices\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Unknow primitive type:', primitive.type );\n\n\t\t\t\t}\n\n\t\t\t\tgeometry.addGroup( start, count, p );\n\t\t\t\tstart += count;\n\n\t\t\t\t// material\n\n\t\t\t\tif ( primitive.material ) {\n\n\t\t\t\t\tmaterialKeys.push( primitive.material );\n\n\t\t\t\t}\n\n\t\t\t\t// geometry data\n\n\t\t\t\tfor ( var name in inputs ) {\n\n\t\t\t\t\tvar input = inputs[ name ];\n\n\t\t\t\t\tswitch ( name )\t{\n\n\t\t\t\t\t\tcase 'VERTEX':\n\t\t\t\t\t\t\tfor ( var key in vertices ) {\n\n\t\t\t\t\t\t\t\tvar id = vertices[ key ];\n\n\t\t\t\t\t\t\t\tswitch ( key ) {\n\n\t\t\t\t\t\t\t\t\tcase 'POSITION':\n\t\t\t\t\t\t\t\t\t\tvar prevLength = position.array.length;\n\t\t\t\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ id ], input.offset, position.array );\n\t\t\t\t\t\t\t\t\t\tposition.stride = sources[ id ].stride;\n\n\t\t\t\t\t\t\t\t\t\tif ( sources.skinWeights && sources.skinIndices ) {\n\n\t\t\t\t\t\t\t\t\t\t\tbuildGeometryData( primitive, sources.skinIndices, input.offset, skinIndex.array );\n\t\t\t\t\t\t\t\t\t\t\tbuildGeometryData( primitive, sources.skinWeights, input.offset, skinWeight.array );\n\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// see #3803\n\n\t\t\t\t\t\t\t\t\t\tif ( primitive.hasUV === false && primitives.uvsNeedsFix === true ) {\n\n\t\t\t\t\t\t\t\t\t\t\tvar count = ( position.array.length - prevLength ) / position.stride;\n\n\t\t\t\t\t\t\t\t\t\t\tfor ( var i = 0; i < count; i ++ ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// fill missing uv coordinates\n\n\t\t\t\t\t\t\t\t\t\t\t\tuv.array.push( 0, 0 );\n\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase 'NORMAL':\n\t\t\t\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ id ], input.offset, normal.array );\n\t\t\t\t\t\t\t\t\t\tnormal.stride = sources[ id ].stride;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase 'COLOR':\n\t\t\t\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ id ], input.offset, color.array );\n\t\t\t\t\t\t\t\t\t\tcolor.stride = sources[ id ].stride;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase 'TEXCOORD':\n\t\t\t\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ id ], input.offset, uv.array );\n\t\t\t\t\t\t\t\t\t\tuv.stride = sources[ id ].stride;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase 'TEXCOORD1':\n\t\t\t\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ id ], input.offset, uv2.array );\n\t\t\t\t\t\t\t\t\t\tuv.stride = sources[ id ].stride;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Semantic \"%s\" not handled in geometry build process.', key );\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'NORMAL':\n\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ input.id ], input.offset, normal.array );\n\t\t\t\t\t\t\tnormal.stride = sources[ input.id ].stride;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'COLOR':\n\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ input.id ], input.offset, color.array );\n\t\t\t\t\t\t\tcolor.stride = sources[ input.id ].stride;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'TEXCOORD':\n\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ input.id ], input.offset, uv.array );\n\t\t\t\t\t\t\tuv.stride = sources[ input.id ].stride;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'TEXCOORD1':\n\t\t\t\t\t\t\tbuildGeometryData( primitive, sources[ input.id ], input.offset, uv2.array );\n\t\t\t\t\t\t\tuv2.stride = sources[ input.id ].stride;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// build geometry\n\n\t\t\tif ( position.array.length > 0 ) geometry.setAttribute( 'position', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( position.array, position.stride ) );\n\t\t\tif ( normal.array.length > 0 ) geometry.setAttribute( 'normal', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( normal.array, normal.stride ) );\n\t\t\tif ( color.array.length > 0 ) geometry.setAttribute( 'color', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( color.array, color.stride ) );\n\t\t\tif ( uv.array.length > 0 ) geometry.setAttribute( 'uv', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( uv.array, uv.stride ) );\n\t\t\tif ( uv2.array.length > 0 ) geometry.setAttribute( 'uv2', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( uv2.array, uv2.stride ) );\n\n\t\t\tif ( skinIndex.array.length > 0 ) geometry.setAttribute( 'skinIndex', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( skinIndex.array, skinIndex.stride ) );\n\t\t\tif ( skinWeight.array.length > 0 ) geometry.setAttribute( 'skinWeight', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( skinWeight.array, skinWeight.stride ) );\n\n\t\t\tbuild.data = geometry;\n\t\t\tbuild.type = primitives[ 0 ].type;\n\t\t\tbuild.materialKeys = materialKeys;\n\n\t\t\treturn build;\n\n\t\t}\n\n\t\tfunction buildGeometryData( primitive, source, offset, array ) {\n\n\t\t\tvar indices = primitive.p;\n\t\t\tvar stride = primitive.stride;\n\t\t\tvar vcount = primitive.vcount;\n\n\t\t\tfunction pushVector( i ) {\n\n\t\t\t\tvar index = indices[ i + offset ] * sourceStride;\n\t\t\t\tvar length = index + sourceStride;\n\n\t\t\t\tfor ( ; index < length; index ++ ) {\n\n\t\t\t\t\tarray.push( sourceArray[ index ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar sourceArray = source.array;\n\t\t\tvar sourceStride = source.stride;\n\n\t\t\tif ( primitive.vcount !== undefined ) {\n\n\t\t\t\tvar index = 0;\n\n\t\t\t\tfor ( var i = 0, l = vcount.length; i < l; i ++ ) {\n\n\t\t\t\t\tvar count = vcount[ i ];\n\n\t\t\t\t\tif ( count === 4 ) {\n\n\t\t\t\t\t\tvar a = index + stride * 0;\n\t\t\t\t\t\tvar b = index + stride * 1;\n\t\t\t\t\t\tvar c = index + stride * 2;\n\t\t\t\t\t\tvar d = index + stride * 3;\n\n\t\t\t\t\t\tpushVector( a ); pushVector( b ); pushVector( d );\n\t\t\t\t\t\tpushVector( b ); pushVector( c ); pushVector( d );\n\n\t\t\t\t\t} else if ( count === 3 ) {\n\n\t\t\t\t\t\tvar a = index + stride * 0;\n\t\t\t\t\t\tvar b = index + stride * 1;\n\t\t\t\t\t\tvar c = index + stride * 2;\n\n\t\t\t\t\t\tpushVector( a ); pushVector( b ); pushVector( c );\n\n\t\t\t\t\t} else if ( count > 4 ) {\n\n\t\t\t\t\t\tfor ( var k = 1, kl = ( count - 2 ); k <= kl; k ++ ) {\n\n\t\t\t\t\t\t\tvar a = index + stride * 0;\n\t\t\t\t\t\t\tvar b = index + stride * k;\n\t\t\t\t\t\t\tvar c = index + stride * ( k + 1 );\n\n\t\t\t\t\t\t\tpushVector( a ); pushVector( b ); pushVector( c );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tindex += stride * count;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tfor ( var i = 0, l = indices.length; i < l; i += stride ) {\n\n\t\t\t\t\tpushVector( i );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction getGeometry( id ) {\n\n\t\t\treturn getBuild( library.geometries[ id ], buildGeometry );\n\n\t\t}\n\n\t\t// kinematics\n\n\t\tfunction parseKinematicsModel( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'name' ) || '',\n\t\t\t\tjoints: {},\n\t\t\t\tlinks: []\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'technique_common':\n\t\t\t\t\t\tparseKinematicsTechniqueCommon( child, data );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.kinematicsModels[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction buildKinematicsModel( data ) {\n\n\t\t\tif ( data.build !== undefined ) return data.build;\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction getKinematicsModel( id ) {\n\n\t\t\treturn getBuild( library.kinematicsModels[ id ], buildKinematicsModel );\n\n\t\t}\n\n\t\tfunction parseKinematicsTechniqueCommon( xml, data ) {\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'joint':\n\t\t\t\t\t\tdata.joints[ child.getAttribute( 'sid' ) ] = parseKinematicsJoint( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'link':\n\t\t\t\t\t\tdata.links.push( parseKinematicsLink( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction parseKinematicsJoint( xml ) {\n\n\t\t\tvar data;\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'prismatic':\n\t\t\t\t\tcase 'revolute':\n\t\t\t\t\t\tdata = parseKinematicsJointParameter( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseKinematicsJointParameter( xml, data ) {\n\n\t\t\tvar data = {\n\t\t\t\tsid: xml.getAttribute( 'sid' ),\n\t\t\t\tname: xml.getAttribute( 'name' ) || '',\n\t\t\t\taxis: new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](),\n\t\t\t\tlimits: {\n\t\t\t\t\tmin: 0,\n\t\t\t\t\tmax: 0\n\t\t\t\t},\n\t\t\t\ttype: xml.nodeName,\n\t\t\t\tstatic: false,\n\t\t\t\tzeroPosition: 0,\n\t\t\t\tmiddlePosition: 0\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'axis':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tdata.axis.fromArray( array );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'limits':\n\t\t\t\t\t\tvar max = child.getElementsByTagName( 'max' )[ 0 ];\n\t\t\t\t\t\tvar min = child.getElementsByTagName( 'min' )[ 0 ];\n\n\t\t\t\t\t\tdata.limits.max = parseFloat( max.textContent );\n\t\t\t\t\t\tdata.limits.min = parseFloat( min.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// if min is equal to or greater than max, consider the joint static\n\n\t\t\tif ( data.limits.min >= data.limits.max ) {\n\n\t\t\t\tdata.static = true;\n\n\t\t\t}\n\n\t\t\t// calculate middle position\n\n\t\t\tdata.middlePosition = ( data.limits.min + data.limits.max ) / 2.0;\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseKinematicsLink( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tsid: xml.getAttribute( 'sid' ),\n\t\t\t\tname: xml.getAttribute( 'name' ) || '',\n\t\t\t\tattachments: [],\n\t\t\t\ttransforms: []\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'attachment_full':\n\t\t\t\t\t\tdata.attachments.push( parseKinematicsAttachment( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'matrix':\n\t\t\t\t\tcase 'translate':\n\t\t\t\t\tcase 'rotate':\n\t\t\t\t\t\tdata.transforms.push( parseKinematicsTransform( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseKinematicsAttachment( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tjoint: xml.getAttribute( 'joint' ).split( '/' ).pop(),\n\t\t\t\ttransforms: [],\n\t\t\t\tlinks: []\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'link':\n\t\t\t\t\t\tdata.links.push( parseKinematicsLink( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'matrix':\n\t\t\t\t\tcase 'translate':\n\t\t\t\t\tcase 'rotate':\n\t\t\t\t\t\tdata.transforms.push( parseKinematicsTransform( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseKinematicsTransform( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\ttype: xml.nodeName\n\t\t\t};\n\n\t\t\tvar array = parseFloats( xml.textContent );\n\n\t\t\tswitch ( data.type ) {\n\n\t\t\t\tcase 'matrix':\n\t\t\t\t\tdata.obj = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]();\n\t\t\t\t\tdata.obj.fromArray( array ).transpose();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'translate':\n\t\t\t\t\tdata.obj = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\t\t\t\t\tdata.obj.fromArray( array );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'rotate':\n\t\t\t\t\tdata.obj = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\t\t\t\t\tdata.obj.fromArray( array );\n\t\t\t\t\tdata.angle = _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MathUtils\"].degToRad( array[ 3 ] );\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\t// physics\n\n\t\tfunction parsePhysicsModel( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'name' ) || '',\n\t\t\t\trigidBodies: {}\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'rigid_body':\n\t\t\t\t\t\tdata.rigidBodies[ child.getAttribute( 'name' ) ] = {};\n\t\t\t\t\t\tparsePhysicsRigidBody( child, data.rigidBodies[ child.getAttribute( 'name' ) ] );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.physicsModels[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction parsePhysicsRigidBody( xml, data ) {\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'technique_common':\n\t\t\t\t\t\tparsePhysicsTechniqueCommon( child, data );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction parsePhysicsTechniqueCommon( xml, data ) {\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'inertia':\n\t\t\t\t\t\tdata.inertia = parseFloats( child.textContent );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'mass':\n\t\t\t\t\t\tdata.mass = parseFloats( child.textContent )[ 0 ];\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// scene\n\n\t\tfunction parseKinematicsScene( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tbindJointAxis: []\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'bind_joint_axis':\n\t\t\t\t\t\tdata.bindJointAxis.push( parseKinematicsBindJointAxis( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tlibrary.kinematicsScenes[ parseId( xml.getAttribute( 'url' ) ) ] = data;\n\n\t\t}\n\n\t\tfunction parseKinematicsBindJointAxis( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\ttarget: xml.getAttribute( 'target' ).split( '/' ).pop()\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'axis':\n\t\t\t\t\t\tvar param = child.getElementsByTagName( 'param' )[ 0 ];\n\t\t\t\t\t\tdata.axis = param.textContent;\n\t\t\t\t\t\tvar tmpJointIndex = data.axis.split( 'inst_' ).pop().split( 'axis' )[ 0 ];\n\t\t\t\t\t\tdata.jointIndex = tmpJointIndex.substr( 0, tmpJointIndex.length - 1 );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction buildKinematicsScene( data ) {\n\n\t\t\tif ( data.build !== undefined ) return data.build;\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction getKinematicsScene( id ) {\n\n\t\t\treturn getBuild( library.kinematicsScenes[ id ], buildKinematicsScene );\n\n\t\t}\n\n\t\tfunction setupKinematics() {\n\n\t\t\tvar kinematicsModelId = Object.keys( library.kinematicsModels )[ 0 ];\n\t\t\tvar kinematicsSceneId = Object.keys( library.kinematicsScenes )[ 0 ];\n\t\t\tvar visualSceneId = Object.keys( library.visualScenes )[ 0 ];\n\n\t\t\tif ( kinematicsModelId === undefined || kinematicsSceneId === undefined ) return;\n\n\t\t\tvar kinematicsModel = getKinematicsModel( kinematicsModelId );\n\t\t\tvar kinematicsScene = getKinematicsScene( kinematicsSceneId );\n\t\t\tvar visualScene = getVisualScene( visualSceneId );\n\n\t\t\tvar bindJointAxis = kinematicsScene.bindJointAxis;\n\t\t\tvar jointMap = {};\n\n\t\t\tfor ( var i = 0, l = bindJointAxis.length; i < l; i ++ ) {\n\n\t\t\t\tvar axis = bindJointAxis[ i ];\n\n\t\t\t\t// the result of the following query is an element of type 'translate', 'rotate','scale' or 'matrix'\n\n\t\t\t\tvar targetElement = collada.querySelector( '[sid=\"' + axis.target + '\"]' );\n\n\t\t\t\tif ( targetElement ) {\n\n\t\t\t\t\t// get the parent of the transform element\n\n\t\t\t\t\tvar parentVisualElement = targetElement.parentElement;\n\n\t\t\t\t\t// connect the joint of the kinematics model with the element in the visual scene\n\n\t\t\t\t\tconnect( axis.jointIndex, parentVisualElement );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tfunction connect( jointIndex, visualElement ) {\n\n\t\t\t\tvar visualElementName = visualElement.getAttribute( 'name' );\n\t\t\t\tvar joint = kinematicsModel.joints[ jointIndex ];\n\n\t\t\t\tvisualScene.traverse( function ( object ) {\n\n\t\t\t\t\tif ( object.name === visualElementName ) {\n\n\t\t\t\t\t\tjointMap[ jointIndex ] = {\n\t\t\t\t\t\t\tobject: object,\n\t\t\t\t\t\t\ttransforms: buildTransformList( visualElement ),\n\t\t\t\t\t\t\tjoint: joint,\n\t\t\t\t\t\t\tposition: joint.zeroPosition\n\t\t\t\t\t\t};\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tvar m0 = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]();\n\n\t\t\tkinematics = {\n\n\t\t\t\tjoints: kinematicsModel && kinematicsModel.joints,\n\n\t\t\t\tgetJointValue: function ( jointIndex ) {\n\n\t\t\t\t\tvar jointData = jointMap[ jointIndex ];\n\n\t\t\t\t\tif ( jointData ) {\n\n\t\t\t\t\t\treturn jointData.position;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Joint ' + jointIndex + ' doesn\\'t exist.' );\n\n\t\t\t\t\t}\n\n\t\t\t\t},\n\n\t\t\t\tsetJointValue: function ( jointIndex, value ) {\n\n\t\t\t\t\tvar jointData = jointMap[ jointIndex ];\n\n\t\t\t\t\tif ( jointData ) {\n\n\t\t\t\t\t\tvar joint = jointData.joint;\n\n\t\t\t\t\t\tif ( value > joint.limits.max || value < joint.limits.min ) {\n\n\t\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ').' );\n\n\t\t\t\t\t\t} else if ( joint.static ) {\n\n\t\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Joint ' + jointIndex + ' is static.' );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tvar object = jointData.object;\n\t\t\t\t\t\t\tvar axis = joint.axis;\n\t\t\t\t\t\t\tvar transforms = jointData.transforms;\n\n\t\t\t\t\t\t\tmatrix.identity();\n\n\t\t\t\t\t\t\t// each update, we have to apply all transforms in the correct order\n\n\t\t\t\t\t\t\tfor ( var i = 0; i < transforms.length; i ++ ) {\n\n\t\t\t\t\t\t\t\tvar transform = transforms[ i ];\n\n\t\t\t\t\t\t\t\t// if there is a connection of the transform node with a joint, apply the joint value\n\n\t\t\t\t\t\t\t\tif ( transform.sid && transform.sid.indexOf( jointIndex ) !== - 1 ) {\n\n\t\t\t\t\t\t\t\t\tswitch ( joint.type ) {\n\n\t\t\t\t\t\t\t\t\t\tcase 'revolute':\n\t\t\t\t\t\t\t\t\t\t\tmatrix.multiply( m0.makeRotationAxis( axis, _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MathUtils\"].degToRad( value ) ) );\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase 'prismatic':\n\t\t\t\t\t\t\t\t\t\t\tmatrix.multiply( m0.makeTranslation( axis.x * value, axis.y * value, axis.z * value ) );\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Unknown joint type: ' + joint.type );\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\tswitch ( transform.type ) {\n\n\t\t\t\t\t\t\t\t\t\tcase 'matrix':\n\t\t\t\t\t\t\t\t\t\t\tmatrix.multiply( transform.obj );\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase 'translate':\n\t\t\t\t\t\t\t\t\t\t\tmatrix.multiply( m0.makeTranslation( transform.obj.x, transform.obj.y, transform.obj.z ) );\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase 'scale':\n\t\t\t\t\t\t\t\t\t\t\tmatrix.scale( transform.obj );\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t\tcase 'rotate':\n\t\t\t\t\t\t\t\t\t\t\tmatrix.multiply( m0.makeRotationAxis( transform.obj, transform.angle ) );\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tobject.matrix.copy( matrix );\n\t\t\t\t\t\t\tobject.matrix.decompose( object.position, object.quaternion, object.scale );\n\n\t\t\t\t\t\t\tjointMap[ jointIndex ].position = value;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tconsole.log( 'THREE.ColladaLoader: ' + jointIndex + ' does not exist.' );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t};\n\n\t\t}\n\n\t\tfunction buildTransformList( node ) {\n\n\t\t\tvar transforms = [];\n\n\t\t\tvar xml = collada.querySelector( '[id=\"' + node.id + '\"]' );\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'matrix':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tvar matrix = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]().fromArray( array ).transpose();\n\t\t\t\t\t\ttransforms.push( {\n\t\t\t\t\t\t\tsid: child.getAttribute( 'sid' ),\n\t\t\t\t\t\t\ttype: child.nodeName,\n\t\t\t\t\t\t\tobj: matrix\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'translate':\n\t\t\t\t\tcase 'scale':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tvar vector = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]().fromArray( array );\n\t\t\t\t\t\ttransforms.push( {\n\t\t\t\t\t\t\tsid: child.getAttribute( 'sid' ),\n\t\t\t\t\t\t\ttype: child.nodeName,\n\t\t\t\t\t\t\tobj: vector\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'rotate':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tvar vector = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]().fromArray( array );\n\t\t\t\t\t\tvar angle = _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MathUtils\"].degToRad( array[ 3 ] );\n\t\t\t\t\t\ttransforms.push( {\n\t\t\t\t\t\t\tsid: child.getAttribute( 'sid' ),\n\t\t\t\t\t\t\ttype: child.nodeName,\n\t\t\t\t\t\t\tobj: vector,\n\t\t\t\t\t\t\tangle: angle\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn transforms;\n\n\t\t}\n\n\t\t// nodes\n\n\t\tfunction prepareNodes( xml ) {\n\n\t\t\tvar elements = xml.getElementsByTagName( 'node' );\n\n\t\t\t// ensure all node elements have id attributes\n\n\t\t\tfor ( var i = 0; i < elements.length; i ++ ) {\n\n\t\t\t\tvar element = elements[ i ];\n\n\t\t\t\tif ( element.hasAttribute( 'id' ) === false ) {\n\n\t\t\t\t\telement.setAttribute( 'id', generateId() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar matrix = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]();\n\t\tvar vector = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\n\t\tfunction parseNode( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'name' ) || '',\n\t\t\t\ttype: xml.getAttribute( 'type' ),\n\t\t\t\tid: xml.getAttribute( 'id' ),\n\t\t\t\tsid: xml.getAttribute( 'sid' ),\n\t\t\t\tmatrix: new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"](),\n\t\t\t\tnodes: [],\n\t\t\t\tinstanceCameras: [],\n\t\t\t\tinstanceControllers: [],\n\t\t\t\tinstanceLights: [],\n\t\t\t\tinstanceGeometries: [],\n\t\t\t\tinstanceNodes: [],\n\t\t\t\ttransforms: {}\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tif ( child.nodeType !== 1 ) continue;\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'node':\n\t\t\t\t\t\tdata.nodes.push( child.getAttribute( 'id' ) );\n\t\t\t\t\t\tparseNode( child );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'instance_camera':\n\t\t\t\t\t\tdata.instanceCameras.push( parseId( child.getAttribute( 'url' ) ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'instance_controller':\n\t\t\t\t\t\tdata.instanceControllers.push( parseNodeInstance( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'instance_light':\n\t\t\t\t\t\tdata.instanceLights.push( parseId( child.getAttribute( 'url' ) ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'instance_geometry':\n\t\t\t\t\t\tdata.instanceGeometries.push( parseNodeInstance( child ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'instance_node':\n\t\t\t\t\t\tdata.instanceNodes.push( parseId( child.getAttribute( 'url' ) ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'matrix':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tdata.matrix.multiply( matrix.fromArray( array ).transpose() );\n\t\t\t\t\t\tdata.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'translate':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tvector.fromArray( array );\n\t\t\t\t\t\tdata.matrix.multiply( matrix.makeTranslation( vector.x, vector.y, vector.z ) );\n\t\t\t\t\t\tdata.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'rotate':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tvar angle = _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MathUtils\"].degToRad( array[ 3 ] );\n\t\t\t\t\t\tdata.matrix.multiply( matrix.makeRotationAxis( vector.fromArray( array ), angle ) );\n\t\t\t\t\t\tdata.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'scale':\n\t\t\t\t\t\tvar array = parseFloats( child.textContent );\n\t\t\t\t\t\tdata.matrix.scale( vector.fromArray( array ) );\n\t\t\t\t\t\tdata.transforms[ child.getAttribute( 'sid' ) ] = child.nodeName;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'extra':\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tconsole.log( child );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( hasNode( data.id ) ) {\n\n\t\t\t\tconsole.warn( 'THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.', data.id );\n\n\t\t\t} else {\n\n\t\t\t\tlibrary.nodes[ data.id ] = data;\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction parseNodeInstance( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tid: parseId( xml.getAttribute( 'url' ) ),\n\t\t\t\tmaterials: {},\n\t\t\t\tskeletons: []\n\t\t\t};\n\n\t\t\tfor ( var i = 0; i < xml.childNodes.length; i ++ ) {\n\n\t\t\t\tvar child = xml.childNodes[ i ];\n\n\t\t\t\tswitch ( child.nodeName ) {\n\n\t\t\t\t\tcase 'bind_material':\n\t\t\t\t\t\tvar instances = child.getElementsByTagName( 'instance_material' );\n\n\t\t\t\t\t\tfor ( var j = 0; j < instances.length; j ++ ) {\n\n\t\t\t\t\t\t\tvar instance = instances[ j ];\n\t\t\t\t\t\t\tvar symbol = instance.getAttribute( 'symbol' );\n\t\t\t\t\t\t\tvar target = instance.getAttribute( 'target' );\n\n\t\t\t\t\t\t\tdata.materials[ symbol ] = parseId( target );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'skeleton':\n\t\t\t\t\t\tdata.skeletons.push( parseId( child.textContent ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tfunction buildSkeleton( skeletons, joints ) {\n\n\t\t\tvar boneData = [];\n\t\t\tvar sortedBoneData = [];\n\n\t\t\tvar i, j, data;\n\n\t\t\t// a skeleton can have multiple root bones. collada expresses this\n\t\t\t// situtation with multiple \"skeleton\" tags per controller instance\n\n\t\t\tfor ( i = 0; i < skeletons.length; i ++ ) {\n\n\t\t\t\tvar skeleton = skeletons[ i ];\n\n\t\t\t\tvar root;\n\n\t\t\t\tif ( hasNode( skeleton ) ) {\n\n\t\t\t\t\troot = getNode( skeleton );\n\t\t\t\t\tbuildBoneHierarchy( root, joints, boneData );\n\n\t\t\t\t} else if ( hasVisualScene( skeleton ) ) {\n\n\t\t\t\t\t// handle case where the skeleton refers to the visual scene (#13335)\n\n\t\t\t\t\tvar visualScene = library.visualScenes[ skeleton ];\n\t\t\t\t\tvar children = visualScene.children;\n\n\t\t\t\t\tfor ( var j = 0; j < children.length; j ++ ) {\n\n\t\t\t\t\t\tvar child = children[ j ];\n\n\t\t\t\t\t\tif ( child.type === 'JOINT' ) {\n\n\t\t\t\t\t\t\tvar root = getNode( child.id );\n\t\t\t\t\t\t\tbuildBoneHierarchy( root, joints, boneData );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( 'THREE.ColladaLoader: Unable to find root bone of skeleton with ID:', skeleton );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// sort bone data (the order is defined in the corresponding controller)\n\n\t\t\tfor ( i = 0; i < joints.length; i ++ ) {\n\n\t\t\t\tfor ( j = 0; j < boneData.length; j ++ ) {\n\n\t\t\t\t\tdata = boneData[ j ];\n\n\t\t\t\t\tif ( data.bone.name === joints[ i ].name ) {\n\n\t\t\t\t\t\tsortedBoneData[ i ] = data;\n\t\t\t\t\t\tdata.processed = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// add unprocessed bone data at the end of the list\n\n\t\t\tfor ( i = 0; i < boneData.length; i ++ ) {\n\n\t\t\t\tdata = boneData[ i ];\n\n\t\t\t\tif ( data.processed === false ) {\n\n\t\t\t\t\tsortedBoneData.push( data );\n\t\t\t\t\tdata.processed = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// setup arrays for skeleton creation\n\n\t\t\tvar bones = [];\n\t\t\tvar boneInverses = [];\n\n\t\t\tfor ( i = 0; i < sortedBoneData.length; i ++ ) {\n\n\t\t\t\tdata = sortedBoneData[ i ];\n\n\t\t\t\tbones.push( data.bone );\n\t\t\t\tboneInverses.push( data.boneInverse );\n\n\t\t\t}\n\n\t\t\treturn new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Skeleton\"]( bones, boneInverses );\n\n\t\t}\n\n\t\tfunction buildBoneHierarchy( root, joints, boneData ) {\n\n\t\t\t// setup bone data from visual scene\n\n\t\t\troot.traverse( function ( object ) {\n\n\t\t\t\tif ( object.isBone === true ) {\n\n\t\t\t\t\tvar boneInverse;\n\n\t\t\t\t\t// retrieve the boneInverse from the controller data\n\n\t\t\t\t\tfor ( var i = 0; i < joints.length; i ++ ) {\n\n\t\t\t\t\t\tvar joint = joints[ i ];\n\n\t\t\t\t\t\tif ( joint.name === object.name ) {\n\n\t\t\t\t\t\t\tboneInverse = joint.boneInverse;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( boneInverse === undefined ) {\n\n\t\t\t\t\t\t// Unfortunately, there can be joints in the visual scene that are not part of the\n\t\t\t\t\t\t// corresponding controller. In this case, we have to create a dummy boneInverse matrix\n\t\t\t\t\t\t// for the respective bone. This bone won't affect any vertices, because there are no skin indices\n\t\t\t\t\t\t// and weights defined for it. But we still have to add the bone to the sorted bone list in order to\n\t\t\t\t\t\t// ensure a correct animation of the model.\n\n\t\t\t\t\t\tboneInverse = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]();\n\n\t\t\t\t\t}\n\n\t\t\t\t\tboneData.push( { bone: object, boneInverse: boneInverse, processed: false } );\n\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t}\n\n\t\tfunction buildNode( data ) {\n\n\t\t\tvar objects = [];\n\n\t\t\tvar matrix = data.matrix;\n\t\t\tvar nodes = data.nodes;\n\t\t\tvar type = data.type;\n\t\t\tvar instanceCameras = data.instanceCameras;\n\t\t\tvar instanceControllers = data.instanceControllers;\n\t\t\tvar instanceLights = data.instanceLights;\n\t\t\tvar instanceGeometries = data.instanceGeometries;\n\t\t\tvar instanceNodes = data.instanceNodes;\n\n\t\t\t// nodes\n\n\t\t\tfor ( var i = 0, l = nodes.length; i < l; i ++ ) {\n\n\t\t\t\tobjects.push( getNode( nodes[ i ] ) );\n\n\t\t\t}\n\n\t\t\t// instance cameras\n\n\t\t\tfor ( var i = 0, l = instanceCameras.length; i < l; i ++ ) {\n\n\t\t\t\tvar instanceCamera = getCamera( instanceCameras[ i ] );\n\n\t\t\t\tif ( instanceCamera !== null ) {\n\n\t\t\t\t\tobjects.push( instanceCamera.clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// instance controllers\n\n\t\t\tfor ( var i = 0, l = instanceControllers.length; i < l; i ++ ) {\n\n\t\t\t\tvar instance = instanceControllers[ i ];\n\t\t\t\tvar controller = getController( instance.id );\n\t\t\t\tvar geometries = getGeometry( controller.id );\n\t\t\t\tvar newObjects = buildObjects( geometries, instance.materials );\n\n\t\t\t\tvar skeletons = instance.skeletons;\n\t\t\t\tvar joints = controller.skin.joints;\n\n\t\t\t\tvar skeleton = buildSkeleton( skeletons, joints );\n\n\t\t\t\tfor ( var j = 0, jl = newObjects.length; j < jl; j ++ ) {\n\n\t\t\t\t\tvar object = newObjects[ j ];\n\n\t\t\t\t\tif ( object.isSkinnedMesh ) {\n\n\t\t\t\t\t\tobject.bind( skeleton, controller.skin.bindMatrix );\n\t\t\t\t\t\tobject.normalizeSkinWeights();\n\n\t\t\t\t\t}\n\n\t\t\t\t\tobjects.push( object );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// instance lights\n\n\t\t\tfor ( var i = 0, l = instanceLights.length; i < l; i ++ ) {\n\n\t\t\t\tvar instanceLight = getLight( instanceLights[ i ] );\n\n\t\t\t\tif ( instanceLight !== null ) {\n\n\t\t\t\t\tobjects.push( instanceLight.clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// instance geometries\n\n\t\t\tfor ( var i = 0, l = instanceGeometries.length; i < l; i ++ ) {\n\n\t\t\t\tvar instance = instanceGeometries[ i ];\n\n\t\t\t\t// a single geometry instance in collada can lead to multiple object3Ds.\n\t\t\t\t// this is the case when primitives are combined like triangles and lines\n\n\t\t\t\tvar geometries = getGeometry( instance.id );\n\t\t\t\tvar newObjects = buildObjects( geometries, instance.materials );\n\n\t\t\t\tfor ( var j = 0, jl = newObjects.length; j < jl; j ++ ) {\n\n\t\t\t\t\tobjects.push( newObjects[ j ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// instance nodes\n\n\t\t\tfor ( var i = 0, l = instanceNodes.length; i < l; i ++ ) {\n\n\t\t\t\tobjects.push( getNode( instanceNodes[ i ] ).clone() );\n\n\t\t\t}\n\n\t\t\tvar object;\n\n\t\t\tif ( nodes.length === 0 && objects.length === 1 ) {\n\n\t\t\t\tobject = objects[ 0 ];\n\n\t\t\t} else {\n\n\t\t\t\tobject = ( type === 'JOINT' ) ? new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Bone\"]() : new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Group\"]();\n\n\t\t\t\tfor ( var i = 0; i < objects.length; i ++ ) {\n\n\t\t\t\t\tobject.add( objects[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tobject.name = ( type === 'JOINT' ) ? data.sid : data.name;\n\t\t\tobject.matrix.copy( matrix );\n\t\t\tobject.matrix.decompose( object.position, object.quaternion, object.scale );\n\n\t\t\treturn object;\n\n\t\t}\n\n\t\tvar fallbackMaterial = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MeshBasicMaterial\"]( { color: 0xff00ff } );\n\n\t\tfunction resolveMaterialBinding( keys, instanceMaterials ) {\n\n\t\t\tvar materials = [];\n\n\t\t\tfor ( var i = 0, l = keys.length; i < l; i ++ ) {\n\n\t\t\t\tvar id = instanceMaterials[ keys[ i ] ];\n\n\t\t\t\tif ( id === undefined ) {\n\n\t\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Material with key %s not found. Apply fallback material.', keys[ i ] );\n\t\t\t\t\tmaterials.push( fallbackMaterial );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tmaterials.push( getMaterial( id ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn materials;\n\n\t\t}\n\n\t\tfunction buildObjects( geometries, instanceMaterials ) {\n\n\t\t\tvar objects = [];\n\n\t\t\tfor ( var type in geometries ) {\n\n\t\t\t\tvar geometry = geometries[ type ];\n\n\t\t\t\tvar materials = resolveMaterialBinding( geometry.materialKeys, instanceMaterials );\n\n\t\t\t\t// handle case if no materials are defined\n\n\t\t\t\tif ( materials.length === 0 ) {\n\n\t\t\t\t\tif ( type === 'lines' || type === 'linestrips' ) {\n\n\t\t\t\t\t\tmaterials.push( new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LineBasicMaterial\"]() );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tmaterials.push( new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MeshPhongMaterial\"]() );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// regard skinning\n\n\t\t\t\tvar skinning = ( geometry.data.attributes.skinIndex !== undefined );\n\n\t\t\t\tif ( skinning ) {\n\n\t\t\t\t\tfor ( var i = 0, l = materials.length; i < l; i ++ ) {\n\n\t\t\t\t\t\tmaterials[ i ].skinning = true;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// choose between a single or multi materials (material array)\n\n\t\t\t\tvar material = ( materials.length === 1 ) ? materials[ 0 ] : materials;\n\n\t\t\t\t// now create a specific 3D object\n\n\t\t\t\tvar object;\n\n\t\t\t\tswitch ( type ) {\n\n\t\t\t\t\tcase 'lines':\n\t\t\t\t\t\tobject = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LineSegments\"]( geometry.data, material );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'linestrips':\n\t\t\t\t\t\tobject = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Line\"]( geometry.data, material );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'triangles':\n\t\t\t\t\tcase 'polylist':\n\t\t\t\t\t\tif ( skinning ) {\n\n\t\t\t\t\t\t\tobject = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"SkinnedMesh\"]( geometry.data, material );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tobject = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Mesh\"]( geometry.data, material );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tobjects.push( object );\n\n\t\t\t}\n\n\t\t\treturn objects;\n\n\t\t}\n\n\t\tfunction hasNode( id ) {\n\n\t\t\treturn library.nodes[ id ] !== undefined;\n\n\t\t}\n\n\t\tfunction getNode( id ) {\n\n\t\t\treturn getBuild( library.nodes[ id ], buildNode );\n\n\t\t}\n\n\t\t// visual scenes\n\n\t\tfunction parseVisualScene( xml ) {\n\n\t\t\tvar data = {\n\t\t\t\tname: xml.getAttribute( 'name' ),\n\t\t\t\tchildren: []\n\t\t\t};\n\n\t\t\tprepareNodes( xml );\n\n\t\t\tvar elements = getElementsByTagName( xml, 'node' );\n\n\t\t\tfor ( var i = 0; i < elements.length; i ++ ) {\n\n\t\t\t\tdata.children.push( parseNode( elements[ i ] ) );\n\n\t\t\t}\n\n\t\t\tlibrary.visualScenes[ xml.getAttribute( 'id' ) ] = data;\n\n\t\t}\n\n\t\tfunction buildVisualScene( data ) {\n\n\t\t\tvar group = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Group\"]();\n\t\t\tgroup.name = data.name;\n\n\t\t\tvar children = data.children;\n\n\t\t\tfor ( var i = 0; i < children.length; i ++ ) {\n\n\t\t\t\tvar child = children[ i ];\n\n\t\t\t\tgroup.add( getNode( child.id ) );\n\n\t\t\t}\n\n\t\t\treturn group;\n\n\t\t}\n\n\t\tfunction hasVisualScene( id ) {\n\n\t\t\treturn library.visualScenes[ id ] !== undefined;\n\n\t\t}\n\n\t\tfunction getVisualScene( id ) {\n\n\t\t\treturn getBuild( library.visualScenes[ id ], buildVisualScene );\n\n\t\t}\n\n\t\t// scenes\n\n\t\tfunction parseScene( xml ) {\n\n\t\t\tvar instance = getElementsByTagName( xml, 'instance_visual_scene' )[ 0 ];\n\t\t\treturn getVisualScene( parseId( instance.getAttribute( 'url' ) ) );\n\n\t\t}\n\n\t\tfunction setupAnimations() {\n\n\t\t\tvar clips = library.clips;\n\n\t\t\tif ( isEmpty( clips ) === true ) {\n\n\t\t\t\tif ( isEmpty( library.animations ) === false ) {\n\n\t\t\t\t\t// if there are animations but no clips, we create a default clip for playback\n\n\t\t\t\t\tvar tracks = [];\n\n\t\t\t\t\tfor ( var id in library.animations ) {\n\n\t\t\t\t\t\tvar animationTracks = getAnimation( id );\n\n\t\t\t\t\t\tfor ( var i = 0, l = animationTracks.length; i < l; i ++ ) {\n\n\t\t\t\t\t\t\ttracks.push( animationTracks[ i ] );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tanimations.push( new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"AnimationClip\"]( 'default', - 1, tracks ) );\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tfor ( var id in clips ) {\n\n\t\t\t\t\tanimations.push( getAnimationClip( id ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// convert the parser error element into text with each child elements text\n\t\t// separated by new lines.\n\n\t\tfunction parserErrorToText( parserError ) {\n\n\t\t\tvar result = '';\n\t\t\tvar stack = [ parserError ];\n\n\t\t\twhile ( stack.length ) {\n\n\t\t\t\tvar node = stack.shift();\n\n\t\t\t\tif ( node.nodeType === Node.TEXT_NODE ) {\n\n\t\t\t\t\tresult += node.textContent;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tresult += '\\n';\n\t\t\t\t\tstack.push.apply( stack, node.childNodes );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn result.trim();\n\n\t\t}\n\n\t\tif ( text.length === 0 ) {\n\n\t\t\treturn { scene: new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Scene\"]() };\n\n\t\t}\n\n\t\tvar xml = new DOMParser().parseFromString( text, 'application/xml' );\n\n\t\tvar collada = getElementsByTagName( xml, 'COLLADA' )[ 0 ];\n\n\t\tvar parserError = xml.getElementsByTagName( 'parsererror' )[ 0 ];\n\t\tif ( parserError !== undefined ) {\n\n\t\t\t// Chrome will return parser error with a div in it\n\n\t\t\tvar errorElement = getElementsByTagName( parserError, 'div' )[ 0 ];\n\t\t\tvar errorText;\n\n\t\t\tif ( errorElement ) {\n\n\t\t\t\terrorText = errorElement.textContent;\n\n\t\t\t} else {\n\n\t\t\t\terrorText = parserErrorToText( parserError );\n\n\t\t\t}\n\n\t\t\tconsole.error( 'THREE.ColladaLoader: Failed to parse collada file.\\n', errorText );\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// metadata\n\n\t\tvar version = collada.getAttribute( 'version' );\n\t\tconsole.log( 'THREE.ColladaLoader: File version', version );\n\n\t\tvar asset = parseAsset( getElementsByTagName( collada, 'asset' )[ 0 ] );\n\t\tvar textureLoader = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"TextureLoader\"]( this.manager );\n\t\ttextureLoader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );\n\n\t\tvar tgaLoader;\n\n\t\tif ( _loaders_TGALoader_js__WEBPACK_IMPORTED_MODULE_1__[\"TGALoader\"] ) {\n\n\t\t\ttgaLoader = new _loaders_TGALoader_js__WEBPACK_IMPORTED_MODULE_1__[\"TGALoader\"]( this.manager );\n\t\t\ttgaLoader.setPath( this.resourcePath || path );\n\n\t\t}\n\n\t\t//\n\n\t\tvar animations = [];\n\t\tvar kinematics = {};\n\t\tvar count = 0;\n\n\t\t//\n\n\t\tvar library = {\n\t\t\tanimations: {},\n\t\t\tclips: {},\n\t\t\tcontrollers: {},\n\t\t\timages: {},\n\t\t\teffects: {},\n\t\t\tmaterials: {},\n\t\t\tcameras: {},\n\t\t\tlights: {},\n\t\t\tgeometries: {},\n\t\t\tnodes: {},\n\t\t\tvisualScenes: {},\n\t\t\tkinematicsModels: {},\n\t\t\tphysicsModels: {},\n\t\t\tkinematicsScenes: {}\n\t\t};\n\n\t\tparseLibrary( collada, 'library_animations', 'animation', parseAnimation );\n\t\tparseLibrary( collada, 'library_animation_clips', 'animation_clip', parseAnimationClip );\n\t\tparseLibrary( collada, 'library_controllers', 'controller', parseController );\n\t\tparseLibrary( collada, 'library_images', 'image', parseImage );\n\t\tparseLibrary( collada, 'library_effects', 'effect', parseEffect );\n\t\tparseLibrary( collada, 'library_materials', 'material', parseMaterial );\n\t\tparseLibrary( collada, 'library_cameras', 'camera', parseCamera );\n\t\tparseLibrary( collada, 'library_lights', 'light', parseLight );\n\t\tparseLibrary( collada, 'library_geometries', 'geometry', parseGeometry );\n\t\tparseLibrary( collada, 'library_nodes', 'node', parseNode );\n\t\tparseLibrary( collada, 'library_visual_scenes', 'visual_scene', parseVisualScene );\n\t\tparseLibrary( collada, 'library_kinematics_models', 'kinematics_model', parseKinematicsModel );\n\t\tparseLibrary( collada, 'library_physics_models', 'physics_model', parsePhysicsModel );\n\t\tparseLibrary( collada, 'scene', 'instance_kinematics_scene', parseKinematicsScene );\n\n\t\tbuildLibrary( library.animations, buildAnimation );\n\t\tbuildLibrary( library.clips, buildAnimationClip );\n\t\tbuildLibrary( library.controllers, buildController );\n\t\tbuildLibrary( library.images, buildImage );\n\t\tbuildLibrary( library.effects, buildEffect );\n\t\tbuildLibrary( library.materials, buildMaterial );\n\t\tbuildLibrary( library.cameras, buildCamera );\n\t\tbuildLibrary( library.lights, buildLight );\n\t\tbuildLibrary( library.geometries, buildGeometry );\n\t\tbuildLibrary( library.visualScenes, buildVisualScene );\n\n\t\tsetupAnimations();\n\t\tsetupKinematics();\n\n\t\tvar scene = parseScene( getElementsByTagName( collada, 'scene' )[ 0 ] );\n\t\tscene.animations = animations;\n\n\t\tif ( asset.upAxis === 'Z_UP' ) {\n\n\t\t\tscene.quaternion.setFromEuler( new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Euler\"]( - Math.PI / 2, 0, 0 ) );\n\n\t\t}\n\n\t\tscene.scale.multiplyScalar( asset.unit );\n\n\t\treturn {\n\t\t\tget animations() {\n\n\t\t\t\tconsole.warn( 'THREE.ColladaLoader: Please access animations over scene.animations now.' );\n\t\t\t\treturn animations;\n\n\t\t\t},\n\t\t\tkinematics: kinematics,\n\t\t\tlibrary: library,\n\t\t\tscene: scene\n\t\t};\n\n\t}\n\n} );\n\n\n\n\n//# sourceURL=webpack://LithoSphere/./node_modules/three/examples/jsm/loaders/ColladaLoader.js?"); + +/***/ }), + /***/ "./node_modules/three/examples/jsm/loaders/GLTFLoader.js": /*!***************************************************************!*\ !*** ./node_modules/three/examples/jsm/loaders/GLTFLoader.js ***! @@ -1724,6 +1736,42 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /***/ }), +/***/ "./node_modules/three/examples/jsm/loaders/MTLLoader.js": +/*!**************************************************************!*\ + !*** ./node_modules/three/examples/jsm/loaders/MTLLoader.js ***! + \**************************************************************/ +/*! exports provided: MTLLoader */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MTLLoader\", function() { return MTLLoader; });\n/* harmony import */ var _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../build/three.module.js */ \"./node_modules/three/build/three.module.js\");\n\n\n/**\n * Loads a Wavefront .mtl file specifying materials\n */\n\nvar MTLLoader = function ( manager ) {\n\n\t_build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].call( this, manager );\n\n};\n\nMTLLoader.prototype = Object.assign( Object.create( _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].prototype ), {\n\n\tconstructor: MTLLoader,\n\n\t/**\n\t * Loads and parses a MTL asset from a URL.\n\t *\n\t * @param {String} url - URL to the MTL file.\n\t * @param {Function} [onLoad] - Callback invoked with the loaded object.\n\t * @param {Function} [onProgress] - Callback for download progress.\n\t * @param {Function} [onError] - Callback for download errors.\n\t *\n\t * @see setPath setResourcePath\n\t *\n\t * @note In order for relative texture references to resolve correctly\n\t * you must call setResourcePath() explicitly prior to load.\n\t */\n\tload: function ( url, onLoad, onProgress, onError ) {\n\n\t\tvar scope = this;\n\n\t\tvar path = ( this.path === '' ) ? _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LoaderUtils\"].extractUrlBase( url ) : this.path;\n\n\t\tvar loader = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"FileLoader\"]( this.manager );\n\t\tloader.setPath( this.path );\n\t\tloader.setRequestHeader( this.requestHeader );\n\t\tloader.setWithCredentials( this.withCredentials );\n\t\tloader.load( url, function ( text ) {\n\n\t\t\ttry {\n\n\t\t\t\tonLoad( scope.parse( text, path ) );\n\n\t\t\t} catch ( e ) {\n\n\t\t\t\tif ( onError ) {\n\n\t\t\t\t\tonError( e );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( e );\n\n\t\t\t\t}\n\n\t\t\t\tscope.manager.itemError( url );\n\n\t\t\t}\n\n\t\t}, onProgress, onError );\n\n\t},\n\n\tsetMaterialOptions: function ( value ) {\n\n\t\tthis.materialOptions = value;\n\t\treturn this;\n\n\t},\n\n\t/**\n\t * Parses a MTL file.\n\t *\n\t * @param {String} text - Content of MTL file\n\t * @return {MTLLoader.MaterialCreator}\n\t *\n\t * @see setPath setResourcePath\n\t *\n\t * @note In order for relative texture references to resolve correctly\n\t * you must call setResourcePath() explicitly prior to parse.\n\t */\n\tparse: function ( text, path ) {\n\n\t\tvar lines = text.split( '\\n' );\n\t\tvar info = {};\n\t\tvar delimiter_pattern = /\\s+/;\n\t\tvar materialsInfo = {};\n\n\t\tfor ( var i = 0; i < lines.length; i ++ ) {\n\n\t\t\tvar line = lines[ i ];\n\t\t\tline = line.trim();\n\n\t\t\tif ( line.length === 0 || line.charAt( 0 ) === '#' ) {\n\n\t\t\t\t// Blank line or comment ignore\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\tvar pos = line.indexOf( ' ' );\n\n\t\t\tvar key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;\n\t\t\tkey = key.toLowerCase();\n\n\t\t\tvar value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';\n\t\t\tvalue = value.trim();\n\n\t\t\tif ( key === 'newmtl' ) {\n\n\t\t\t\t// New material\n\n\t\t\t\tinfo = { name: value };\n\t\t\t\tmaterialsInfo[ value ] = info;\n\n\t\t\t} else {\n\n\t\t\t\tif ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) {\n\n\t\t\t\t\tvar ss = value.split( delimiter_pattern, 3 );\n\t\t\t\t\tinfo[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];\n\n\t\t\t\t} else {\n\n\t\t\t\t\tinfo[ key ] = value;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar materialCreator = new MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions );\n\t\tmaterialCreator.setCrossOrigin( this.crossOrigin );\n\t\tmaterialCreator.setManager( this.manager );\n\t\tmaterialCreator.setMaterials( materialsInfo );\n\t\treturn materialCreator;\n\n\t}\n\n} );\n\n/**\n * Create a new MTLLoader.MaterialCreator\n * @param baseUrl - Url relative to which textures are loaded\n * @param options - Set of options on how to construct the materials\n * side: Which side to apply the material\n * FrontSide (default), THREE.BackSide, THREE.DoubleSide\n * wrap: What type of wrapping to apply for textures\n * RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping\n * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255\n * Default: false, assumed to be already normalized\n * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's\n * Default: false\n * @constructor\n */\n\nMTLLoader.MaterialCreator = function ( baseUrl, options ) {\n\n\tthis.baseUrl = baseUrl || '';\n\tthis.options = options;\n\tthis.materialsInfo = {};\n\tthis.materials = {};\n\tthis.materialsArray = [];\n\tthis.nameLookup = {};\n\n\tthis.side = ( this.options && this.options.side ) ? this.options.side : _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"FrontSide\"];\n\tthis.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"RepeatWrapping\"];\n\n};\n\nMTLLoader.MaterialCreator.prototype = {\n\n\tconstructor: MTLLoader.MaterialCreator,\n\n\tcrossOrigin: 'anonymous',\n\n\tsetCrossOrigin: function ( value ) {\n\n\t\tthis.crossOrigin = value;\n\t\treturn this;\n\n\t},\n\n\tsetManager: function ( value ) {\n\n\t\tthis.manager = value;\n\n\t},\n\n\tsetMaterials: function ( materialsInfo ) {\n\n\t\tthis.materialsInfo = this.convert( materialsInfo );\n\t\tthis.materials = {};\n\t\tthis.materialsArray = [];\n\t\tthis.nameLookup = {};\n\n\t},\n\n\tconvert: function ( materialsInfo ) {\n\n\t\tif ( ! this.options ) return materialsInfo;\n\n\t\tvar converted = {};\n\n\t\tfor ( var mn in materialsInfo ) {\n\n\t\t\t// Convert materials info into normalized form based on options\n\n\t\t\tvar mat = materialsInfo[ mn ];\n\n\t\t\tvar covmat = {};\n\n\t\t\tconverted[ mn ] = covmat;\n\n\t\t\tfor ( var prop in mat ) {\n\n\t\t\t\tvar save = true;\n\t\t\t\tvar value = mat[ prop ];\n\t\t\t\tvar lprop = prop.toLowerCase();\n\n\t\t\t\tswitch ( lprop ) {\n\n\t\t\t\t\tcase 'kd':\n\t\t\t\t\tcase 'ka':\n\t\t\t\t\tcase 'ks':\n\n\t\t\t\t\t\t// Diffuse color (color under white light) using RGB values\n\n\t\t\t\t\t\tif ( this.options && this.options.normalizeRGB ) {\n\n\t\t\t\t\t\t\tvalue = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( this.options && this.options.ignoreZeroRGBs ) {\n\n\t\t\t\t\t\t\tif ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {\n\n\t\t\t\t\t\t\t\t// ignore\n\n\t\t\t\t\t\t\t\tsave = false;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tif ( save ) {\n\n\t\t\t\t\tcovmat[ lprop ] = value;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn converted;\n\n\t},\n\n\tpreload: function () {\n\n\t\tfor ( var mn in this.materialsInfo ) {\n\n\t\t\tthis.create( mn );\n\n\t\t}\n\n\t},\n\n\tgetIndex: function ( materialName ) {\n\n\t\treturn this.nameLookup[ materialName ];\n\n\t},\n\n\tgetAsArray: function () {\n\n\t\tvar index = 0;\n\n\t\tfor ( var mn in this.materialsInfo ) {\n\n\t\t\tthis.materialsArray[ index ] = this.create( mn );\n\t\t\tthis.nameLookup[ mn ] = index;\n\t\t\tindex ++;\n\n\t\t}\n\n\t\treturn this.materialsArray;\n\n\t},\n\n\tcreate: function ( materialName ) {\n\n\t\tif ( this.materials[ materialName ] === undefined ) {\n\n\t\t\tthis.createMaterial_( materialName );\n\n\t\t}\n\n\t\treturn this.materials[ materialName ];\n\n\t},\n\n\tcreateMaterial_: function ( materialName ) {\n\n\t\t// Create material\n\n\t\tvar scope = this;\n\t\tvar mat = this.materialsInfo[ materialName ];\n\t\tvar params = {\n\n\t\t\tname: materialName,\n\t\t\tside: this.side\n\n\t\t};\n\n\t\tfunction resolveURL( baseUrl, url ) {\n\n\t\t\tif ( typeof url !== 'string' || url === '' )\n\t\t\t\treturn '';\n\n\t\t\t// Absolute URL\n\t\t\tif ( /^https?:\\/\\//i.test( url ) ) return url;\n\n\t\t\treturn baseUrl + url;\n\n\t\t}\n\n\t\tfunction setMapForType( mapType, value ) {\n\n\t\t\tif ( params[ mapType ] ) return; // Keep the first encountered texture\n\n\t\t\tvar texParams = scope.getTextureParams( value, params );\n\t\t\tvar map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );\n\n\t\t\tmap.repeat.copy( texParams.scale );\n\t\t\tmap.offset.copy( texParams.offset );\n\n\t\t\tmap.wrapS = scope.wrap;\n\t\t\tmap.wrapT = scope.wrap;\n\n\t\t\tparams[ mapType ] = map;\n\n\t\t}\n\n\t\tfor ( var prop in mat ) {\n\n\t\t\tvar value = mat[ prop ];\n\t\t\tvar n;\n\n\t\t\tif ( value === '' ) continue;\n\n\t\t\tswitch ( prop.toLowerCase() ) {\n\n\t\t\t\t// Ns is material specular exponent\n\n\t\t\t\tcase 'kd':\n\n\t\t\t\t\t// Diffuse color (color under white light) using RGB values\n\n\t\t\t\t\tparams.color = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Color\"]().fromArray( value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'ks':\n\n\t\t\t\t\t// Specular color (color when light is reflected from shiny surface) using RGB values\n\t\t\t\t\tparams.specular = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Color\"]().fromArray( value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'ke':\n\n\t\t\t\t\t// Emissive using RGB values\n\t\t\t\t\tparams.emissive = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Color\"]().fromArray( value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'map_kd':\n\n\t\t\t\t\t// Diffuse texture map\n\n\t\t\t\t\tsetMapForType( 'map', value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'map_ks':\n\n\t\t\t\t\t// Specular map\n\n\t\t\t\t\tsetMapForType( 'specularMap', value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'map_ke':\n\n\t\t\t\t\t// Emissive map\n\n\t\t\t\t\tsetMapForType( 'emissiveMap', value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'norm':\n\n\t\t\t\t\tsetMapForType( 'normalMap', value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'map_bump':\n\t\t\t\tcase 'bump':\n\n\t\t\t\t\t// Bump texture map\n\n\t\t\t\t\tsetMapForType( 'bumpMap', value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'map_d':\n\n\t\t\t\t\t// Alpha map\n\n\t\t\t\t\tsetMapForType( 'alphaMap', value );\n\t\t\t\t\tparams.transparent = true;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'ns':\n\n\t\t\t\t\t// The specular exponent (defines the focus of the specular highlight)\n\t\t\t\t\t// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.\n\n\t\t\t\t\tparams.shininess = parseFloat( value );\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'd':\n\t\t\t\t\tn = parseFloat( value );\n\n\t\t\t\t\tif ( n < 1 ) {\n\n\t\t\t\t\t\tparams.opacity = n;\n\t\t\t\t\t\tparams.transparent = true;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'tr':\n\t\t\t\t\tn = parseFloat( value );\n\n\t\t\t\t\tif ( this.options && this.options.invertTrProperty ) n = 1 - n;\n\n\t\t\t\t\tif ( n > 0 ) {\n\n\t\t\t\t\t\tparams.opacity = 1 - n;\n\t\t\t\t\t\tparams.transparent = true;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.materials[ materialName ] = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MeshPhongMaterial\"]( params );\n\t\treturn this.materials[ materialName ];\n\n\t},\n\n\tgetTextureParams: function ( value, matParams ) {\n\n\t\tvar texParams = {\n\n\t\t\tscale: new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector2\"]( 1, 1 ),\n\t\t\toffset: new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector2\"]( 0, 0 )\n\n\t\t };\n\n\t\tvar items = value.split( /\\s+/ );\n\t\tvar pos;\n\n\t\tpos = items.indexOf( '-bm' );\n\n\t\tif ( pos >= 0 ) {\n\n\t\t\tmatParams.bumpScale = parseFloat( items[ pos + 1 ] );\n\t\t\titems.splice( pos, 2 );\n\n\t\t}\n\n\t\tpos = items.indexOf( '-s' );\n\n\t\tif ( pos >= 0 ) {\n\n\t\t\ttexParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );\n\t\t\titems.splice( pos, 4 ); // we expect 3 parameters here!\n\n\t\t}\n\n\t\tpos = items.indexOf( '-o' );\n\n\t\tif ( pos >= 0 ) {\n\n\t\t\ttexParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );\n\t\t\titems.splice( pos, 4 ); // we expect 3 parameters here!\n\n\t\t}\n\n\t\ttexParams.url = items.join( ' ' ).trim();\n\t\treturn texParams;\n\n\t},\n\n\tloadTexture: function ( url, mapping, onLoad, onProgress, onError ) {\n\n\t\tvar texture;\n\t\tvar manager = ( this.manager !== undefined ) ? this.manager : _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"DefaultLoadingManager\"];\n\t\tvar loader = manager.getHandler( url );\n\n\t\tif ( loader === null ) {\n\n\t\t\tloader = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"TextureLoader\"]( manager );\n\n\t\t}\n\n\t\tif ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );\n\t\ttexture = loader.load( url, onLoad, onProgress, onError );\n\n\t\tif ( mapping !== undefined ) texture.mapping = mapping;\n\n\t\treturn texture;\n\n\t}\n\n};\n\n\n\n\n//# sourceURL=webpack://LithoSphere/./node_modules/three/examples/jsm/loaders/MTLLoader.js?"); + +/***/ }), + +/***/ "./node_modules/three/examples/jsm/loaders/OBJLoader.js": +/*!**************************************************************!*\ + !*** ./node_modules/three/examples/jsm/loaders/OBJLoader.js ***! + \**************************************************************/ +/*! exports provided: OBJLoader */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"OBJLoader\", function() { return OBJLoader; });\n/* harmony import */ var _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../build/three.module.js */ \"./node_modules/three/build/three.module.js\");\n\n\nvar OBJLoader = ( function () {\n\n\t// o object_name | g group_name\n\tvar object_pattern = /^[og]\\s*(.+)?/;\n\t// mtllib file_reference\n\tvar material_library_pattern = /^mtllib /;\n\t// usemtl material_name\n\tvar material_use_pattern = /^usemtl /;\n\t// usemap map_name\n\tvar map_use_pattern = /^usemap /;\n\n\tvar vA = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\tvar vB = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\tvar vC = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\n\tvar ab = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\tvar cb = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]();\n\n\tfunction ParserState() {\n\n\t\tvar state = {\n\t\t\tobjects: [],\n\t\t\tobject: {},\n\n\t\t\tvertices: [],\n\t\t\tnormals: [],\n\t\t\tcolors: [],\n\t\t\tuvs: [],\n\n\t\t\tmaterials: {},\n\t\t\tmaterialLibraries: [],\n\n\t\t\tstartObject: function ( name, fromDeclaration ) {\n\n\t\t\t\t// If the current object (initial from reset) is not from a g/o declaration in the parsed\n\t\t\t\t// file. We need to use it for the first parsed g/o to keep things in sync.\n\t\t\t\tif ( this.object && this.object.fromDeclaration === false ) {\n\n\t\t\t\t\tthis.object.name = name;\n\t\t\t\t\tthis.object.fromDeclaration = ( fromDeclaration !== false );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tvar previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );\n\n\t\t\t\tif ( this.object && typeof this.object._finalize === 'function' ) {\n\n\t\t\t\t\tthis.object._finalize( true );\n\n\t\t\t\t}\n\n\t\t\t\tthis.object = {\n\t\t\t\t\tname: name || '',\n\t\t\t\t\tfromDeclaration: ( fromDeclaration !== false ),\n\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\tvertices: [],\n\t\t\t\t\t\tnormals: [],\n\t\t\t\t\t\tcolors: [],\n\t\t\t\t\t\tuvs: [],\n\t\t\t\t\t\thasUVIndices: false\n\t\t\t\t\t},\n\t\t\t\t\tmaterials: [],\n\t\t\t\t\tsmooth: true,\n\n\t\t\t\t\tstartMaterial: function ( name, libraries ) {\n\n\t\t\t\t\t\tvar previous = this._finalize( false );\n\n\t\t\t\t\t\t// New usemtl declaration overwrites an inherited material, except if faces were declared\n\t\t\t\t\t\t// after the material, then it must be preserved for proper MultiMaterial continuation.\n\t\t\t\t\t\tif ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {\n\n\t\t\t\t\t\t\tthis.materials.splice( previous.index, 1 );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar material = {\n\t\t\t\t\t\t\tindex: this.materials.length,\n\t\t\t\t\t\t\tname: name || '',\n\t\t\t\t\t\t\tmtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),\n\t\t\t\t\t\t\tsmooth: ( previous !== undefined ? previous.smooth : this.smooth ),\n\t\t\t\t\t\t\tgroupStart: ( previous !== undefined ? previous.groupEnd : 0 ),\n\t\t\t\t\t\t\tgroupEnd: - 1,\n\t\t\t\t\t\t\tgroupCount: - 1,\n\t\t\t\t\t\t\tinherited: false,\n\n\t\t\t\t\t\t\tclone: function ( index ) {\n\n\t\t\t\t\t\t\t\tvar cloned = {\n\t\t\t\t\t\t\t\t\tindex: ( typeof index === 'number' ? index : this.index ),\n\t\t\t\t\t\t\t\t\tname: this.name,\n\t\t\t\t\t\t\t\t\tmtllib: this.mtllib,\n\t\t\t\t\t\t\t\t\tsmooth: this.smooth,\n\t\t\t\t\t\t\t\t\tgroupStart: 0,\n\t\t\t\t\t\t\t\t\tgroupEnd: - 1,\n\t\t\t\t\t\t\t\t\tgroupCount: - 1,\n\t\t\t\t\t\t\t\t\tinherited: false\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tcloned.clone = this.clone.bind( cloned );\n\t\t\t\t\t\t\t\treturn cloned;\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tthis.materials.push( material );\n\n\t\t\t\t\t\treturn material;\n\n\t\t\t\t\t},\n\n\t\t\t\t\tcurrentMaterial: function () {\n\n\t\t\t\t\t\tif ( this.materials.length > 0 ) {\n\n\t\t\t\t\t\t\treturn this.materials[ this.materials.length - 1 ];\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn undefined;\n\n\t\t\t\t\t},\n\n\t\t\t\t\t_finalize: function ( end ) {\n\n\t\t\t\t\t\tvar lastMultiMaterial = this.currentMaterial();\n\t\t\t\t\t\tif ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {\n\n\t\t\t\t\t\t\tlastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;\n\t\t\t\t\t\t\tlastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;\n\t\t\t\t\t\t\tlastMultiMaterial.inherited = false;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Ignore objects tail materials if no face declarations followed them before a new o/g started.\n\t\t\t\t\t\tif ( end && this.materials.length > 1 ) {\n\n\t\t\t\t\t\t\tfor ( var mi = this.materials.length - 1; mi >= 0; mi -- ) {\n\n\t\t\t\t\t\t\t\tif ( this.materials[ mi ].groupCount <= 0 ) {\n\n\t\t\t\t\t\t\t\t\tthis.materials.splice( mi, 1 );\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Guarantee at least one empty material, this makes the creation later more straight forward.\n\t\t\t\t\t\tif ( end && this.materials.length === 0 ) {\n\n\t\t\t\t\t\t\tthis.materials.push( {\n\t\t\t\t\t\t\t\tname: '',\n\t\t\t\t\t\t\t\tsmooth: this.smooth\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn lastMultiMaterial;\n\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Inherit previous objects material.\n\t\t\t\t// Spec tells us that a declared material must be set to all objects until a new material is declared.\n\t\t\t\t// If a usemtl declaration is encountered while this new object is being parsed, it will\n\t\t\t\t// overwrite the inherited material. Exception being that there was already face declarations\n\t\t\t\t// to the inherited material, then it will be preserved for proper MultiMaterial continuation.\n\n\t\t\t\tif ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {\n\n\t\t\t\t\tvar declared = previousMaterial.clone( 0 );\n\t\t\t\t\tdeclared.inherited = true;\n\t\t\t\t\tthis.object.materials.push( declared );\n\n\t\t\t\t}\n\n\t\t\t\tthis.objects.push( this.object );\n\n\t\t\t},\n\n\t\t\tfinalize: function () {\n\n\t\t\t\tif ( this.object && typeof this.object._finalize === 'function' ) {\n\n\t\t\t\t\tthis.object._finalize( true );\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tparseVertexIndex: function ( value, len ) {\n\n\t\t\t\tvar index = parseInt( value, 10 );\n\t\t\t\treturn ( index >= 0 ? index - 1 : index + len / 3 ) * 3;\n\n\t\t\t},\n\n\t\t\tparseNormalIndex: function ( value, len ) {\n\n\t\t\t\tvar index = parseInt( value, 10 );\n\t\t\t\treturn ( index >= 0 ? index - 1 : index + len / 3 ) * 3;\n\n\t\t\t},\n\n\t\t\tparseUVIndex: function ( value, len ) {\n\n\t\t\t\tvar index = parseInt( value, 10 );\n\t\t\t\treturn ( index >= 0 ? index - 1 : index + len / 2 ) * 2;\n\n\t\t\t},\n\n\t\t\taddVertex: function ( a, b, c ) {\n\n\t\t\t\tvar src = this.vertices;\n\t\t\t\tvar dst = this.object.geometry.vertices;\n\n\t\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t\t},\n\n\t\t\taddVertexPoint: function ( a ) {\n\n\t\t\t\tvar src = this.vertices;\n\t\t\t\tvar dst = this.object.geometry.vertices;\n\n\t\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\n\t\t\t},\n\n\t\t\taddVertexLine: function ( a ) {\n\n\t\t\t\tvar src = this.vertices;\n\t\t\t\tvar dst = this.object.geometry.vertices;\n\n\t\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\n\t\t\t},\n\n\t\t\taddNormal: function ( a, b, c ) {\n\n\t\t\t\tvar src = this.normals;\n\t\t\t\tvar dst = this.object.geometry.normals;\n\n\t\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t\t},\n\n\t\t\taddFaceNormal: function ( a, b, c ) {\n\n\t\t\t\tvar src = this.vertices;\n\t\t\t\tvar dst = this.object.geometry.normals;\n\n\t\t\t\tvA.fromArray( src, a );\n\t\t\t\tvB.fromArray( src, b );\n\t\t\t\tvC.fromArray( src, c );\n\n\t\t\t\tcb.subVectors( vC, vB );\n\t\t\t\tab.subVectors( vA, vB );\n\t\t\t\tcb.cross( ab );\n\n\t\t\t\tcb.normalize();\n\n\t\t\t\tdst.push( cb.x, cb.y, cb.z );\n\t\t\t\tdst.push( cb.x, cb.y, cb.z );\n\t\t\t\tdst.push( cb.x, cb.y, cb.z );\n\n\t\t\t},\n\n\t\t\taddColor: function ( a, b, c ) {\n\n\t\t\t\tvar src = this.colors;\n\t\t\t\tvar dst = this.object.geometry.colors;\n\n\t\t\t\tif ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );\n\t\t\t\tif ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );\n\t\t\t\tif ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );\n\n\t\t\t},\n\n\t\t\taddUV: function ( a, b, c ) {\n\n\t\t\t\tvar src = this.uvs;\n\t\t\t\tvar dst = this.object.geometry.uvs;\n\n\t\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ] );\n\t\t\t\tdst.push( src[ b + 0 ], src[ b + 1 ] );\n\t\t\t\tdst.push( src[ c + 0 ], src[ c + 1 ] );\n\n\t\t\t},\n\n\t\t\taddDefaultUV: function () {\n\n\t\t\t\tvar dst = this.object.geometry.uvs;\n\n\t\t\t\tdst.push( 0, 0 );\n\t\t\t\tdst.push( 0, 0 );\n\t\t\t\tdst.push( 0, 0 );\n\n\t\t\t},\n\n\t\t\taddUVLine: function ( a ) {\n\n\t\t\t\tvar src = this.uvs;\n\t\t\t\tvar dst = this.object.geometry.uvs;\n\n\t\t\t\tdst.push( src[ a + 0 ], src[ a + 1 ] );\n\n\t\t\t},\n\n\t\t\taddFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {\n\n\t\t\t\tvar vLen = this.vertices.length;\n\n\t\t\t\tvar ia = this.parseVertexIndex( a, vLen );\n\t\t\t\tvar ib = this.parseVertexIndex( b, vLen );\n\t\t\t\tvar ic = this.parseVertexIndex( c, vLen );\n\n\t\t\t\tthis.addVertex( ia, ib, ic );\n\t\t\t\tthis.addColor( ia, ib, ic );\n\n\t\t\t\t// normals\n\n\t\t\t\tif ( na !== undefined && na !== '' ) {\n\n\t\t\t\t\tvar nLen = this.normals.length;\n\n\t\t\t\t\tia = this.parseNormalIndex( na, nLen );\n\t\t\t\t\tib = this.parseNormalIndex( nb, nLen );\n\t\t\t\t\tic = this.parseNormalIndex( nc, nLen );\n\n\t\t\t\t\tthis.addNormal( ia, ib, ic );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis.addFaceNormal( ia, ib, ic );\n\n\t\t\t\t}\n\n\t\t\t\t// uvs\n\n\t\t\t\tif ( ua !== undefined && ua !== '' ) {\n\n\t\t\t\t\tvar uvLen = this.uvs.length;\n\n\t\t\t\t\tia = this.parseUVIndex( ua, uvLen );\n\t\t\t\t\tib = this.parseUVIndex( ub, uvLen );\n\t\t\t\t\tic = this.parseUVIndex( uc, uvLen );\n\n\t\t\t\t\tthis.addUV( ia, ib, ic );\n\n\t\t\t\t\tthis.object.geometry.hasUVIndices = true;\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// add placeholder values (for inconsistent face definitions)\n\n\t\t\t\t\tthis.addDefaultUV();\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\taddPointGeometry: function ( vertices ) {\n\n\t\t\t\tthis.object.geometry.type = 'Points';\n\n\t\t\t\tvar vLen = this.vertices.length;\n\n\t\t\t\tfor ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {\n\n\t\t\t\t\tvar index = this.parseVertexIndex( vertices[ vi ], vLen );\n\n\t\t\t\t\tthis.addVertexPoint( index );\n\t\t\t\t\tthis.addColor( index );\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\taddLineGeometry: function ( vertices, uvs ) {\n\n\t\t\t\tthis.object.geometry.type = 'Line';\n\n\t\t\t\tvar vLen = this.vertices.length;\n\t\t\t\tvar uvLen = this.uvs.length;\n\n\t\t\t\tfor ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {\n\n\t\t\t\t\tthis.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );\n\n\t\t\t\t}\n\n\t\t\t\tfor ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {\n\n\t\t\t\t\tthis.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t};\n\n\t\tstate.startObject( '', false );\n\n\t\treturn state;\n\n\t}\n\n\t//\n\n\tfunction OBJLoader( manager ) {\n\n\t\t_build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].call( this, manager );\n\n\t\tthis.materials = null;\n\n\t}\n\n\tOBJLoader.prototype = Object.assign( Object.create( _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].prototype ), {\n\n\t\tconstructor: OBJLoader,\n\n\t\tload: function ( url, onLoad, onProgress, onError ) {\n\n\t\t\tvar scope = this;\n\n\t\t\tvar loader = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"FileLoader\"]( this.manager );\n\t\t\tloader.setPath( this.path );\n\t\t\tloader.setRequestHeader( this.requestHeader );\n\t\t\tloader.setWithCredentials( this.withCredentials );\n\t\t\tloader.load( url, function ( text ) {\n\n\t\t\t\ttry {\n\n\t\t\t\t\tonLoad( scope.parse( text ) );\n\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\tif ( onError ) {\n\n\t\t\t\t\t\tonError( e );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tconsole.error( e );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tscope.manager.itemError( url );\n\n\t\t\t\t}\n\n\t\t\t}, onProgress, onError );\n\n\t\t},\n\n\t\tsetMaterials: function ( materials ) {\n\n\t\t\tthis.materials = materials;\n\n\t\t\treturn this;\n\n\t\t},\n\n\t\tparse: function ( text ) {\n\n\t\t\tvar state = new ParserState();\n\n\t\t\tif ( text.indexOf( '\\r\\n' ) !== - 1 ) {\n\n\t\t\t\t// This is faster than String.split with regex that splits on both\n\t\t\t\ttext = text.replace( /\\r\\n/g, '\\n' );\n\n\t\t\t}\n\n\t\t\tif ( text.indexOf( '\\\\\\n' ) !== - 1 ) {\n\n\t\t\t\t// join lines separated by a line continuation character (\\)\n\t\t\t\ttext = text.replace( /\\\\\\n/g, '' );\n\n\t\t\t}\n\n\t\t\tvar lines = text.split( '\\n' );\n\t\t\tvar line = '', lineFirstChar = '';\n\t\t\tvar lineLength = 0;\n\t\t\tvar result = [];\n\n\t\t\t// Faster to just trim left side of the line. Use if available.\n\t\t\tvar trimLeft = ( typeof ''.trimLeft === 'function' );\n\n\t\t\tfor ( var i = 0, l = lines.length; i < l; i ++ ) {\n\n\t\t\t\tline = lines[ i ];\n\n\t\t\t\tline = trimLeft ? line.trimLeft() : line.trim();\n\n\t\t\t\tlineLength = line.length;\n\n\t\t\t\tif ( lineLength === 0 ) continue;\n\n\t\t\t\tlineFirstChar = line.charAt( 0 );\n\n\t\t\t\t// @todo invoke passed in handler if any\n\t\t\t\tif ( lineFirstChar === '#' ) continue;\n\n\t\t\t\tif ( lineFirstChar === 'v' ) {\n\n\t\t\t\t\tvar data = line.split( /\\s+/ );\n\n\t\t\t\t\tswitch ( data[ 0 ] ) {\n\n\t\t\t\t\t\tcase 'v':\n\t\t\t\t\t\t\tstate.vertices.push(\n\t\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 2 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 3 ] )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif ( data.length >= 7 ) {\n\n\t\t\t\t\t\t\t\tstate.colors.push(\n\t\t\t\t\t\t\t\t\tparseFloat( data[ 4 ] ),\n\t\t\t\t\t\t\t\t\tparseFloat( data[ 5 ] ),\n\t\t\t\t\t\t\t\t\tparseFloat( data[ 6 ] )\n\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// if no colors are defined, add placeholders so color and vertex indices match\n\n\t\t\t\t\t\t\t\tstate.colors.push( undefined, undefined, undefined );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'vn':\n\t\t\t\t\t\t\tstate.normals.push(\n\t\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 2 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 3 ] )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'vt':\n\t\t\t\t\t\t\tstate.uvs.push(\n\t\t\t\t\t\t\t\tparseFloat( data[ 1 ] ),\n\t\t\t\t\t\t\t\tparseFloat( data[ 2 ] )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( lineFirstChar === 'f' ) {\n\n\t\t\t\t\tvar lineData = line.substr( 1 ).trim();\n\t\t\t\t\tvar vertexData = lineData.split( /\\s+/ );\n\t\t\t\t\tvar faceVertices = [];\n\n\t\t\t\t\t// Parse the face vertex data into an easy to work with format\n\n\t\t\t\t\tfor ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {\n\n\t\t\t\t\t\tvar vertex = vertexData[ j ];\n\n\t\t\t\t\t\tif ( vertex.length > 0 ) {\n\n\t\t\t\t\t\t\tvar vertexParts = vertex.split( '/' );\n\t\t\t\t\t\t\tfaceVertices.push( vertexParts );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Draw an edge between the first vertex and all subsequent vertices to form an n-gon\n\n\t\t\t\t\tvar v1 = faceVertices[ 0 ];\n\n\t\t\t\t\tfor ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {\n\n\t\t\t\t\t\tvar v2 = faceVertices[ j ];\n\t\t\t\t\t\tvar v3 = faceVertices[ j + 1 ];\n\n\t\t\t\t\t\tstate.addFace(\n\t\t\t\t\t\t\tv1[ 0 ], v2[ 0 ], v3[ 0 ],\n\t\t\t\t\t\t\tv1[ 1 ], v2[ 1 ], v3[ 1 ],\n\t\t\t\t\t\t\tv1[ 2 ], v2[ 2 ], v3[ 2 ]\n\t\t\t\t\t\t);\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( lineFirstChar === 'l' ) {\n\n\t\t\t\t\tvar lineParts = line.substring( 1 ).trim().split( ' ' );\n\t\t\t\t\tvar lineVertices = [], lineUVs = [];\n\n\t\t\t\t\tif ( line.indexOf( '/' ) === - 1 ) {\n\n\t\t\t\t\t\tlineVertices = lineParts;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tfor ( var li = 0, llen = lineParts.length; li < llen; li ++ ) {\n\n\t\t\t\t\t\t\tvar parts = lineParts[ li ].split( '/' );\n\n\t\t\t\t\t\t\tif ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );\n\t\t\t\t\t\t\tif ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tstate.addLineGeometry( lineVertices, lineUVs );\n\n\t\t\t\t} else if ( lineFirstChar === 'p' ) {\n\n\t\t\t\t\tvar lineData = line.substr( 1 ).trim();\n\t\t\t\t\tvar pointData = lineData.split( ' ' );\n\n\t\t\t\t\tstate.addPointGeometry( pointData );\n\n\t\t\t\t} else if ( ( result = object_pattern.exec( line ) ) !== null ) {\n\n\t\t\t\t\t// o object_name\n\t\t\t\t\t// or\n\t\t\t\t\t// g group_name\n\n\t\t\t\t\t// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869\n\t\t\t\t\t// var name = result[ 0 ].substr( 1 ).trim();\n\t\t\t\t\tvar name = ( ' ' + result[ 0 ].substr( 1 ).trim() ).substr( 1 );\n\n\t\t\t\t\tstate.startObject( name );\n\n\t\t\t\t} else if ( material_use_pattern.test( line ) ) {\n\n\t\t\t\t\t// material\n\n\t\t\t\t\tstate.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );\n\n\t\t\t\t} else if ( material_library_pattern.test( line ) ) {\n\n\t\t\t\t\t// mtl file\n\n\t\t\t\t\tstate.materialLibraries.push( line.substring( 7 ).trim() );\n\n\t\t\t\t} else if ( map_use_pattern.test( line ) ) {\n\n\t\t\t\t\t// the line is parsed but ignored since the loader assumes textures are defined MTL files\n\t\t\t\t\t// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)\n\n\t\t\t\t\tconsole.warn( 'THREE.OBJLoader: Rendering identifier \"usemap\" not supported. Textures must be defined in MTL files.' );\n\n\t\t\t\t} else if ( lineFirstChar === 's' ) {\n\n\t\t\t\t\tresult = line.split( ' ' );\n\n\t\t\t\t\t// smooth shading\n\n\t\t\t\t\t// @todo Handle files that have varying smooth values for a set of faces inside one geometry,\n\t\t\t\t\t// but does not define a usemtl for each face set.\n\t\t\t\t\t// This should be detected and a dummy material created (later MultiMaterial and geometry groups).\n\t\t\t\t\t// This requires some care to not create extra material on each smooth value for \"normal\" obj files.\n\t\t\t\t\t// where explicit usemtl defines geometry groups.\n\t\t\t\t\t// Example asset: examples/models/obj/cerberus/Cerberus.obj\n\n\t\t\t\t\t/*\n\t\t\t\t\t * http://paulbourke.net/dataformats/obj/\n\t\t\t\t\t * or\n\t\t\t\t\t * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf\n\t\t\t\t\t *\n\t\t\t\t\t * From chapter \"Grouping\" Syntax explanation \"s group_number\":\n\t\t\t\t\t * \"group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.\n\t\t\t\t\t * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form\n\t\t\t\t\t * surfaces, smoothing groups are either turned on or off; there is no difference between values greater\n\t\t\t\t\t * than 0.\"\n\t\t\t\t\t */\n\t\t\t\t\tif ( result.length > 1 ) {\n\n\t\t\t\t\t\tvar value = result[ 1 ].trim().toLowerCase();\n\t\t\t\t\t\tstate.object.smooth = ( value !== '0' && value !== 'off' );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// ZBrush can produce \"s\" lines #11707\n\t\t\t\t\t\tstate.object.smooth = true;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tvar material = state.object.currentMaterial();\n\t\t\t\t\tif ( material ) material.smooth = state.object.smooth;\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Handle null terminated files without exception\n\t\t\t\t\tif ( line === '\\0' ) continue;\n\n\t\t\t\t\tconsole.warn( 'THREE.OBJLoader: Unexpected line: \"' + line + '\"' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tstate.finalize();\n\n\t\t\tvar container = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Group\"]();\n\t\t\tcontainer.materialLibraries = [].concat( state.materialLibraries );\n\n\t\t\tvar hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );\n\n\t\t\tif ( hasPrimitives === true ) {\n\n\t\t\t\tfor ( var i = 0, l = state.objects.length; i < l; i ++ ) {\n\n\t\t\t\t\tvar object = state.objects[ i ];\n\t\t\t\t\tvar geometry = object.geometry;\n\t\t\t\t\tvar materials = object.materials;\n\t\t\t\t\tvar isLine = ( geometry.type === 'Line' );\n\t\t\t\t\tvar isPoints = ( geometry.type === 'Points' );\n\t\t\t\t\tvar hasVertexColors = false;\n\n\t\t\t\t\t// Skip o/g line declarations that did not follow with any faces\n\t\t\t\t\tif ( geometry.vertices.length === 0 ) continue;\n\n\t\t\t\t\tvar buffergeometry = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"BufferGeometry\"]();\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'position', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( geometry.vertices, 3 ) );\n\n\t\t\t\t\tif ( geometry.normals.length > 0 ) {\n\n\t\t\t\t\t\tbuffergeometry.setAttribute( 'normal', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( geometry.normals, 3 ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( geometry.colors.length > 0 ) {\n\n\t\t\t\t\t\thasVertexColors = true;\n\t\t\t\t\t\tbuffergeometry.setAttribute( 'color', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( geometry.colors, 3 ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( geometry.hasUVIndices === true ) {\n\n\t\t\t\t\t\tbuffergeometry.setAttribute( 'uv', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( geometry.uvs, 2 ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create materials\n\n\t\t\t\t\tvar createdMaterials = [];\n\n\t\t\t\t\tfor ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {\n\n\t\t\t\t\t\tvar sourceMaterial = materials[ mi ];\n\t\t\t\t\t\tvar materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;\n\t\t\t\t\t\tvar material = state.materials[ materialHash ];\n\n\t\t\t\t\t\tif ( this.materials !== null ) {\n\n\t\t\t\t\t\t\tmaterial = this.materials.create( sourceMaterial.name );\n\n\t\t\t\t\t\t\t// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.\n\t\t\t\t\t\t\tif ( isLine && material && ! ( material instanceof _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LineBasicMaterial\"] ) ) {\n\n\t\t\t\t\t\t\t\tvar materialLine = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LineBasicMaterial\"]();\n\t\t\t\t\t\t\t\t_build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Material\"].prototype.copy.call( materialLine, material );\n\t\t\t\t\t\t\t\tmaterialLine.color.copy( material.color );\n\t\t\t\t\t\t\t\tmaterial = materialLine;\n\n\t\t\t\t\t\t\t} else if ( isPoints && material && ! ( material instanceof _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"PointsMaterial\"] ) ) {\n\n\t\t\t\t\t\t\t\tvar materialPoints = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"PointsMaterial\"]( { size: 10, sizeAttenuation: false } );\n\t\t\t\t\t\t\t\t_build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Material\"].prototype.copy.call( materialPoints, material );\n\t\t\t\t\t\t\t\tmaterialPoints.color.copy( material.color );\n\t\t\t\t\t\t\t\tmaterialPoints.map = material.map;\n\t\t\t\t\t\t\t\tmaterial = materialPoints;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( material === undefined ) {\n\n\t\t\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\t\t\tmaterial = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LineBasicMaterial\"]();\n\n\t\t\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\t\t\tmaterial = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"PointsMaterial\"]( { size: 1, sizeAttenuation: false } );\n\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\tmaterial = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"MeshPhongMaterial\"]();\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tmaterial.name = sourceMaterial.name;\n\t\t\t\t\t\t\tmaterial.flatShading = sourceMaterial.smooth ? false : true;\n\t\t\t\t\t\t\tmaterial.vertexColors = hasVertexColors;\n\n\t\t\t\t\t\t\tstate.materials[ materialHash ] = material;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcreatedMaterials.push( material );\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create mesh\n\n\t\t\t\t\tvar mesh;\n\n\t\t\t\t\tif ( createdMaterials.length > 1 ) {\n\n\t\t\t\t\t\tfor ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {\n\n\t\t\t\t\t\t\tvar sourceMaterial = materials[ mi ];\n\t\t\t\t\t\t\tbuffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\t\tmesh = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LineSegments\"]( buffergeometry, createdMaterials );\n\n\t\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\t\tmesh = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Points\"]( buffergeometry, createdMaterials );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tmesh = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Mesh\"]( buffergeometry, createdMaterials );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( isLine ) {\n\n\t\t\t\t\t\t\tmesh = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"LineSegments\"]( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t\t} else if ( isPoints ) {\n\n\t\t\t\t\t\t\tmesh = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Points\"]( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tmesh = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Mesh\"]( buffergeometry, createdMaterials[ 0 ] );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t\tmesh.name = object.name;\n\n\t\t\t\t\tcontainer.add( mesh );\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// if there is only the default parser state object with no geometry data, interpret data as point cloud\n\n\t\t\t\tif ( state.vertices.length > 0 ) {\n\n\t\t\t\t\tvar material = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"PointsMaterial\"]( { size: 1, sizeAttenuation: false } );\n\n\t\t\t\t\tvar buffergeometry = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"BufferGeometry\"]();\n\n\t\t\t\t\tbuffergeometry.setAttribute( 'position', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( state.vertices, 3 ) );\n\n\t\t\t\t\tif ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {\n\n\t\t\t\t\t\tbuffergeometry.setAttribute( 'color', new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Float32BufferAttribute\"]( state.colors, 3 ) );\n\t\t\t\t\t\tmaterial.vertexColors = true;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tvar points = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Points\"]( buffergeometry, material );\n\t\t\t\t\tcontainer.add( points );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn container;\n\n\t\t}\n\n\t} );\n\n\treturn OBJLoader;\n\n} )();\n\n\n\n\n//# sourceURL=webpack://LithoSphere/./node_modules/three/examples/jsm/loaders/OBJLoader.js?"); + +/***/ }), + +/***/ "./node_modules/three/examples/jsm/loaders/TGALoader.js": +/*!**************************************************************!*\ + !*** ./node_modules/three/examples/jsm/loaders/TGALoader.js ***! + \**************************************************************/ +/*! exports provided: TGALoader */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TGALoader\", function() { return TGALoader; });\n/* harmony import */ var _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../build/three.module.js */ \"./node_modules/three/build/three.module.js\");\n\n\nvar TGALoader = function ( manager ) {\n\n\t_build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].call( this, manager );\n\n};\n\nTGALoader.prototype = Object.assign( Object.create( _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Loader\"].prototype ), {\n\n\tconstructor: TGALoader,\n\n\tload: function ( url, onLoad, onProgress, onError ) {\n\n\t\tvar scope = this;\n\n\t\tvar texture = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"Texture\"]();\n\n\t\tvar loader = new _build_three_module_js__WEBPACK_IMPORTED_MODULE_0__[\"FileLoader\"]( this.manager );\n\t\tloader.setResponseType( 'arraybuffer' );\n\t\tloader.setPath( this.path );\n\t\tloader.setWithCredentials( this.withCredentials );\n\n\t\tloader.load( url, function ( buffer ) {\n\n\t\t\ttexture.image = scope.parse( buffer );\n\t\t\ttexture.needsUpdate = true;\n\n\t\t\tif ( onLoad !== undefined ) {\n\n\t\t\t\tonLoad( texture );\n\n\t\t\t}\n\n\t\t}, onProgress, onError );\n\n\t\treturn texture;\n\n\t},\n\n\tparse: function ( buffer ) {\n\n\t\t// reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js\n\n\t\tfunction tgaCheckHeader( header ) {\n\n\t\t\tswitch ( header.image_type ) {\n\n\t\t\t\t// check indexed type\n\n\t\t\t\tcase TGA_TYPE_INDEXED:\n\t\t\t\tcase TGA_TYPE_RLE_INDEXED:\n\t\t\t\t\tif ( header.colormap_length > 256 || header.colormap_size !== 24 || header.colormap_type !== 1 ) {\n\n\t\t\t\t\t\tconsole.error( 'THREE.TGALoader: Invalid type colormap data for indexed type.' );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\t\t// check colormap type\n\n\t\t\t\tcase TGA_TYPE_RGB:\n\t\t\t\tcase TGA_TYPE_GREY:\n\t\t\t\tcase TGA_TYPE_RLE_RGB:\n\t\t\t\tcase TGA_TYPE_RLE_GREY:\n\t\t\t\t\tif ( header.colormap_type ) {\n\n\t\t\t\t\t\tconsole.error( 'THREE.TGALoader: Invalid type colormap data for colormap type.' );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\t\t// What the need of a file without data ?\n\n\t\t\t\tcase TGA_TYPE_NO_DATA:\n\t\t\t\t\tconsole.error( 'THREE.TGALoader: No data.' );\n\n\t\t\t\t\t// Invalid type ?\n\n\t\t\t\tdefault:\n\t\t\t\t\tconsole.error( 'THREE.TGALoader: Invalid type \"%s\".', header.image_type );\n\n\t\t\t}\n\n\t\t\t// check image width and height\n\n\t\t\tif ( header.width <= 0 || header.height <= 0 ) {\n\n\t\t\t\tconsole.error( 'THREE.TGALoader: Invalid image size.' );\n\n\t\t\t}\n\n\t\t\t// check image pixel size\n\n\t\t\tif ( header.pixel_size !== 8 && header.pixel_size !== 16 &&\n\t\t\t\theader.pixel_size !== 24 && header.pixel_size !== 32 ) {\n\n\t\t\t\tconsole.error( 'THREE.TGALoader: Invalid pixel size \"%s\".', header.pixel_size );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// parse tga image buffer\n\n\t\tfunction tgaParse( use_rle, use_pal, header, offset, data ) {\n\n\t\t\tvar pixel_data,\n\t\t\t\tpixel_size,\n\t\t\t\tpixel_total,\n\t\t\t\tpalettes;\n\n\t\t\tpixel_size = header.pixel_size >> 3;\n\t\t\tpixel_total = header.width * header.height * pixel_size;\n\n\t\t\t // read palettes\n\n\t\t\t if ( use_pal ) {\n\n\t\t\t\t palettes = data.subarray( offset, offset += header.colormap_length * ( header.colormap_size >> 3 ) );\n\n\t\t\t }\n\n\t\t\t // read RLE\n\n\t\t\t if ( use_rle ) {\n\n\t\t\t\t pixel_data = new Uint8Array( pixel_total );\n\n\t\t\t\tvar c, count, i;\n\t\t\t\tvar shift = 0;\n\t\t\t\tvar pixels = new Uint8Array( pixel_size );\n\n\t\t\t\twhile ( shift < pixel_total ) {\n\n\t\t\t\t\tc = data[ offset ++ ];\n\t\t\t\t\tcount = ( c & 0x7f ) + 1;\n\n\t\t\t\t\t// RLE pixels\n\n\t\t\t\t\tif ( c & 0x80 ) {\n\n\t\t\t\t\t\t// bind pixel tmp array\n\n\t\t\t\t\t\tfor ( i = 0; i < pixel_size; ++ i ) {\n\n\t\t\t\t\t\t\tpixels[ i ] = data[ offset ++ ];\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// copy pixel array\n\n\t\t\t\t\t\tfor ( i = 0; i < count; ++ i ) {\n\n\t\t\t\t\t\t\tpixel_data.set( pixels, shift + i * pixel_size );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tshift += pixel_size * count;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// raw pixels\n\n\t\t\t\t\t\tcount *= pixel_size;\n\n\t\t\t\t\t\tfor ( i = 0; i < count; ++ i ) {\n\n\t\t\t\t\t\t\tpixel_data[ shift + i ] = data[ offset ++ ];\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tshift += count;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t } else {\n\n\t\t\t\t// raw pixels\n\n\t\t\t\tpixel_data = data.subarray(\n\t\t\t\t\t offset, offset += ( use_pal ? header.width * header.height : pixel_total )\n\t\t\t\t);\n\n\t\t\t }\n\n\t\t\t return {\n\t\t\t\tpixel_data: pixel_data,\n\t\t\t\tpalettes: palettes\n\t\t\t };\n\n\t\t}\n\n\t\tfunction tgaGetImageData8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image, palettes ) {\n\n\t\t\tvar colormap = palettes;\n\t\t\tvar color, i = 0, x, y;\n\t\t\tvar width = header.width;\n\n\t\t\tfor ( y = y_start; y !== y_end; y += y_step ) {\n\n\t\t\t\tfor ( x = x_start; x !== x_end; x += x_step, i ++ ) {\n\n\t\t\t\t\tcolor = image[ i ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 3 ] = 255;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 2 ] = colormap[ ( color * 3 ) + 0 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 1 ] = colormap[ ( color * 3 ) + 1 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 0 ] = colormap[ ( color * 3 ) + 2 ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn imageData;\n\n\t\t}\n\n\t\tfunction tgaGetImageData16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) {\n\n\t\t\tvar color, i = 0, x, y;\n\t\t\tvar width = header.width;\n\n\t\t\tfor ( y = y_start; y !== y_end; y += y_step ) {\n\n\t\t\t\tfor ( x = x_start; x !== x_end; x += x_step, i += 2 ) {\n\n\t\t\t\t\tcolor = image[ i + 0 ] + ( image[ i + 1 ] << 8 ); // Inversed ?\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 0 ] = ( color & 0x7C00 ) >> 7;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 1 ] = ( color & 0x03E0 ) >> 2;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 2 ] = ( color & 0x001F ) >> 3;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 3 ] = ( color & 0x8000 ) ? 0 : 255;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn imageData;\n\n\t\t}\n\n\t\tfunction tgaGetImageData24bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) {\n\n\t\t\tvar i = 0, x, y;\n\t\t\tvar width = header.width;\n\n\t\t\tfor ( y = y_start; y !== y_end; y += y_step ) {\n\n\t\t\t\tfor ( x = x_start; x !== x_end; x += x_step, i += 3 ) {\n\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 3 ] = 255;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn imageData;\n\n\t\t}\n\n\t\tfunction tgaGetImageData32bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) {\n\n\t\t\tvar i = 0, x, y;\n\t\t\tvar width = header.width;\n\n\t\t\tfor ( y = y_start; y !== y_end; y += y_step ) {\n\n\t\t\t\tfor ( x = x_start; x !== x_end; x += x_step, i += 4 ) {\n\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 1 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 2 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 3 ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn imageData;\n\n\t\t}\n\n\t\tfunction tgaGetImageDataGrey8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) {\n\n\t\t\tvar color, i = 0, x, y;\n\t\t\tvar width = header.width;\n\n\t\t\tfor ( y = y_start; y !== y_end; y += y_step ) {\n\n\t\t\t\tfor ( x = x_start; x !== x_end; x += x_step, i ++ ) {\n\n\t\t\t\t\tcolor = image[ i ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 0 ] = color;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 1 ] = color;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 2 ] = color;\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 3 ] = 255;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn imageData;\n\n\t\t}\n\n\t\tfunction tgaGetImageDataGrey16bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) {\n\n\t\t\tvar i = 0, x, y;\n\t\t\tvar width = header.width;\n\n\t\t\tfor ( y = y_start; y !== y_end; y += y_step ) {\n\n\t\t\t\tfor ( x = x_start; x !== x_end; x += x_step, i += 2 ) {\n\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 0 ] = image[ i + 0 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 1 ] = image[ i + 0 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 2 ] = image[ i + 0 ];\n\t\t\t\t\timageData[ ( x + width * y ) * 4 + 3 ] = image[ i + 1 ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn imageData;\n\n\t\t}\n\n\t\tfunction getTgaRGBA( data, width, height, image, palette ) {\n\n\t\t\tvar x_start,\n\t\t\t\ty_start,\n\t\t\t\tx_step,\n\t\t\t\ty_step,\n\t\t\t\tx_end,\n\t\t\t\ty_end;\n\n\t\t\tswitch ( ( header.flags & TGA_ORIGIN_MASK ) >> TGA_ORIGIN_SHIFT ) {\n\n\t\t\t\tdefault:\n\t\t\t\tcase TGA_ORIGIN_UL:\n\t\t\t\t\tx_start = 0;\n\t\t\t\t\tx_step = 1;\n\t\t\t\t\tx_end = width;\n\t\t\t\t\ty_start = 0;\n\t\t\t\t\ty_step = 1;\n\t\t\t\t\ty_end = height;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_ORIGIN_BL:\n\t\t\t\t\tx_start = 0;\n\t\t\t\t\tx_step = 1;\n\t\t\t\t\tx_end = width;\n\t\t\t\t\ty_start = height - 1;\n\t\t\t\t\ty_step = - 1;\n\t\t\t\t\ty_end = - 1;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_ORIGIN_UR:\n\t\t\t\t\tx_start = width - 1;\n\t\t\t\t\tx_step = - 1;\n\t\t\t\t\tx_end = - 1;\n\t\t\t\t\ty_start = 0;\n\t\t\t\t\ty_step = 1;\n\t\t\t\t\ty_end = height;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TGA_ORIGIN_BR:\n\t\t\t\t\tx_start = width - 1;\n\t\t\t\t\tx_step = - 1;\n\t\t\t\t\tx_end = - 1;\n\t\t\t\t\ty_start = height - 1;\n\t\t\t\t\ty_step = - 1;\n\t\t\t\t\ty_end = - 1;\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tif ( use_grey ) {\n\n\t\t\t\tswitch ( header.pixel_size ) {\n\n\t\t\t\t\tcase 8:\n\t\t\t\t\t\ttgaGetImageDataGrey8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 16:\n\t\t\t\t\t\ttgaGetImageDataGrey16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tconsole.error( 'THREE.TGALoader: Format not supported.' );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tswitch ( header.pixel_size ) {\n\n\t\t\t\t\tcase 8:\n\t\t\t\t\t\ttgaGetImageData8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image, palette );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 16:\n\t\t\t\t\t\ttgaGetImageData16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 24:\n\t\t\t\t\t\ttgaGetImageData24bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 32:\n\t\t\t\t\t\ttgaGetImageData32bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tconsole.error( 'THREE.TGALoader: Format not supported.' );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Load image data according to specific method\n\t\t\t// var func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits';\n\t\t\t// func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette );\n\t\t\treturn data;\n\n\t\t}\n\n\t\t// TGA constants\n\n\t\tvar TGA_TYPE_NO_DATA = 0,\n\t\t\tTGA_TYPE_INDEXED = 1,\n\t\t\tTGA_TYPE_RGB = 2,\n\t\t\tTGA_TYPE_GREY = 3,\n\t\t\tTGA_TYPE_RLE_INDEXED = 9,\n\t\t\tTGA_TYPE_RLE_RGB = 10,\n\t\t\tTGA_TYPE_RLE_GREY = 11,\n\n\t\t\tTGA_ORIGIN_MASK = 0x30,\n\t\t\tTGA_ORIGIN_SHIFT = 0x04,\n\t\t\tTGA_ORIGIN_BL = 0x00,\n\t\t\tTGA_ORIGIN_BR = 0x01,\n\t\t\tTGA_ORIGIN_UL = 0x02,\n\t\t\tTGA_ORIGIN_UR = 0x03;\n\n\t\tif ( buffer.length < 19 ) console.error( 'THREE.TGALoader: Not enough data to contain header.' );\n\n\t\tvar content = new Uint8Array( buffer ),\n\t\t\toffset = 0,\n\t\t\theader = {\n\t\t\t\tid_length: content[ offset ++ ],\n\t\t\t\tcolormap_type: content[ offset ++ ],\n\t\t\t\timage_type: content[ offset ++ ],\n\t\t\t\tcolormap_index: content[ offset ++ ] | content[ offset ++ ] << 8,\n\t\t\t\tcolormap_length: content[ offset ++ ] | content[ offset ++ ] << 8,\n\t\t\t\tcolormap_size: content[ offset ++ ],\n\t\t\t\torigin: [\n\t\t\t\t\tcontent[ offset ++ ] | content[ offset ++ ] << 8,\n\t\t\t\t\tcontent[ offset ++ ] | content[ offset ++ ] << 8\n\t\t\t\t],\n\t\t\t\twidth: content[ offset ++ ] | content[ offset ++ ] << 8,\n\t\t\t\theight: content[ offset ++ ] | content[ offset ++ ] << 8,\n\t\t\t\tpixel_size: content[ offset ++ ],\n\t\t\t\tflags: content[ offset ++ ]\n\t\t\t};\n\n\t\t// check tga if it is valid format\n\n\t\ttgaCheckHeader( header );\n\n\t\tif ( header.id_length + offset > buffer.length ) {\n\n\t\t\tconsole.error( 'THREE.TGALoader: No data.' );\n\n\t\t}\n\n\t\t// skip the needn't data\n\n\t\toffset += header.id_length;\n\n\t\t// get targa information about RLE compression and palette\n\n\t\tvar use_rle = false,\n\t\t\tuse_pal = false,\n\t\t\tuse_grey = false;\n\n\t\tswitch ( header.image_type ) {\n\n\t\t\tcase TGA_TYPE_RLE_INDEXED:\n\t\t\t\tuse_rle = true;\n\t\t\t\tuse_pal = true;\n\t\t\t\tbreak;\n\n\t\t\tcase TGA_TYPE_INDEXED:\n\t\t\t\tuse_pal = true;\n\t\t\t\tbreak;\n\n\t\t\tcase TGA_TYPE_RLE_RGB:\n\t\t\t\tuse_rle = true;\n\t\t\t\tbreak;\n\n\t\t\tcase TGA_TYPE_RGB:\n\t\t\t\tbreak;\n\n\t\t\tcase TGA_TYPE_RLE_GREY:\n\t\t\t\tuse_rle = true;\n\t\t\t\tuse_grey = true;\n\t\t\t\tbreak;\n\n\t\t\tcase TGA_TYPE_GREY:\n\t\t\t\tuse_grey = true;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t//\n\n\t\tvar useOffscreen = typeof OffscreenCanvas !== 'undefined';\n\n\t\tvar canvas = useOffscreen ? new OffscreenCanvas( header.width, header.height ) : document.createElement( 'canvas' );\n\t\tcanvas.width = header.width;\n\t\tcanvas.height = header.height;\n\n\t\tvar context = canvas.getContext( '2d' );\n\t\tvar imageData = context.createImageData( header.width, header.height );\n\n\t\tvar result = tgaParse( use_rle, use_pal, header, offset, content );\n\t\tgetTgaRGBA( imageData.data, header.width, header.height, result.pixel_data, result.palettes );\n\n\t\tcontext.putImageData( imageData, 0, 0 );\n\n\t\treturn canvas;\n\n\t}\n\n} );\n\n\n\n\n//# sourceURL=webpack://LithoSphere/./node_modules/three/examples/jsm/loaders/TGALoader.js?"); + +/***/ }), + /***/ "./node_modules/wkt-parser/index.js": /*!******************************************!*\ !*** ./node_modules/wkt-parser/index.js ***! @@ -1900,7 +1948,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var thre /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _turf_circle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @turf/circle */ \"./node_modules/@turf/circle/dist/es/index.js\");\n/* harmony import */ var _turf_boolean_intersects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @turf/boolean-intersects */ \"./node_modules/@turf/boolean-intersects/dist/es/index.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n\n\n\n\n\nvar Events = function () {\n function Events(parent) {\n var _this = this;\n\n this._rotateGlobe = function (e, prevXY) {\n if (prevXY) {\n _this._.prevMouseXY.x = prevXY.x;\n _this._.prevMouseXY.y = prevXY.y;\n }\n\n if (!e) return;\n if (!e.pageX && e.touches) e.pageX = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageX');\n if (!e.pageY && e.touches) e.pageY = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageY');\n\n if (e.hasOwnProperty('x') && e.hasOwnProperty('y') && _this.p._.cameras.isFirstPerson) {\n _this._.prevMouseXY.x = 0;\n _this._.prevMouseXY.y = 0;\n e.pageX = e.x;\n e.pageY = e.y;\n }\n\n var rotSpeed = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].getRadiansPerPixel(_this.p.trueZoom) * 0.5 * (_this.p._.marsRadius / _this.p.projection.radii.major);\n\n var pixelDif = 0;\n var cpX = new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](_this.p._.cameras.orbit.camera.position.x, 0, _this.p._.cameras.orbit.camera.position.z);\n cpX.applyAxisAngle(new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](0, 1, 0), Math.PI / 2);\n var cpY = new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](_this.p._.cameras.orbit.camera.position.x, 0, _this.p._.cameras.orbit.camera.position.z);\n\n if (e.pageY < _this._.prevMouseXY.y) {\n pixelDif = Math.abs(e.pageY - _this._.prevMouseXY.y);\n\n _this._rotateAroundArbAxis(cpX, rotSpeed * pixelDif);\n } else if (e.pageY > _this._.prevMouseXY.y) {\n pixelDif = Math.abs(e.pageY - _this._.prevMouseXY.y);\n\n _this._rotateAroundArbAxis(cpX, -rotSpeed * pixelDif);\n }\n\n if (e.pageX > _this._.prevMouseXY.x) {\n pixelDif = Math.abs(e.pageX - _this._.prevMouseXY.x);\n\n _this._rotateAroundArbAxis(cpY, -rotSpeed * pixelDif);\n } else if (e.pageX < _this._.prevMouseXY.x) {\n pixelDif = Math.abs(e.pageX - _this._.prevMouseXY.x);\n\n _this._rotateAroundArbAxis(cpY, rotSpeed * pixelDif);\n }\n\n _this._.prevMouseXY.x = e.pageX;\n _this._.prevMouseXY.y = e.pageY;\n\n if (_this.p.zoom <= _this.p._.zCutOff) {\n _this.p._.cameras.orbit.controls.target.x = 0;\n _this.p._.cameras.orbit.controls.target.y = -_this.p.planetCenter.y;\n _this.p._.cameras.orbit.controls.target.z = 0;\n\n _this.p._.cameras.orbit.controls.update();\n } else {\n var elevRaw = _this.p.getCenterElevationRaw();\n\n if (elevRaw != null) {\n var newLookAtY = -(elevRaw + _this.p.planetCenter.y);\n if (newLookAtY != 0 && newLookAtY != -10000) _this.p._.cameras.orbit.controls.target.y = newLookAtY - _this.p.options.targetYOffset;\n }\n\n var center = _this.p.getCenter();\n\n _this.p.controls._onMove(center.lng, center.lat, center.height);\n }\n };\n\n this._rotateGlobe_MouseDown = function (e) {\n if (e.which === 1 || e.button === 0) {\n _this._.prevMouseXY.x = e.pageX;\n _this._.prevMouseXY.y = e.pageY;\n\n _this.p._.sceneContainer.addEventListener('mousemove', _this._rotateGlobe, false);\n\n _this.p._.sceneContainer.addEventListener('mouseup', _this._rotateGlobe_MouseUp, false);\n\n _this.p._.sceneContainer.addEventListener('mouseleave', _this._rotateGlobe_MouseUp, false);\n } else if (e.touches && e.touches.length > 2) {\n _this._.prevMouseXY.x = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageX');\n _this._.prevMouseXY.y = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageY');\n\n _this.p._.sceneContainer.addEventListener('touchmove', _this._rotateGlobe, false);\n\n _this.p._.sceneContainer.addEventListener('touchend', _this._rotateGlobe_MouseUp, false);\n }\n };\n\n this._rotateGlobe_MouseUp = function (e) {\n _this.p._.sceneContainer.removeEventListener('mousemove', _this._rotateGlobe);\n\n _this.p._.sceneContainer.removeEventListener('mouseup', _this._rotateGlobe_MouseUp);\n\n _this.p._.sceneContainer.removeEventListener('mouseleave', _this._rotateGlobe_MouseUp);\n\n _this.p._.sceneContainer.removeEventListener('touchmove', _this._rotateGlobe);\n\n _this.p._.sceneContainer.removeEventListener('touchend', _this._rotateGlobe_MouseUp);\n };\n\n this._onZoom = function (e) {\n _this._.zoomedSince = 0;\n\n var zoomDist = _this.p._.cameras.orbit.camera.position.distanceTo(_this.p._.cameras.orbit.controls.target);\n\n var nf = 8 - (_this.p.projection.radiusScale.toString().length - 1);\n var dZoom = Math.ceil((nf * Math.log(2) - Math.log(zoomDist / Math.pow(5, nf - 1))) / Math.log(2)) + 1;\n _this._.desiredZoom = dZoom;\n\n _this._attenuate();\n };\n\n this._onTouchZoom = function (e) {\n if (e.touches && e.touches.length == 1) _this._onZoom(e);\n };\n\n this._onClick = function (e) {\n if (_this.hoveredFeature && _this.hoverInfo) {\n var layer = _this.p.layers.getLayerByName(_this.hoveredFeature.layerName);\n\n if (layer) {\n _this.setActiveFeature({\n layerName: _this.hoveredFeature.layerName,\n type: _this.hoveredFeature.type,\n obj: _this.hoveredFeature.obj,\n feature: _this.hoveredFeature.feature || _this.hoveredFeature.obj.feature,\n lnglat: {\n lng: _this.hoveredFeature.lnglat.lng,\n lat: _this.hoveredFeature.lnglat.lat\n }\n });\n\n if (typeof layer.onClick === 'function') {\n layer.onClick(JSON.parse(JSON.stringify(_this.hoveredFeature.feature)), JSON.parse(JSON.stringify(_this.hoveredFeature.lnglat)), layer);\n }\n }\n }\n };\n\n this._onMouseMove = function (e) {\n _this.p._.mouseIsInScene = true;\n\n if (_this.p._.cameras.isFirstPerson) {\n _this._.mouseXY.x = 0;\n _this._.mouseXY.y = 0;\n } else {\n _this._.mouseXY.x = (e.clientX - _this.p._.renderer.domElement.getBoundingClientRect().left) / _this.p._.renderer.domElement.clientWidth * 2 - 1;\n _this._.mouseXY.y = -((e.clientY - _this.p._.renderer.domElement.getBoundingClientRect().top) / _this.p._.renderer.domElement.clientHeight) * 2 + 1;\n }\n\n _this._.containerXY = {\n x: e ? e.offsetX : null,\n y: e ? e.offsetY : null\n };\n\n _this.updateHoverInfoPosition();\n\n _this.p._.raycaster.setFromCamera(_this._.mouseXY, _this.p._.cameras.camera);\n\n var intersectArr = [];\n\n for (var i = 0; i < _this.p._.tiledWorld.tilesDrawn.length; i++) {\n if (!_this.p._.tiledWorld.tilesDrawn[i].isLODTile) intersectArr.push(_this.p._.tiledWorld.tilesDrawn[i].t);\n }\n\n for (var i = 0; i < _this.p.layers.vector.length; i++) {\n if (_this.p.layers.vector[i].meshes && _this.p.layers.vector[i].meshes.children) for (var j = 0; j < _this.p.layers.vector[i].meshes.children.length; j++) intersectArr.push(_this.p.layers.vector[i].meshes.children[j]);\n }\n\n var intersects = _this.p._.raycaster.intersectObjects(intersectArr);\n\n if (intersects.length > 0) {\n var type_1 = intersects[0].object.type;\n var obj_1 = null;\n\n switch (type_1) {\n case 'Sprite':\n obj_1 = intersects[0].object;\n break;\n\n case 'Line2':\n obj_1 = intersects[0].object;\n break;\n\n case 'Mesh':\n obj_1 = _this.p._.tiledWorld.findTileDrawnBasedOnUUID(intersects[0].object.uuid);\n if (obj_1 == null) return;\n break;\n\n default:\n return;\n break;\n }\n\n var savedIntersectionPoint = intersects[0].point;\n intersects[0].point.y += _this.p.planetCenter.y;\n intersects[0].point = _this.p.projection.rotatePoint3D(intersects[0].point, {\n x: -_this.p.planet.rotation.x,\n y: 0,\n z: 0\n });\n intersects[0].point = _this.p.projection.rotatePoint3D(intersects[0].point, {\n x: 0,\n y: -_this.p.planet.rotation.y,\n z: 0\n });\n intersects[0].point = _this.p.projection.rotatePoint3D(intersects[0].point, {\n x: 0,\n y: 0,\n z: -_this.p.planet.rotation.z\n });\n\n var intersectedLL_1 = _this.p.projection.vector3ToLatLng(intersects[0].point);\n\n intersectedLL_1.height = savedIntersectionPoint.length() * _this.p.projection.radiusScale - _this.p.projection.radii.major;\n\n _this._updateMouseCoords(intersectedLL_1.lng, intersectedLL_1.lat, intersectedLL_1.height);\n\n clearTimeout(_this._.highlightTimeout);\n _this._.highlightTimeout = setTimeout(function () {\n _this._highlightFeature(intersectedLL_1.lng, intersectedLL_1.lat, type_1, obj_1);\n }, 10);\n\n _this.p.controls._onMouseMove(intersectedLL_1.lng, intersectedLL_1.lat, intersectedLL_1.height, e);\n } else {\n _this._updateMouseCoords(null, null, null);\n\n _this._unhighlightHoveredFeature();\n\n _this.p.controls._onMouseMove(null, null, null, e);\n }\n };\n\n this.p = parent;\n this.activeFeature = null;\n this.hoveredFeature = null;\n this.hoverInfo = null;\n this._ = {\n mouseXY: {\n x: null,\n y: null\n },\n prevMouseXY: {\n x: null,\n y: null\n },\n containerXY: {\n x: null,\n y: null\n },\n lastZoomDelta: 1,\n desiredZoom: null,\n zoomedSince: 0,\n zoomWait: 30,\n highlightTimeout: null\n };\n\n this._init();\n }\n\n Events.prototype._init = function () {\n var _this = this;\n\n this._matchPlanetsLODToPlanet();\n\n this.p._.sceneContainer.addEventListener('mousewheel', this._onZoom, false);\n\n this.p._.sceneContainer.addEventListener('DOMMouseScroll', this._onZoom, false);\n\n this.p._.sceneContainer.addEventListener('wheel', this._onZoom, false);\n\n this.p._.sceneContainer.addEventListener('mouseleave', this.p.controls._onMouseOut, false);\n\n this.p._.sceneContainer.addEventListener('touchend', this._onTouchZoom);\n\n this.p._.sceneContainer.addEventListener('mousedown', this._rotateGlobe_MouseDown, false);\n\n this.p._.sceneContainer.addEventListener('mousemove', this._onMouseMove, false);\n\n this.p._.sceneContainer.addEventListener('click', this._onClick, false);\n\n this.p._.sceneContainer.addEventListener('mouseenter', function () {\n _this.p._.mouseIsInScene = true;\n }, false);\n\n this.p._.sceneContainer.addEventListener('mouseleave', function () {\n _this.p._.mouseIsInScene = false;\n }, false);\n };\n\n Events.prototype._rotateAroundArbAxis = function (axis, radians, noPremultiply) {\n var rotationMatrix = new three__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]();\n rotationMatrix.makeRotationAxis(axis.normalize(), radians);\n if (noPremultiply !== true) rotationMatrix.multiply(this.p.planet.matrix);\n this.p.planet.matrix = rotationMatrix;\n this.p.planet.rotation.setFromRotationMatrix(this.p.planet.matrix);\n\n this._matchPlanetsLODToPlanet();\n\n this._refreshFrontGroupRotation();\n };\n\n Events.prototype._checkDesiredZoom = function () {\n this._.zoomedSince++;\n\n if (this._.desiredZoom != null) {\n this.p._.cameras.setNearFarPlane(this._.desiredZoom < 14);\n\n if (this._.zoomedSince > this._.zoomWait) {\n if (this._.desiredZoom >= this.p._.minNativeZoom) this._setZoom(this._.desiredZoom);\n this._.desiredZoom = null;\n }\n }\n };\n\n Events.prototype._setZoom = function (newZoom) {\n var zoomSave = this.p.zoom;\n this.p.zoom = newZoom;\n this.p.trueZoom = Math.max(0, newZoom);\n if (this.p.zoom < 0) this.p.zoom = 0;\n if (this.p.zoom < this.p._.minNativeZoom) this.p.zoom = this.p._.minNativeZoom;\n if (this.p.zoom > this.p._.maxZoom) this.p.zoom = this.p._.maxZoom;\n this._.lastZoomDelta = Math.abs(this.p.zoom - zoomSave);\n };\n\n Events.prototype._matchPlanetsLODToPlanet = function () {\n for (var i = 0; i < this.p.planetsLOD.length; i++) {\n this.p.planetsLOD[i].matrix = this.p.planet.matrix;\n this.p.planetsLOD[i].position.set(this.p.planet.position.x, this.p.planet.position.y, this.p.planet.position.z);\n this.p.planetsLOD[i].rotation.set(this.p.planet.rotation.x, this.p.planet.rotation.y, this.p.planet.rotation.z);\n }\n\n if (this.p.atmosphere) {\n this.p.atmosphere.matrix = this.p.planet.matrix;\n this.p.atmosphere.position.set(this.p.planet.position.x, this.p.planet.position.y, this.p.planet.position.z);\n this.p.atmosphere.rotation.set(this.p.planet.rotation.x, this.p.planet.rotation.y, this.p.planet.rotation.z);\n }\n };\n\n Events.prototype._refreshFrontGroupRotation = function () {\n this.p.frontGroup.rotation.set(this.p.planet.rotation.x, this.p.planet.rotation.y, this.p.planet.rotation.z);\n };\n\n Events.prototype._updateMouseCoords = function (lng, lat, elev) {\n this.p.mouse.lng = lng;\n this.p.mouse.lat = lat;\n this.p.mouse.elev = elev;\n };\n\n Events.prototype.updateHoverInfoPosition = function () {\n if (this.hoverInfo) {\n this.hoverInfo.style.left = this._.containerXY.x + 14 + \"px\";\n this.hoverInfo.style.top = this._.containerXY.y + 14 + \"px\";\n }\n };\n\n Events.prototype._highlightFeature = function (lng, lat, type, obj) {\n var cursor = {\n type: 'Point',\n coordinates: [lng, lat]\n };\n var highlighted = false;\n\n switch (type) {\n case 'Sprite':\n case 'Line2':\n highlighted = true;\n if (obj.feature._highlighted == true) return;\n\n this._unhighlightHoveredFeature();\n\n obj.feature._highlighted = true;\n obj.restyle();\n this.setHoveredFeature({\n layerName: obj.layerName,\n type: type,\n obj: obj,\n feature: obj.feature,\n lnglat: {\n lng: lng,\n lat: lat\n }\n });\n break;\n\n case 'Mesh':\n if (obj && obj.contains) {\n for (var _i = 0, _a = Object.keys(obj.contains).reverse(); _i < _a.length; _i++) {\n var layerName = _a[_i];\n\n for (var _b = 0, _c = obj.contains[layerName].reverse(); _b < _c.length; _b++) {\n var f = _c[_b];\n var feature = Object.assign({}, f);\n\n if (feature.geometry.type.toLowerCase() === 'point') {\n feature = Object(_turf_circle__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(feature.geometry.coordinates, feature._radiusInMeters || 1, {\n steps: 12,\n units: 'meters',\n properties: feature.properties\n });\n }\n\n if (Object(_turf_boolean_intersects__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(feature, cursor)) {\n highlighted = true;\n if (f._highlighted == true) return;\n\n this._unhighlightHoveredFeature();\n\n f._highlighted = true;\n this.setHoveredFeature({\n layerName: layerName,\n type: type,\n obj: obj,\n feature: f,\n lnglat: {\n lng: lng,\n lat: lat\n }\n });\n\n this.p._.tiledWorld.updateClampedRasterForTile(obj, layerName);\n\n break;\n }\n }\n\n if (highlighted) return;\n }\n }\n\n break;\n\n default:\n break;\n }\n\n if (!highlighted) {\n this._unhighlightHoveredFeature();\n }\n };\n\n Events.prototype._unhighlightHoveredFeature = function () {\n if (this.hoveredFeature) {\n this.hoveredFeature.feature._highlighted = false;\n\n switch (this.hoveredFeature.type) {\n case 'Sprite':\n case 'Line2':\n this.hoveredFeature.obj.restyle();\n break;\n\n case 'Mesh':\n this.p._.tiledWorld.updateClampedRasterForTile(this.hoveredFeature.obj, this.hoveredFeature.layerName);\n\n break;\n\n default:\n break;\n }\n\n this.clearHoveredFeature();\n }\n };\n\n Events.prototype.setHoveredFeature = function (hoveredFeature) {\n this.hoveredFeature = hoveredFeature;\n\n if (this.hoverInfo) {\n this.p._.container.removeChild(this.hoverInfo);\n\n this.hoverInfo = null;\n }\n\n this.hoverInfo = document.createElement('div');\n this.hoverInfo.id = '_lithosphere_hover_info';\n var layer = this.p.layers.getLayerByName(this.hoveredFeature.layerName);\n\n if (layer && layer.useKeyAsHoverName) {\n var text = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].getIn(this.hoveredFeature.feature.properties, layer.useKeyAsHoverName.split('.'));\n\n if (text != null) {\n this.hoverInfo.innerHTML = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].capitalizeFirstLetter(layer.useKeyAsHoverName + \": \" + text);\n this.hoverInfo.style.position = 'absolute';\n this.hoverInfo.style.background = 'black';\n this.hoverInfo.style.color = 'white';\n this.hoverInfo.style.fontSize = '16px';\n this.hoverInfo.style.fontFamily = 'sans-serif';\n this.hoverInfo.style.fontWeight = 'bold';\n this.hoverInfo.style.padding = '4px 8px';\n this.updateHoverInfoPosition();\n }\n }\n\n this.p._.container.appendChild(this.hoverInfo);\n\n this.p._.container.style.cursor = 'pointer';\n };\n\n Events.prototype.clearHoveredFeature = function () {\n this.hoveredFeature = null;\n\n if (this.hoverInfo) {\n this.p._.container.removeChild(this.hoverInfo);\n\n this.hoverInfo = null;\n this.p._.container.style.cursor = 'default';\n }\n };\n\n Events.prototype.setActiveFeature = function (activeFeature) {\n this.clearActiveFeature();\n this.activeFeature = activeFeature;\n this.activeFeature.feature._active = true;\n\n switch (this.activeFeature.type) {\n case 'Sprite':\n case 'Line2':\n this.activeFeature.obj.restyle();\n break;\n\n case 'Mesh':\n this.p._.tiledWorld.updateClampedRasterForTile(this.activeFeature.obj, this.activeFeature.layerName);\n\n break;\n\n default:\n break;\n }\n };\n\n Events.prototype.clearActiveFeature = function () {\n if (this.activeFeature) {\n this.activeFeature.feature._active = false;\n\n switch (this.activeFeature.type) {\n case 'Sprite':\n case 'Line2':\n this.activeFeature.obj.restyle();\n break;\n\n case 'Mesh':\n this.p._.tiledWorld.updateClampedRasterForTile(this.activeFeature.obj, this.activeFeature.layerName);\n\n break;\n\n default:\n break;\n }\n }\n\n this.activeFeature = null;\n };\n\n Events.prototype._attenuate = function () {\n var zoomDist = this.p._.cameras.camera.position.distanceTo(this.p._.cameras.controls.target);\n\n var attenuationFactor = zoomDist / 256;\n\n if (this.p.layers.vector) {\n this.p.layers.vector.forEach(function (vectorLayer) {\n if (vectorLayer.meshes && vectorLayer.meshes.children) {\n vectorLayer.meshes.children.forEach(function (mesh) {\n if (mesh instanceof three__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"]) {\n mesh.scale.set(attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius);\n }\n });\n }\n });\n }\n\n if (this.p.frontGroup.children) {\n this.p.frontGroup.children.forEach(function (child) {\n if (child.children && child.children.length > 0) {\n child.children.forEach(function (mesh) {\n if (mesh instanceof three__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"]) {\n mesh.scale.set(attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius);\n }\n });\n } else {\n if (child instanceof three__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"]) {\n child.scale.set(attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius);\n }\n }\n });\n }\n };\n\n return Events;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Events);\n\n//# sourceURL=webpack://LithoSphere/./src/core/events.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _turf_circle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @turf/circle */ \"./node_modules/@turf/circle/dist/es/index.js\");\n/* harmony import */ var _turf_boolean_intersects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @turf/boolean-intersects */ \"./node_modules/@turf/boolean-intersects/dist/es/index.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n\n\n\n\n\nvar Events = function () {\n function Events(parent) {\n var _this = this;\n\n this._rotateGlobe = function (e, prevXY) {\n if (prevXY) {\n _this._.prevMouseXY.x = prevXY.x;\n _this._.prevMouseXY.y = prevXY.y;\n }\n\n if (!e) return;\n if (!e.pageX && e.touches) e.pageX = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageX');\n if (!e.pageY && e.touches) e.pageY = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageY');\n\n if (e.hasOwnProperty('x') && e.hasOwnProperty('y') && _this.p._.cameras.isFirstPerson) {\n _this._.prevMouseXY.x = 0;\n _this._.prevMouseXY.y = 0;\n e.pageX = e.x;\n e.pageY = e.y;\n }\n\n var rotSpeed = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].getRadiansPerPixel(_this.p.trueZoom) * 0.5 * (_this.p._.marsRadius / _this.p.projection.radii.major);\n\n var pixelDif = 0;\n var cpX = new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](_this.p._.cameras.orbit.camera.position.x, 0, _this.p._.cameras.orbit.camera.position.z);\n cpX.applyAxisAngle(new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](0, 1, 0), Math.PI / 2);\n var cpY = new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](_this.p._.cameras.orbit.camera.position.x, 0, _this.p._.cameras.orbit.camera.position.z);\n\n if (e.pageY < _this._.prevMouseXY.y) {\n pixelDif = Math.abs(e.pageY - _this._.prevMouseXY.y);\n\n _this._rotateAroundArbAxis(cpX, rotSpeed * pixelDif);\n } else if (e.pageY > _this._.prevMouseXY.y) {\n pixelDif = Math.abs(e.pageY - _this._.prevMouseXY.y);\n\n _this._rotateAroundArbAxis(cpX, -rotSpeed * pixelDif);\n }\n\n if (e.pageX > _this._.prevMouseXY.x) {\n pixelDif = Math.abs(e.pageX - _this._.prevMouseXY.x);\n\n _this._rotateAroundArbAxis(cpY, -rotSpeed * pixelDif);\n } else if (e.pageX < _this._.prevMouseXY.x) {\n pixelDif = Math.abs(e.pageX - _this._.prevMouseXY.x);\n\n _this._rotateAroundArbAxis(cpY, rotSpeed * pixelDif);\n }\n\n _this._.prevMouseXY.x = e.pageX;\n _this._.prevMouseXY.y = e.pageY;\n\n if (_this.p.zoom <= _this.p._.zCutOff) {\n _this.p._.cameras.orbit.controls.target.x = 0;\n _this.p._.cameras.orbit.controls.target.y = -_this.p.planetCenter.y;\n _this.p._.cameras.orbit.controls.target.z = 0;\n\n _this.p._.cameras.orbit.controls.update();\n } else {\n var elevRaw = _this.p.getCenterElevationRaw();\n\n if (elevRaw != null) {\n var newLookAtY = -(elevRaw + _this.p.planetCenter.y);\n if (newLookAtY != 0 && newLookAtY != -10000) _this.p._.cameras.orbit.controls.target.y = newLookAtY - _this.p.options.targetYOffset;\n }\n\n var center = _this.p.getCenter();\n\n _this.p.controls._onMove(center.lng, center.lat, center.height);\n }\n };\n\n this._rotateGlobe_MouseDown = function (e) {\n if (e.which === 1 || e.button === 0) {\n _this._.prevMouseXY.x = e.pageX;\n _this._.prevMouseXY.y = e.pageY;\n\n _this.p._.sceneContainer.addEventListener('mousemove', _this._rotateGlobe, false);\n\n _this.p._.sceneContainer.addEventListener('mouseup', _this._rotateGlobe_MouseUp, false);\n\n _this.p._.sceneContainer.addEventListener('mouseleave', _this._rotateGlobe_MouseUp, false);\n } else if (e.touches && e.touches.length > 2) {\n _this._.prevMouseXY.x = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageX');\n _this._.prevMouseXY.y = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].arrayAverage(e.touches, 'pageY');\n\n _this.p._.sceneContainer.addEventListener('touchmove', _this._rotateGlobe, false);\n\n _this.p._.sceneContainer.addEventListener('touchend', _this._rotateGlobe_MouseUp, false);\n }\n };\n\n this._rotateGlobe_MouseUp = function (e) {\n _this.p._.sceneContainer.removeEventListener('mousemove', _this._rotateGlobe);\n\n _this.p._.sceneContainer.removeEventListener('mouseup', _this._rotateGlobe_MouseUp);\n\n _this.p._.sceneContainer.removeEventListener('mouseleave', _this._rotateGlobe_MouseUp);\n\n _this.p._.sceneContainer.removeEventListener('touchmove', _this._rotateGlobe);\n\n _this.p._.sceneContainer.removeEventListener('touchend', _this._rotateGlobe_MouseUp);\n };\n\n this._onZoom = function (e) {\n _this._.zoomedSince = 0;\n\n var zoomDist = _this.p._.cameras.orbit.camera.position.distanceTo(_this.p._.cameras.orbit.controls.target);\n\n var nf = 8 - (_this.p.projection.radiusScale.toString().length - 1);\n var dZoom = Math.ceil((nf * Math.log(2) - Math.log(zoomDist / Math.pow(5, nf - 1))) / Math.log(2)) + 1;\n _this._.desiredZoom = dZoom;\n\n _this._attenuate();\n };\n\n this._onTouchZoom = function (e) {\n if (e.touches && e.touches.length == 1) _this._onZoom(e);\n };\n\n this._onClick = function (e) {\n if (_this.hoveredFeature && _this.hoverInfo) {\n var layer = _this.p.layers.getLayerByName(_this.hoveredFeature.layerName);\n\n if (layer) {\n _this.setActiveFeature({\n layerName: _this.hoveredFeature.layerName,\n type: _this.hoveredFeature.type,\n obj: _this.hoveredFeature.obj,\n feature: _this.hoveredFeature.feature || _this.hoveredFeature.obj.feature,\n lnglat: {\n lng: _this.hoveredFeature.lnglat.lng,\n lat: _this.hoveredFeature.lnglat.lat\n }\n });\n\n if (typeof layer.onClick === 'function') {\n layer.onClick(JSON.parse(JSON.stringify(_this.hoveredFeature.feature)), JSON.parse(JSON.stringify(_this.hoveredFeature.lnglat)), layer);\n }\n }\n }\n };\n\n this._onKeyDown = function (e) {\n if (_this.p._.cameras.isFirstPerson) return;\n var speed = e.shiftKey ? 20 : 8;\n\n switch (e.key) {\n case 'w':\n case 'ArrowUp':\n _this._rotateGlobe({\n pageX: 0,\n pageY: speed\n }, {\n x: 0,\n y: 0\n });\n\n break;\n\n case 'a':\n case 'ArrowLeft':\n _this._rotateGlobe({\n pageX: speed,\n pageY: 0\n }, {\n x: 0,\n y: 0\n });\n\n break;\n\n case 's':\n case 'ArrowDown':\n _this._rotateGlobe({\n pageX: 0,\n pageY: -speed\n }, {\n x: 0,\n y: 0\n });\n\n break;\n\n case 'd':\n case 'ArrowRight':\n _this._rotateGlobe({\n pageX: -speed,\n pageY: 0\n }, {\n x: 0,\n y: 0\n });\n\n break;\n\n case 'g':\n case 'PageDown':\n var lerpedDown = new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]().lerpVectors(_this.p._.cameras.orbit.camera.position, _this.p._.cameras.orbit.controls.target, e.shiftKey ? -0.035 : -0.02);\n\n _this.p._.cameras.orbit.camera.position.set(lerpedDown.x, lerpedDown.y, lerpedDown.z);\n\n _this._onZoom();\n\n break;\n\n case 't':\n case 'PageUp':\n var lerpedUp = new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"]().lerpVectors(_this.p._.cameras.orbit.camera.position, _this.p._.cameras.orbit.controls.target, e.shiftKey ? 0.035 : 0.02);\n\n _this.p._.cameras.orbit.camera.position.set(lerpedUp.x, lerpedUp.y, lerpedUp.z);\n\n _this._onZoom();\n\n break;\n\n case 'q':\n _this.p._.cameras.orbit.controls.rotateLeft(Math.PI / 64);\n\n break;\n\n case 'e':\n _this.p._.cameras.orbit.controls.rotateLeft(-Math.PI / 64);\n\n break;\n\n case 'r':\n _this.p._.cameras.orbit.controls.rotateUp(Math.PI / 64);\n\n break;\n\n case 'f':\n _this.p._.cameras.orbit.controls.rotateUp(-Math.PI / 64);\n\n break;\n }\n };\n\n this._onMouseMove = function (e) {\n _this.p._.mouseIsInScene = true;\n\n if (_this.p._.cameras.isFirstPerson) {\n _this._.mouseXY.x = 0;\n _this._.mouseXY.y = 0;\n } else {\n _this._.mouseXY.x = (e.clientX - _this.p._.renderer.domElement.getBoundingClientRect().left) / _this.p._.renderer.domElement.clientWidth * 2 - 1;\n _this._.mouseXY.y = -((e.clientY - _this.p._.renderer.domElement.getBoundingClientRect().top) / _this.p._.renderer.domElement.clientHeight) * 2 + 1;\n }\n\n _this._.containerXY = {\n x: e ? e.offsetX : null,\n y: e ? e.offsetY : null\n };\n\n _this.updateHoverInfoPosition();\n\n _this.p._.raycaster.setFromCamera(_this._.mouseXY, _this.p._.cameras.camera);\n\n var intersectArr = [];\n\n for (var i = 0; i < _this.p._.tiledWorld.tilesDrawn.length; i++) {\n if (!_this.p._.tiledWorld.tilesDrawn[i].isLODTile) intersectArr.push(_this.p._.tiledWorld.tilesDrawn[i].t);\n }\n\n for (var i = 0; i < _this.p.layers.vector.length; i++) {\n if (_this.p.layers.vector[i].meshes && _this.p.layers.vector[i].meshes.children) for (var j = 0; j < _this.p.layers.vector[i].meshes.children.length; j++) intersectArr.push(_this.p.layers.vector[i].meshes.children[j]);\n }\n\n var intersects = _this.p._.raycaster.intersectObjects(intersectArr);\n\n if (intersects.length > 0) {\n var type_1 = intersects[0].object.type;\n var obj_1 = null;\n\n switch (type_1) {\n case 'Sprite':\n obj_1 = intersects[0].object;\n break;\n\n case 'Line2':\n obj_1 = intersects[0].object;\n break;\n\n case 'Mesh':\n obj_1 = _this.p._.tiledWorld.findTileDrawnBasedOnUUID(intersects[0].object.uuid);\n if (obj_1 == null) return;\n break;\n\n default:\n return;\n break;\n }\n\n var savedIntersectionPoint = intersects[0].point;\n intersects[0].point.y += _this.p.planetCenter.y;\n intersects[0].point = _this.p.projection.rotatePoint3D(intersects[0].point, {\n x: -_this.p.planet.rotation.x,\n y: 0,\n z: 0\n });\n intersects[0].point = _this.p.projection.rotatePoint3D(intersects[0].point, {\n x: 0,\n y: -_this.p.planet.rotation.y,\n z: 0\n });\n intersects[0].point = _this.p.projection.rotatePoint3D(intersects[0].point, {\n x: 0,\n y: 0,\n z: -_this.p.planet.rotation.z\n });\n\n var intersectedLL_1 = _this.p.projection.vector3ToLatLng(intersects[0].point);\n\n intersectedLL_1.height = savedIntersectionPoint.length() * _this.p.projection.radiusScale - _this.p.projection.radii.major;\n\n _this._updateMouseCoords(intersectedLL_1.lng, intersectedLL_1.lat, intersectedLL_1.height);\n\n clearTimeout(_this._.highlightTimeout);\n _this._.highlightTimeout = setTimeout(function () {\n _this._highlightFeature(intersectedLL_1.lng, intersectedLL_1.lat, type_1, obj_1);\n }, 10);\n\n _this.p.controls._onMouseMove(intersectedLL_1.lng, intersectedLL_1.lat, intersectedLL_1.height, e);\n } else {\n _this._updateMouseCoords(null, null, null);\n\n _this._unhighlightHoveredFeature();\n\n _this.p.controls._onMouseMove(null, null, null, e);\n }\n };\n\n this.p = parent;\n this.activeFeature = null;\n this.hoveredFeature = null;\n this.hoverInfo = null;\n this._ = {\n mouseXY: {\n x: null,\n y: null\n },\n prevMouseXY: {\n x: null,\n y: null\n },\n containerXY: {\n x: null,\n y: null\n },\n lastZoomDelta: 1,\n desiredZoom: null,\n zoomedSince: 0,\n zoomWait: 30,\n highlightTimeout: null\n };\n\n this._init();\n }\n\n Events.prototype._init = function () {\n var _this = this;\n\n this._matchPlanetsLODToPlanet();\n\n this.p._.sceneContainer.addEventListener('mousewheel', this._onZoom, false);\n\n this.p._.sceneContainer.addEventListener('DOMMouseScroll', this._onZoom, false);\n\n this.p._.sceneContainer.addEventListener('wheel', this._onZoom, false);\n\n this.p._.sceneContainer.addEventListener('mouseleave', this.p.controls._onMouseOut, false);\n\n this.p._.sceneContainer.addEventListener('touchend', this._onTouchZoom);\n\n this.p._.sceneContainer.addEventListener('mousedown', this._rotateGlobe_MouseDown, false);\n\n this.p._.sceneContainer.addEventListener('mousemove', this._onMouseMove, false);\n\n this.p._.sceneContainer.addEventListener('click', this._onClick, false);\n\n this.p._.sceneContainer.addEventListener('mouseenter', function () {\n _this.p._.mouseIsInScene = true;\n }, false);\n\n this.p._.sceneContainer.addEventListener('mouseleave', function () {\n _this.p._.mouseIsInScene = false;\n }, false);\n\n window.addEventListener('keydown', this._onKeyDown, false);\n };\n\n Events.prototype._rotateAroundArbAxis = function (axis, radians, noPremultiply) {\n var rotationMatrix = new three__WEBPACK_IMPORTED_MODULE_0__[\"Matrix4\"]();\n rotationMatrix.makeRotationAxis(axis.normalize(), radians);\n if (noPremultiply !== true) rotationMatrix.multiply(this.p.planet.matrix);\n this.p.planet.matrix = rotationMatrix;\n this.p.planet.rotation.setFromRotationMatrix(this.p.planet.matrix);\n\n this._matchPlanetsLODToPlanet();\n\n this._refreshFrontGroupRotation();\n };\n\n Events.prototype._checkDesiredZoom = function () {\n this._.zoomedSince++;\n\n if (this._.desiredZoom != null) {\n this.p._.cameras.setNearFarPlane(this._.desiredZoom < 14);\n\n if (this._.zoomedSince > this._.zoomWait) {\n if (this._.desiredZoom >= this.p._.minNativeZoom) this._setZoom(this._.desiredZoom);\n this._.desiredZoom = null;\n }\n }\n };\n\n Events.prototype._setZoom = function (newZoom) {\n var zoomSave = this.p.zoom;\n this.p.zoom = newZoom;\n this.p.trueZoom = Math.max(0, newZoom);\n if (this.p.zoom < 0) this.p.zoom = 0;\n if (this.p.zoom < this.p._.minNativeZoom) this.p.zoom = this.p._.minNativeZoom;\n if (this.p.zoom > this.p._.maxZoom) this.p.zoom = this.p._.maxZoom;\n this._.lastZoomDelta = Math.abs(this.p.zoom - zoomSave);\n };\n\n Events.prototype._matchPlanetsLODToPlanet = function () {\n for (var i = 0; i < this.p.planetsLOD.length; i++) {\n this.p.planetsLOD[i].matrix = this.p.planet.matrix;\n this.p.planetsLOD[i].position.set(this.p.planet.position.x, this.p.planet.position.y, this.p.planet.position.z);\n this.p.planetsLOD[i].rotation.set(this.p.planet.rotation.x, this.p.planet.rotation.y, this.p.planet.rotation.z);\n }\n\n if (this.p.atmosphere) {\n this.p.atmosphere.matrix = this.p.planet.matrix;\n this.p.atmosphere.position.set(this.p.planet.position.x, this.p.planet.position.y, this.p.planet.position.z);\n this.p.atmosphere.rotation.set(this.p.planet.rotation.x, this.p.planet.rotation.y, this.p.planet.rotation.z);\n }\n };\n\n Events.prototype._refreshFrontGroupRotation = function () {\n this.p.frontGroup.rotation.set(this.p.planet.rotation.x, this.p.planet.rotation.y, this.p.planet.rotation.z);\n };\n\n Events.prototype._updateMouseCoords = function (lng, lat, elev) {\n this.p.mouse.lng = lng;\n this.p.mouse.lat = lat;\n this.p.mouse.elev = elev;\n };\n\n Events.prototype.updateHoverInfoPosition = function () {\n if (this.hoverInfo) {\n this.hoverInfo.style.left = this._.containerXY.x + 14 + \"px\";\n this.hoverInfo.style.top = this._.containerXY.y + 14 + \"px\";\n }\n };\n\n Events.prototype._highlightFeature = function (lng, lat, type, obj) {\n var cursor = {\n type: 'Point',\n coordinates: [lng, lat]\n };\n var highlighted = false;\n\n switch (type) {\n case 'Sprite':\n case 'Line2':\n highlighted = true;\n if (obj.feature._highlighted == true) return;\n\n this._unhighlightHoveredFeature();\n\n obj.feature._highlighted = true;\n obj.restyle();\n this.setHoveredFeature({\n layerName: obj.layerName,\n type: type,\n obj: obj,\n feature: obj.feature,\n lnglat: {\n lng: lng,\n lat: lat\n }\n });\n break;\n\n case 'Mesh':\n if (obj && obj.contains) {\n for (var _i = 0, _a = Object.keys(obj.contains).reverse(); _i < _a.length; _i++) {\n var layerName = _a[_i];\n\n for (var _b = 0, _c = obj.contains[layerName].reverse(); _b < _c.length; _b++) {\n var f = _c[_b];\n var feature = Object.assign({}, f);\n\n if (feature.geometry.type.toLowerCase() === 'point') {\n feature = Object(_turf_circle__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(feature.geometry.coordinates, feature._radiusInMeters || 1, {\n steps: 12,\n units: 'meters',\n properties: feature.properties\n });\n }\n\n if (Object(_turf_boolean_intersects__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(feature, cursor)) {\n highlighted = true;\n if (f._highlighted == true) return;\n\n this._unhighlightHoveredFeature();\n\n f._highlighted = true;\n this.setHoveredFeature({\n layerName: layerName,\n type: type,\n obj: obj,\n feature: f,\n lnglat: {\n lng: lng,\n lat: lat\n }\n });\n\n this.p._.tiledWorld.updateClampedRasterForTile(obj, layerName);\n\n break;\n }\n }\n\n if (highlighted) return;\n }\n }\n\n break;\n\n default:\n break;\n }\n\n if (!highlighted) {\n this._unhighlightHoveredFeature();\n }\n };\n\n Events.prototype._unhighlightHoveredFeature = function () {\n if (this.hoveredFeature) {\n this.hoveredFeature.feature._highlighted = false;\n\n switch (this.hoveredFeature.type) {\n case 'Sprite':\n case 'Line2':\n this.hoveredFeature.obj.restyle();\n break;\n\n case 'Mesh':\n this.p._.tiledWorld.updateClampedRasterForTile(this.hoveredFeature.obj, this.hoveredFeature.layerName);\n\n break;\n\n default:\n break;\n }\n\n this.clearHoveredFeature();\n }\n };\n\n Events.prototype.setHoveredFeature = function (hoveredFeature) {\n this.hoveredFeature = hoveredFeature;\n\n if (this.hoverInfo) {\n this.p._.container.removeChild(this.hoverInfo);\n\n this.hoverInfo = null;\n }\n\n this.hoverInfo = document.createElement('div');\n this.hoverInfo.id = '_lithosphere_hover_info';\n var layer = this.p.layers.getLayerByName(this.hoveredFeature.layerName);\n\n if (layer && layer.useKeyAsHoverName) {\n var text = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].getIn(this.hoveredFeature.feature.properties, layer.useKeyAsHoverName.split('.'));\n\n if (text != null) {\n this.hoverInfo.innerHTML = _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].capitalizeFirstLetter(layer.useKeyAsHoverName + \": \" + text);\n this.hoverInfo.style.position = 'absolute';\n this.hoverInfo.style.background = 'black';\n this.hoverInfo.style.color = 'white';\n this.hoverInfo.style.fontSize = '16px';\n this.hoverInfo.style.fontFamily = 'sans-serif';\n this.hoverInfo.style.fontWeight = 'bold';\n this.hoverInfo.style.padding = '4px 8px';\n this.updateHoverInfoPosition();\n }\n }\n\n this.p._.container.appendChild(this.hoverInfo);\n\n this.p._.container.style.cursor = 'pointer';\n };\n\n Events.prototype.clearHoveredFeature = function () {\n this.hoveredFeature = null;\n\n if (this.hoverInfo) {\n this.p._.container.removeChild(this.hoverInfo);\n\n this.hoverInfo = null;\n this.p._.container.style.cursor = 'default';\n }\n };\n\n Events.prototype.setActiveFeature = function (activeFeature) {\n this.clearActiveFeature();\n this.activeFeature = activeFeature;\n this.activeFeature.feature._active = true;\n\n switch (this.activeFeature.type) {\n case 'Sprite':\n case 'Line2':\n this.activeFeature.obj.restyle();\n break;\n\n case 'Mesh':\n this.p._.tiledWorld.updateClampedRasterForTile(this.activeFeature.obj, this.activeFeature.layerName);\n\n break;\n\n default:\n break;\n }\n };\n\n Events.prototype.clearActiveFeature = function () {\n if (this.activeFeature) {\n this.activeFeature.feature._active = false;\n\n switch (this.activeFeature.type) {\n case 'Sprite':\n case 'Line2':\n this.activeFeature.obj.restyle();\n break;\n\n case 'Mesh':\n this.p._.tiledWorld.updateClampedRasterForTile(this.activeFeature.obj, this.activeFeature.layerName);\n\n break;\n\n default:\n break;\n }\n }\n\n this.activeFeature = null;\n };\n\n Events.prototype._attenuate = function () {\n var zoomDist = this.p._.cameras.camera.position.distanceTo(this.p._.cameras.controls.target);\n\n var attenuationFactor = zoomDist / 256;\n\n if (this.p.layers.vector) {\n this.p.layers.vector.forEach(function (vectorLayer) {\n if (vectorLayer.meshes && vectorLayer.meshes.children) {\n vectorLayer.meshes.children.forEach(function (mesh) {\n if (mesh instanceof three__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"]) {\n mesh.scale.set(attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius);\n }\n });\n }\n });\n }\n\n if (this.p.frontGroup.children) {\n this.p.frontGroup.children.forEach(function (child) {\n if (child.children && child.children.length > 0) {\n child.children.forEach(function (mesh) {\n if (mesh instanceof three__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"]) {\n mesh.scale.set(attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius);\n }\n });\n } else {\n if (child instanceof three__WEBPACK_IMPORTED_MODULE_0__[\"Sprite\"]) {\n child.scale.set(attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius, attenuationFactor * mesh.style.radius);\n }\n }\n });\n }\n };\n\n return Events;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Events);\n\n//# sourceURL=webpack://LithoSphere/./src/core/events.ts?"); /***/ }), @@ -1924,7 +1972,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ren /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _CRS__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./CRS */ \"./src/core/CRS.ts\");\n\nvar RadiusE;\n\n(function (RadiusE) {\n RadiusE[\"Major\"] = \"major\";\n RadiusE[\"Minor\"] = \"minor\";\n})(RadiusE || (RadiusE = {}));\n\nvar Projection = function () {\n function Projection(majorRadius, minorRadius, tileMapResource, trueTileResolution) {\n var _this = this;\n\n this.setRadius = function (radius, which) {\n if (which === void 0) {\n which = RadiusE.Major;\n }\n\n if (which.toLowerCase() == 'major') _this.radii.major = radius || _this.baseRadius;else if (which.toLowerCase() == 'minor') _this.radii.minor = radius || _this.radii.major || _this.baseRadius;\n };\n\n this.invertY = function (y, z) {\n return Math.pow(2, z) - 1 - y;\n };\n\n this.toBounds = function (a, b) {\n var bounds = {\n min: {\n x: null,\n y: null\n },\n max: {\n x: null,\n y: null\n }\n };\n bounds.min.x = Math.min(a.x, b.x);\n bounds.max.x = Math.max(a.x, b.x);\n bounds.min.y = Math.min(a.y, b.y);\n bounds.max.y = Math.max(a.y, b.y);\n return bounds;\n };\n\n this.tileXYZ2NwSe = function (xyz, tileResolution, asBounds, stretchFactor) {\n if (_this.tileMapResource.proj == null) return null;\n stretchFactor = Math.max(stretchFactor || 1, 1);\n var stretchAmount = (stretchFactor - 1) * tileResolution;\n var nwPoint = {\n x: xyz.x * tileResolution - stretchAmount,\n y: xyz.y * tileResolution - stretchAmount\n };\n var sePoint = {\n x: nwPoint.x + tileResolution + stretchAmount * 2,\n y: nwPoint.y + tileResolution + stretchAmount * 2\n };\n\n var nw = _this.crs.pointToLatLng(nwPoint, xyz.z);\n\n var se = _this.crs.pointToLatLng(sePoint, xyz.z);\n\n if (asBounds) return _this.toBounds(_this.crs.project(nw), _this.crs.project(se));\n return {\n nw: nw,\n se: se\n };\n };\n\n this.tileXYZ2LatLng = function (x, y, z, flatXYZ) {\n if (_this.tileMapResource.proj == null) {\n var lng = x / Math.pow(2, z) * 360 - 180;\n var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);\n var lat = 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));\n return {\n lat: lat,\n lng: lng\n };\n } else {\n y = -y;\n var easting = _this.trueTileResolution * x * _this.res[z] + _this.tileMapResource.origin[0];\n var northing = _this.trueTileResolution * y * _this.res[z] + _this.tileMapResource.origin[1];\n return _this.crs.unproject({\n x: easting,\n y: northing\n });\n }\n };\n\n this.latLngZ2TileXYZ = function (lat, lng, z, dontFloor) {\n if (_this.tileMapResource.proj == null) {\n var x = (lng + 180) / 360 * Math.pow(2, z);\n var y = (1 - Math.log(Math.tan(lat * (Math.PI / 180)) + 1 / Math.cos(lat * (Math.PI / 180))) / Math.PI) / 2 * Math.pow(2, z);\n\n if (dontFloor == null) {\n x = Math.floor(x);\n y = Math.floor(y);\n }\n\n return {\n x: x,\n y: y,\n z: z\n };\n } else {\n var p = _this.crs.project({\n lng: lng,\n lat: lat\n });\n\n var easting = p.x;\n var northing = p.y;\n var x = (easting - _this.tileMapResource.origin[0]) / (_this.trueTileResolution * _this.res[z]);\n var y = (northing - _this.tileMapResource.origin[1]) / (_this.trueTileResolution * _this.res[z]);\n y = -y;\n return {\n x: x,\n y: y,\n z: z\n };\n }\n };\n\n this.vector3ToLatLng = function (xyz) {\n var y = xyz.y;\n var z = xyz.z;\n xyz.y = -z;\n xyz.z = -y;\n var rs = _this.radii.major / _this.radiusScale;\n var rs2 = _this.radii.minor / _this.radiusScale;\n var r = Math.sqrt(Math.pow(xyz.x, 2) + Math.pow(xyz.y, 2));\n var E2 = Math.pow(rs, 2) - Math.pow(rs2, 2);\n var F = 54 * Math.pow(rs, 2) * Math.pow(xyz.z, 2);\n var G = Math.pow(r, 2) + (1 - Math.pow(_this.e, 2)) * Math.pow(xyz.z, 2) - Math.pow(_this.e, 2) * E2;\n var C = Math.pow(_this.e, 4) * F * Math.pow(r, 2) / Math.pow(G, 3);\n var S = Math.cbrt(1 + C + Math.sqrt(Math.pow(C, 2) + 2 * C));\n var P = F / (3 * Math.pow(S + 1 / S + 1, 2) * Math.pow(G, 2));\n var Q = Math.sqrt(1 + 2 * Math.pow(_this.e, 4) * P);\n var r0 = -(P * Math.pow(_this.e, 2) * r) / (1 + Q) + Math.sqrt(0.5 * Math.pow(rs, 2) * (1 + 1 / Q) - P * (1 - Math.pow(_this.e, 2)) * Math.pow(xyz.z, 2) / (Q * (1 + Q)) - 0.5 * P * Math.pow(r, 2));\n var U = Math.sqrt(r - Math.pow(_this.e, 2) * r0 + Math.pow(xyz.z, 2));\n var V = Math.sqrt(Math.pow(r - Math.pow(_this.e, 2) * r0, 2) + (1 - Math.pow(_this.e, 2)) * Math.pow(xyz.z, 2));\n var Z0 = Math.pow(rs2, 2) * xyz.z / (rs * V);\n var h = U * (1 - Math.pow(rs2, 2) / (rs * V));\n var phi = Math.atan((xyz.z + Math.pow(_this.ep, 2) * Z0) / r) * (180 / Math.PI);\n var lambda = -(Math.atan2(xyz.y, xyz.x) * (180 / Math.PI)) - 90;\n if (lambda < -180) lambda += 360;\n return {\n lat: phi,\n lng: lambda,\n height: h\n };\n };\n\n this.lonLatToVector3 = function (lon, lat, height) {\n var phi = lat * (Math.PI / 180);\n var theta = (lon - 180) * (Math.PI / 180);\n var x = (_this.radii.major + height) / _this.radiusScale * Math.cos(phi) * Math.sin(theta);\n var y = -(_this.radii.major + height) / _this.radiusScale * Math.sin(phi);\n var z = -(_this.radii.major + height) / _this.radiusScale * Math.cos(phi) * Math.cos(theta);\n return {\n x: x,\n y: y,\n z: z\n };\n };\n\n this.rotatePoint3D = function (pt, angle, center) {\n if (center == undefined) center = {\n x: 0,\n y: 0,\n z: 0\n };\n var dx = pt.x - center.x;\n var dy = pt.y - center.y;\n var dz = pt.z - center.z;\n var sx = Math.sin(angle.x);\n var cx = Math.cos(angle.x);\n var sy = Math.sin(angle.y);\n var cy = Math.cos(angle.y);\n var sz = Math.sin(angle.z);\n var cz = Math.cos(angle.z);\n var x = center.x + dx * (cy * cz) + dy * (-cy * sz) + dz * sy;\n var y = center.y + dx * (cx * sz + sx * sy * cz) + dy * (cx * cz - sx * sy * sz) + dz * (-sx * cy);\n var z = center.z + dx * (sx * sz - cx * sy * cz) + dy * (sx * cz + cx * sy * sz) + dz * (cx * cy);\n return {\n x: x,\n y: y,\n z: z\n };\n };\n\n this.lon2tileUnfloored = function (lon, zoom) {\n return (lon + 180) / 360 * Math.pow(2, zoom);\n };\n\n this.lat2tileUnfloored = function (lat, zoom) {\n return (1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom);\n };\n\n this.lngLatDistBetween = function (lon1, lat1, lon2, lat2) {\n var R = _this.radii.major / _this.radiusScale;\n var φ1 = lat1 * (Math.PI / 180);\n var φ2 = lat2 * (Math.PI / 180);\n var Δφ = (lat2 - lat1) * (Math.PI / 180);\n var Δλ = (lon2 - lon1) * (Math.PI / 180);\n var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);\n var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n return R * c;\n };\n\n this._reset();\n\n this.setRadius(majorRadius, RadiusE.Major);\n this.setRadius(minorRadius, RadiusE.Minor);\n this.tileMapResource = tileMapResource || {\n bounds: null,\n origin: null,\n crsCode: null,\n epsg: null,\n proj: null,\n resunitsperpixel: null,\n reszoomlevel: null\n };\n this.tileMapResource.crsCode = this.tileMapResource.crsCode || 'EPSG:4326';\n this.trueTileResolution = trueTileResolution || 256;\n\n if (this.tileMapResource.resunitsperpixel != null && this.tileMapResource.reszoomlevel != null) {\n var reszoomlevel = this.tileMapResource.reszoomlevel;\n reszoomlevel += Math.round(4 * Math.PI * Math.pow(3396190, 2) / (4 * Math.PI * Math.pow(this.radii.major, 2)));\n var baseRes = this.tileMapResource.resunitsperpixel * Math.pow(2, reszoomlevel);\n var res = [];\n\n for (var i = 0; i < 32; i++) {\n res.push(baseRes / Math.pow(2, i));\n }\n\n this.res = res;\n }\n\n var tmr = this.tileMapResource;\n this.crs = new _CRS__WEBPACK_IMPORTED_MODULE_0__[\"default\"](Number.isFinite(parseInt(tmr.crsCode[0])) ? \"EPSG:\" + tmr.epsg : tmr.crsCode, tmr.proj, {\n origin: [parseFloat(tmr.origin[0]), parseFloat(tmr.origin[1])],\n resolutions: this.res,\n bounds: [[parseFloat(tmr.bounds[0]), parseFloat(tmr.bounds[1])], [parseFloat(tmr.bounds[2]), parseFloat(tmr.bounds[3])]]\n }, parseFloat(this.radii.major));\n }\n\n Projection.prototype._reset = function () {\n this.baseRadius = 6371000;\n this.radiusScale = 1;\n this.radii = {\n major: this.baseRadius,\n minor: this.baseRadius\n };\n this.tileMapResource = {\n bounds: null,\n origin: null,\n crsCode: 'EPSG:4326',\n proj: null,\n resunitsperpixel: null,\n reszoomlevel: null\n };\n this.e = 0;\n this.ep = 0;\n this.flatteningFactor = 0;\n };\n\n return Projection;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Projection);\n\n//# sourceURL=webpack://LithoSphere/./src/core/projection.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _CRS__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./CRS */ \"./src/core/CRS.ts\");\n\nvar RadiusE;\n\n(function (RadiusE) {\n RadiusE[\"Major\"] = \"major\";\n RadiusE[\"Minor\"] = \"minor\";\n})(RadiusE || (RadiusE = {}));\n\nvar Projection = function () {\n function Projection(majorRadius, minorRadius, tileMapResource, trueTileResolution) {\n var _this = this;\n\n this.setRadius = function (radius, which) {\n if (which === void 0) {\n which = RadiusE.Major;\n }\n\n if (which.toLowerCase() == 'major') _this.radii.major = radius || _this.baseRadius;else if (which.toLowerCase() == 'minor') _this.radii.minor = radius || _this.radii.major || _this.baseRadius;\n };\n\n this.invertY = function (y, z) {\n var b = _this.crs.projection.bounds;\n\n if (_this.tileMapResource.crsCode === 'EPSG:4326') {\n return Math.pow(2, z) - 1 - y;\n }\n\n var s = _this.crs.scale(z);\n\n var max = _this.crs.transformation.transform(b.min, s);\n\n var yMax = Math.ceil(max.y / 256) - 1;\n return yMax - y;\n };\n\n this.toBounds = function (a, b) {\n var bounds = {\n min: {\n x: null,\n y: null\n },\n max: {\n x: null,\n y: null\n }\n };\n bounds.min.x = Math.min(a.x, b.x);\n bounds.max.x = Math.max(a.x, b.x);\n bounds.min.y = Math.min(a.y, b.y);\n bounds.max.y = Math.max(a.y, b.y);\n return bounds;\n };\n\n this.tileXYZ2NwSe = function (xyz, tileResolution, asBounds, stretchFactor) {\n if (_this.tileMapResource.proj == null) return null;\n stretchFactor = Math.max(stretchFactor || 1, 1);\n var stretchAmount = (stretchFactor - 1) * tileResolution;\n var nwPoint = {\n x: xyz.x * tileResolution - stretchAmount,\n y: xyz.y * tileResolution - stretchAmount\n };\n var sePoint = {\n x: nwPoint.x + tileResolution + stretchAmount * 2,\n y: nwPoint.y + tileResolution + stretchAmount * 2\n };\n\n var nw = _this.crs.pointToLatLng(nwPoint, xyz.z);\n\n var se = _this.crs.pointToLatLng(sePoint, xyz.z);\n\n if (asBounds) return _this.toBounds(_this.crs.project(nw), _this.crs.project(se));\n return {\n nw: nw,\n se: se\n };\n };\n\n this.tileXYZ2LatLng = function (x, y, z, flatXYZ) {\n if (_this.tileMapResource.proj == null) {\n var lng = x / Math.pow(2, z) * 360 - 180;\n var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);\n var lat = 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));\n return {\n lat: lat,\n lng: lng\n };\n } else {\n y = -y;\n var easting = _this.trueTileResolution * x * _this.res[z] + _this.tileMapResource.origin[0];\n var northing = _this.trueTileResolution * y * _this.res[z] + _this.tileMapResource.origin[1];\n return _this.crs.unproject({\n x: easting,\n y: northing\n });\n }\n };\n\n this.latLngZ2TileXYZ = function (lat, lng, z, dontFloor) {\n if (_this.tileMapResource.proj == null) {\n var x = (lng + 180) / 360 * Math.pow(2, z);\n var y = (1 - Math.log(Math.tan(lat * (Math.PI / 180)) + 1 / Math.cos(lat * (Math.PI / 180))) / Math.PI) / 2 * Math.pow(2, z);\n\n if (dontFloor == null) {\n x = Math.floor(x);\n y = Math.floor(y);\n }\n\n return {\n x: x,\n y: y,\n z: z\n };\n } else {\n var p = _this.crs.project({\n lng: lng,\n lat: lat\n });\n\n var easting = p.x;\n var northing = p.y;\n var x = (easting - _this.tileMapResource.origin[0]) / (_this.trueTileResolution * _this.res[z]);\n var y = (northing - _this.tileMapResource.origin[1]) / (_this.trueTileResolution * _this.res[z]);\n y = -y;\n return {\n x: x,\n y: y,\n z: z\n };\n }\n };\n\n this.vector3ToLatLng = function (xyz) {\n var y = xyz.y;\n var z = xyz.z;\n xyz.y = -z;\n xyz.z = -y;\n var rs = _this.radii.major / _this.radiusScale;\n var rs2 = _this.radii.minor / _this.radiusScale;\n var r = Math.sqrt(Math.pow(xyz.x, 2) + Math.pow(xyz.y, 2));\n var E2 = Math.pow(rs, 2) - Math.pow(rs2, 2);\n var F = 54 * Math.pow(rs, 2) * Math.pow(xyz.z, 2);\n var G = Math.pow(r, 2) + (1 - Math.pow(_this.e, 2)) * Math.pow(xyz.z, 2) - Math.pow(_this.e, 2) * E2;\n var C = Math.pow(_this.e, 4) * F * Math.pow(r, 2) / Math.pow(G, 3);\n var S = Math.cbrt(1 + C + Math.sqrt(Math.pow(C, 2) + 2 * C));\n var P = F / (3 * Math.pow(S + 1 / S + 1, 2) * Math.pow(G, 2));\n var Q = Math.sqrt(1 + 2 * Math.pow(_this.e, 4) * P);\n var r0 = -(P * Math.pow(_this.e, 2) * r) / (1 + Q) + Math.sqrt(0.5 * Math.pow(rs, 2) * (1 + 1 / Q) - P * (1 - Math.pow(_this.e, 2)) * Math.pow(xyz.z, 2) / (Q * (1 + Q)) - 0.5 * P * Math.pow(r, 2));\n var U = Math.sqrt(r - Math.pow(_this.e, 2) * r0 + Math.pow(xyz.z, 2));\n var V = Math.sqrt(Math.pow(r - Math.pow(_this.e, 2) * r0, 2) + (1 - Math.pow(_this.e, 2)) * Math.pow(xyz.z, 2));\n var Z0 = Math.pow(rs2, 2) * xyz.z / (rs * V);\n var h = U * (1 - Math.pow(rs2, 2) / (rs * V));\n var phi = Math.atan((xyz.z + Math.pow(_this.ep, 2) * Z0) / r) * (180 / Math.PI);\n var lambda = -(Math.atan2(xyz.y, xyz.x) * (180 / Math.PI)) - 90;\n if (lambda < -180) lambda += 360;\n return {\n lat: phi,\n lng: lambda,\n height: h\n };\n };\n\n this.lonLatToVector3 = function (lon, lat, height) {\n var phi = lat * (Math.PI / 180);\n var theta = (lon - 180) * (Math.PI / 180);\n var x = (_this.radii.major + height) / _this.radiusScale * Math.cos(phi) * Math.sin(theta);\n var y = -(_this.radii.major + height) / _this.radiusScale * Math.sin(phi);\n var z = -(_this.radii.major + height) / _this.radiusScale * Math.cos(phi) * Math.cos(theta);\n return {\n x: x,\n y: y,\n z: z\n };\n };\n\n this.rotatePoint3D = function (pt, angle, center) {\n if (center == undefined) center = {\n x: 0,\n y: 0,\n z: 0\n };\n var dx = pt.x - center.x;\n var dy = pt.y - center.y;\n var dz = pt.z - center.z;\n var sx = Math.sin(angle.x);\n var cx = Math.cos(angle.x);\n var sy = Math.sin(angle.y);\n var cy = Math.cos(angle.y);\n var sz = Math.sin(angle.z);\n var cz = Math.cos(angle.z);\n var x = center.x + dx * (cy * cz) + dy * (-cy * sz) + dz * sy;\n var y = center.y + dx * (cx * sz + sx * sy * cz) + dy * (cx * cz - sx * sy * sz) + dz * (-sx * cy);\n var z = center.z + dx * (sx * sz - cx * sy * cz) + dy * (sx * cz + cx * sy * sz) + dz * (cx * cy);\n return {\n x: x,\n y: y,\n z: z\n };\n };\n\n this.lon2tileUnfloored = function (lon, zoom) {\n return (lon + 180) / 360 * Math.pow(2, zoom);\n };\n\n this.lat2tileUnfloored = function (lat, zoom) {\n return (1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom);\n };\n\n this.lngLatDistBetween = function (lon1, lat1, lon2, lat2) {\n var R = _this.radii.major / _this.radiusScale;\n var φ1 = lat1 * (Math.PI / 180);\n var φ2 = lat2 * (Math.PI / 180);\n var Δφ = (lat2 - lat1) * (Math.PI / 180);\n var Δλ = (lon2 - lon1) * (Math.PI / 180);\n var a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);\n var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n return R * c;\n };\n\n this._reset();\n\n this.setRadius(majorRadius, RadiusE.Major);\n this.setRadius(minorRadius, RadiusE.Minor);\n this.tileMapResource = tileMapResource || {\n bounds: null,\n origin: null,\n crsCode: null,\n epsg: null,\n proj: null,\n resunitsperpixel: null,\n reszoomlevel: null\n };\n this.tileMapResource.crsCode = this.tileMapResource.crsCode || 'EPSG:4326';\n this.trueTileResolution = trueTileResolution || 256;\n\n if (this.tileMapResource.resunitsperpixel != null && this.tileMapResource.reszoomlevel != null) {\n var reszoomlevel = this.tileMapResource.reszoomlevel;\n reszoomlevel += Math.round(4 * Math.PI * Math.pow(3396190, 2) / (4 * Math.PI * Math.pow(this.radii.major, 2)));\n var baseRes = this.tileMapResource.resunitsperpixel * Math.pow(2, reszoomlevel);\n var res = [];\n\n for (var i = 0; i < 32; i++) {\n res.push(baseRes / Math.pow(2, i));\n }\n\n this.res = res;\n }\n\n var tmr = this.tileMapResource;\n this.crs = new _CRS__WEBPACK_IMPORTED_MODULE_0__[\"default\"](Number.isFinite(parseInt(tmr.crsCode[0])) ? \"EPSG:\" + tmr.epsg : tmr.crsCode, tmr.proj, {\n origin: [parseFloat(tmr.origin[0]), parseFloat(tmr.origin[1])],\n resolutions: this.res,\n bounds: [[parseFloat(tmr.bounds[0]), parseFloat(tmr.bounds[1])], [parseFloat(tmr.bounds[2]), parseFloat(tmr.bounds[3])]]\n }, parseFloat(this.radii.major));\n }\n\n Projection.prototype._reset = function () {\n this.baseRadius = 6371000;\n this.radiusScale = 1;\n this.radii = {\n major: this.baseRadius,\n minor: this.baseRadius\n };\n this.tileMapResource = {\n bounds: null,\n origin: null,\n crsCode: 'EPSG:4326',\n proj: null,\n resunitsperpixel: null,\n reszoomlevel: null\n };\n this.e = 0;\n this.ep = 0;\n this.flatteningFactor = 0;\n };\n\n return Projection;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Projection);\n\n//# sourceURL=webpack://LithoSphere/./src/core/projection.ts?"); /***/ }), @@ -1948,7 +1996,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var thre /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n\nvar Shaders = {\n simplePoint: function () {\n var baseShaderVert = '#ifdef GL_ES\\n' + 'precision highp float;\\n' + '#endif\\n' + 'void main() {\\n' + 'gl_PointSize = 50.\\n' + 'gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.)\\n' + '}';\n var baseShaderFrag = 'void main() {\\n' + 'gl_FragColor = vec4(0.0, 1.0, 1.0, 0.0)\\n' + '}';\n return new three__WEBPACK_IMPORTED_MODULE_0__[\"ShaderMaterial\"]({\n uniforms: {},\n vertexShader: baseShaderVert,\n fragmentShader: baseShaderFrag,\n transparent: true\n });\n },\n multiTexture: function (textures, fadeIn) {\n var numberOfTextures = textures.length;\n var baseShaderVert = '#ifdef GL_ES\\n' + 'precision highp float;\\n' + '#endif\\n' + 'varying vec2 vUv;\\n' + 'attribute vec3 customColor;\\n' + 'varying vec3 vColor;\\n' + 'void main() {\\n' + 'vUv = uv;\\n' + 'vColor = customColor;\\n' + 'vec4 mvPosition = viewMatrix * modelMatrix * vec4(position, 1.0);\\n' + 'gl_Position = projectionMatrix * mvPosition;\\n' + '}';\n var baseShaderFrag = '#ifdef GL_ES\\n' + 'precision highp float;\\n' + '#endif\\n';\n\n for (var i = 0; i < numberOfTextures; i++) {\n baseShaderFrag += 'uniform sampler2D t' + i + ';\\n' + 'uniform float tA' + i + ';\\n' + 'uniform float tVAT' + i + ';\\n';\n }\n\n baseShaderFrag += 'varying vec2 vUv;\\n' + 'varying vec3 vColor;\\n' + 'void main(void) {\\n' + 'vec4 C;\\n' + 'vec4 B = vec4(0,0,0,0);\\n' + 'vec4 C0 = texture2D(t0, vUv);\\n' + 'float highestA = tA0;\\n';\n baseShaderFrag += 'C = vec4( C0.rgb * (C0.a * tA0) + B.rgb * B.a * (1.0 - (C0.a * tA0)), 1);\\n';\n\n for (var i = 1; i < numberOfTextures; i++) {\n baseShaderFrag += 'if ( tVAT' + i + ' == 0.0 && tA' + i + ' > highestA ){ highestA = tA' + i + '; }\\n' + 'vec4 C' + i + ' = texture2D(t' + i + ', vUv);\\n' + 'C = vec4( C' + i + '.rgb * (C' + i + '.a * tA' + i + ') + C.rgb * C.a * (1.0 - (C' + i + '.a * tA' + i + ')), 1);\\n';\n }\n\n baseShaderFrag += 'if (';\n\n for (var i = 0; i < numberOfTextures; i++) {\n baseShaderFrag += ' C' + i + '.a == 0.0';\n\n if (i != numberOfTextures - 1) {\n baseShaderFrag += ' && ';\n }\n }\n\n baseShaderFrag += '){\\n' + 'discard;\\n' + '}\\n' + 'if (vColor.r * vColor.g * vColor.b == 1.0){\\n' + 'discard;\\n' + '}\\n' + 'if (!(vColor.r == 0.0 && vColor.g == 0.0 && vColor.b == 0.0)){\\n' + 'C = vec4(vColor, 1);\\n' + '}\\n' + 'C.a = highestA;\\n' + 'gl_FragColor = C;\\n' + '}';\n var uniforms = {};\n\n for (var i = 0; i < numberOfTextures; i++) {\n uniforms['t' + i] = {\n value: textures[i].texture\n };\n uniforms['tA' + i] = {\n value: fadeIn ? 0 : textures[i].opacity\n };\n uniforms['tVAT' + i] = {\n value: textures[i].isVAT\n };\n }\n\n return new three__WEBPACK_IMPORTED_MODULE_0__[\"ShaderMaterial\"]({\n uniforms: uniforms,\n vertexShader: baseShaderVert,\n fragmentShader: baseShaderFrag,\n transparent: true\n });\n },\n atmosphere: function (color) {\n var vertexShader = ['varying vec3\tvVertexWorldPosition;', 'varying vec3\tvVertexNormal;', 'void main(){', '\tvVertexNormal = normalize(normalMatrix * normal);', '\tvVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;', '\t// set gl_Position', '\tgl_Position\t= projectionMatrix * modelViewMatrix * vec4(position, 1.0);', '}'].join('\\n');\n var fragmentShader = [\"#ifdef GL_ES\", \"precision highp float;\", \"#endif\", 'uniform vec3 glowColor;', 'uniform float coefficient;', 'uniform float opacity;', 'uniform float power;', 'varying vec3 vVertexNormal;', 'varying vec3 vVertexWorldPosition;', 'void main(){', '\tvec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition;', '\tvec3 viewCameraToVertex\t= (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;', '\tviewCameraToVertex = normalize(viewCameraToVertex);', '\tfloat intensity = pow(coefficient + dot(vVertexNormal, viewCameraToVertex), power);', '\tgl_FragColor = vec4(glowColor * intensity * opacity, 1.0);', ' if (intensity > 0.4) { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); }', '}'].join('\\n');\n return new three__WEBPACK_IMPORTED_MODULE_0__[\"ShaderMaterial\"]({\n uniforms: {\n coefficient: {\n value: 0.1\n },\n power: {\n value: 6.0\n },\n opacity: {\n value: 0.5\n },\n glowColor: {\n value: new three__WEBPACK_IMPORTED_MODULE_0__[\"Color\"](color || '#FFFFFF')\n }\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n blending: three__WEBPACK_IMPORTED_MODULE_0__[\"AdditiveBlending\"],\n transparent: true,\n depthWrite: false\n });\n }\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (Shaders);\n\n//# sourceURL=webpack://LithoSphere/./src/core/shaders.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n\nvar Shaders = {\n simplePoint: function () {\n var baseShaderVert = '#ifdef GL_ES\\n' + 'precision highp float;\\n' + '#endif\\n' + 'void main() {\\n' + 'gl_PointSize = 50.\\n' + 'gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.)\\n' + '}';\n var baseShaderFrag = 'void main() {\\n' + 'gl_FragColor = vec4(0.0, 1.0, 1.0, 0.0)\\n' + '}';\n return new three__WEBPACK_IMPORTED_MODULE_0__[\"ShaderMaterial\"]({\n uniforms: {},\n vertexShader: baseShaderVert,\n fragmentShader: baseShaderFrag,\n transparent: true\n });\n },\n multiTexture: function (textures, fadeIn) {\n var numberOfTextures = textures.length;\n var baseShaderVert = '#ifdef GL_ES\\n' + 'precision highp float;\\n' + '#endif\\n' + 'varying vec2 vUv;\\n' + 'void main() {\\n' + 'vUv = uv;\\n' + 'vec4 mvPosition = viewMatrix * modelMatrix * vec4(position, 1.0);\\n' + 'gl_Position = projectionMatrix * mvPosition;\\n' + '}';\n var baseShaderFrag = getColorSpaceFunctions() + \"\\n\\n\" + '#ifdef GL_ES\\n' + 'precision highp float;\\n' + '#endif\\n';\n\n for (var i = 0; i < numberOfTextures; i++) {\n baseShaderFrag += 'uniform sampler2D t' + i + ';\\n' + 'uniform float tA' + i + ';\\n' + 'uniform float fbrightness' + i + ';\\n' + 'uniform float fcontrast' + i + ';\\n' + 'uniform float fsaturation' + i + ';\\n' + 'uniform float fblendCode' + i + ';\\n';\n }\n\n baseShaderFrag += 'varying vec2 vUv;\\n' + 'float sat;\\n' + 'float x;\\n' + 'float y;\\n' + 'vec4 Csat;\\n' + 'vec3 backdropHSL;\\nvec3 currentHSL;\\n' + 'void main(void) {\\n' + 'vec4 C = vec4(0,0,0,0);\\n';\n var highestA = 0;\n\n for (var i = 0; i < numberOfTextures; i++) {\n baseShaderFrag += \"vec4 C\" + i + \" = texture2D(t\" + i + \", vUv);\\n\" + (textures[i].isVAT === 0 ? (i > 0 ? \"if (fblendCode\" + i + \" == 2.0) {\\n\" + \"backdropHSL = RGBtoHSL(C.rgb);\\n\" + (\"currentHSL = RGBtoHSL(C\" + i + \".rgb);\\n\") + \"currentHSL.z = backdropHSL.z;\\n\" + (\"C\" + i + \".rgb = HSLtoRGB(currentHSL);\\n\") + \"}\\n\" : '') + (\"C\" + i + \".rgb = ((C\" + i + \".rgb - 0.5f) * max(fcontrast\" + i + \", 0.0f)) + 0.5f;\\n\") + (\"C\" + i + \".rgb *= fbrightness\" + i + \";\\n\") + (\"sat = fsaturation\" + i + \" - 1.0f;\\n\") + \"x = sat * (2.0f / 3.0f) + 1.0f;\\n\" + \"y = (x - 1.0f) * -0.5f;\\n\" + (\"Csat = C\" + i + \";\\n\") + (\"C\" + i + \".r = Csat.r * x + Csat.g * y + Csat.b * y;\\n\") + (\"C\" + i + \".g = Csat.r * y + Csat.g * x + Csat.b * y;\\n\") + (\"C\" + i + \".b = Csat.r * y + Csat.g * y + Csat.b * x;\\n\") + (i > 0 ? \"if (fblendCode\" + i + \" == 1.0) {\\n\" + (\"if (C\" + i + \".r < 0.5f) {\\n\") + (\"C\" + i + \".r = 2.0f * C\" + i + \".r * C.r;\\n\") + \"} else {\\n\" + (\"C\" + i + \".r = 1.0f - (2.0f * (1.0f - C.r) * (1.0f - C\" + i + \".r));\\n\") + \"}\\n\" + (\"if (C\" + i + \".g < 0.5f) {\\n\") + (\"C\" + i + \".g = 2.0f * C\" + i + \".g * C.g;\\n\") + \"} else {\\n\" + (\"C\" + i + \".g = 1.0f - (2.0f * (1.0f - C.g) * (1.0f - C\" + i + \".g));\\n\") + \"}\\n\" + (\"if (C\" + i + \".b < 0.5f) {\\n\") + (\"C\" + i + \".b = 2.0f * C\" + i + \".b * C.b;\\n\") + \"} else {\\n\" + (\"C\" + i + \".b = 1.0f - (2.0f * (1.0f - C.b) * (1.0f - C\" + i + \".b));\\n\") + \"}\\n\" + \"}\\n\" : '') : '') + (\"C = vec4( C\" + i + \".rgb * (C\" + i + \".a * tA\" + i + \") + C.rgb * C.a * (1.0 - (C\" + i + \".a * tA\" + i + \")), 1);\\n\");\n if (textures[i].isVat === 0 && textures[i].opacity > highestA) highestA = textures[i].opacity;\n }\n\n if (highestA === 0) highestA = 1;\n baseShaderFrag += 'if (';\n\n for (var i = 0; i < numberOfTextures; i++) {\n baseShaderFrag += ' C' + i + '.a == 0.0';\n\n if (i != numberOfTextures - 1) {\n baseShaderFrag += ' && ';\n }\n }\n\n baseShaderFrag += '){\\n' + 'discard;\\n' + '}\\n' + (\"C.a = \" + highestA.toFixed(1) + \"f;\\n\") + 'gl_FragColor = C;\\n' + '}';\n var uniforms = {};\n\n for (var i = 0; i < numberOfTextures; i++) {\n uniforms['t' + i] = {\n value: textures[i].texture\n };\n uniforms['tA' + i] = {\n value: fadeIn ? 0 : textures[i].opacity\n };\n uniforms['fbrightness' + i] = {\n value: textures[i].filters.brightness\n };\n uniforms['fcontrast' + i] = {\n value: textures[i].filters.contrast\n };\n uniforms['fsaturation' + i] = {\n value: textures[i].filters.saturation\n };\n uniforms['fblendCode' + i] = {\n value: textures[i].filters.blendCode\n };\n }\n\n return new three__WEBPACK_IMPORTED_MODULE_0__[\"ShaderMaterial\"]({\n uniforms: uniforms,\n vertexShader: baseShaderVert,\n fragmentShader: baseShaderFrag,\n transparent: true\n });\n },\n atmosphere: function (color) {\n var vertexShader = ['varying vec3\tvVertexWorldPosition;', 'varying vec3\tvVertexNormal;', 'void main(){', '\tvVertexNormal = normalize(normalMatrix * normal);', '\tvVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;', '\t// set gl_Position', '\tgl_Position\t= projectionMatrix * modelViewMatrix * vec4(position, 1.0);', '}'].join('\\n');\n var fragmentShader = [\"#ifdef GL_ES\", \"precision highp float;\", \"#endif\", 'uniform vec3 glowColor;', 'uniform float coefficient;', 'uniform float opacity;', 'uniform float power;', 'varying vec3 vVertexNormal;', 'varying vec3 vVertexWorldPosition;', 'void main(){', '\tvec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition;', '\tvec3 viewCameraToVertex\t= (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;', '\tviewCameraToVertex = normalize(viewCameraToVertex);', '\tfloat intensity = pow(coefficient + dot(vVertexNormal, viewCameraToVertex), power);', '\tgl_FragColor = vec4(glowColor * intensity * opacity, 1.0);', ' if (intensity > 0.4) { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); }', '}'].join('\\n');\n return new three__WEBPACK_IMPORTED_MODULE_0__[\"ShaderMaterial\"]({\n uniforms: {\n coefficient: {\n value: 0.1\n },\n power: {\n value: 6.0\n },\n opacity: {\n value: 0.5\n },\n glowColor: {\n value: new three__WEBPACK_IMPORTED_MODULE_0__[\"Color\"](color || '#FFFFFF')\n }\n },\n vertexShader: vertexShader,\n fragmentShader: fragmentShader,\n blending: three__WEBPACK_IMPORTED_MODULE_0__[\"AdditiveBlending\"],\n transparent: true,\n depthWrite: false\n });\n }\n};\n\nfunction getColorSpaceFunctions() {\n return ['vec3 RGBtoHSL(in vec3 RGB) {\\n', 'float cMax = max(max(RGB.r, RGB.g), RGB.b);\\n', 'float cMin = min(min(RGB.r, RGB.g), RGB.b);\\n', 'float delta = cMax - cMin;\\n', 'float lightness = (cMax + cMin) / 2.0f;\\n', 'float hue = 0.0f;\\n', 'if (delta == 0.0f) {\\n', 'hue = 0.0f;\\n', '}\\n', 'else if (cMax == RGB.r) {\\n', 'hue = (60.0f / 360.0f) * mod((RGB.g - RGB.b) / delta , 6.0f);\\n', '}\\n', 'else if (cMax == RGB.g) {\\n', 'hue = (60.0f / 360.0f) * (((RGB.b - RGB.r) / delta) + 2.0f);\\n', '}\\n', 'else if (cMax == RGB.b) {\\n', 'hue = (60.0f / 360.0f) * (((RGB.r - RGB.g) / delta) + 4.0f);\\n', '}\\n', 'float saturation = 0.0f;\\n', 'if (delta > 0.0f) {\\n', 'saturation = delta / (1.0f - abs((2.0f * lightness) - 1.0f));\\n', '}\\n', 'return vec3(hue, saturation, lightness);\\n', '}', 'vec3 HSLtoRGB(in vec3 HSL) {', 'float C = (1.0f - abs((2.0f * HSL.z) - 1.0f)) * HSL.y;\\n', 'float X = C * (1.0f - abs(mod(HSL.x / (60.0f / 360.0f), 2.0f) - 1.0f));\\n', 'float m = HSL.z - C / 2.0f;\\n', 'vec3 rgb;\\n', 'if (HSL.x < (60.0f / 360.0f)) {\\n', 'rgb = vec3(C, X, 0);\\n', '} else if (HSL.x < (120.0f / 360.0f)) {\\n', 'rgb = vec3(X, C, 0);\\n', '} else if (HSL.x < (180.0f / 360.0f)) {\\n', 'rgb = vec3(0, C, X);\\n', '} else if (HSL.x < (240.0f / 360.0f)) {\\n', 'rgb = vec3(0, X, C);\\n', '} else if (HSL.x < (300.0f / 360.0f)) {\\n', 'rgb = vec3(X, 0, C);\\n', '} else {\\n', 'rgb = vec3(C, 0, X);\\n', '}\\n', 'return vec3(rgb.r + m, rgb.g + m, rgb.b + m);\\n', '}'].join('\\n');\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Shaders);\n\n//# sourceURL=webpack://LithoSphere/./src/core/shaders.ts?"); /***/ }), @@ -1960,7 +2008,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var thre /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ */ \"./src/core/index.ts\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _parsers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../parsers */ \"./src/parsers/index.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n/* harmony import */ var _utils_paths__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/paths */ \"./src/utils/paths.ts\");\nvar __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {\n function adopt(value) {\n return value instanceof P ? value : new P(function (resolve) {\n resolve(value);\n });\n }\n\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n }\n\n function rejected(value) {\n try {\n step(generator[\"throw\"](value));\n } catch (e) {\n reject(e);\n }\n }\n\n function step(result) {\n result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);\n }\n\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\nvar __generator = undefined && undefined.__generator || function (thisArg, body) {\n var _ = {\n label: 0,\n sent: function () {\n if (t[0] & 1) throw t[1];\n return t[1];\n },\n trys: [],\n ops: []\n },\n f,\n y,\n t,\n g;\n return g = {\n next: verb(0),\n \"throw\": verb(1),\n \"return\": verb(2)\n }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function () {\n return this;\n }), g;\n\n function verb(n) {\n return function (v) {\n return step([n, v]);\n };\n }\n\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n\n while (_) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n\n switch (op[0]) {\n case 0:\n case 1:\n t = op;\n break;\n\n case 4:\n _.label++;\n return {\n value: op[1],\n done: false\n };\n\n case 5:\n _.label++;\n y = op[1];\n op = [0];\n continue;\n\n case 7:\n op = _.ops.pop();\n\n _.trys.pop();\n\n continue;\n\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {\n _ = 0;\n continue;\n }\n\n if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {\n _.label = op[1];\n break;\n }\n\n if (op[0] === 6 && _.label < t[1]) {\n _.label = t[1];\n t = op;\n break;\n }\n\n if (t && _.label < t[2]) {\n _.label = t[2];\n\n _.ops.push(op);\n\n break;\n }\n\n if (t[2]) _.ops.pop();\n\n _.trys.pop();\n\n continue;\n }\n\n op = body.call(thisArg, _);\n } catch (e) {\n op = [6, e];\n y = 0;\n } finally {\n f = t = 0;\n }\n\n if (op[0] & 5) throw op[1];\n return {\n value: op[0] ? op[1] : void 0,\n done: true\n };\n }\n};\n\n\n\n\n\n\n\nvar TiledWorld = function () {\n function TiledWorld(parent) {\n this.p = parent;\n\n this._reset();\n }\n\n TiledWorld.prototype._reset = function () {\n this._ = {\n loader: new three__WEBPACK_IMPORTED_MODULE_1__[\"TextureLoader\"](),\n tileDimension: 6\n };\n this.tilesDrawn = [];\n this.tilesWanted = [];\n this.tilesToBeDrawn = [];\n this.tilesBeingDrawn = [];\n };\n\n TiledWorld.prototype.refreshTiles = function () {\n var _this = this;\n\n this.updateDesiredTiles();\n this.tilesToBeDrawn = [];\n\n for (var i = 0; i < this.tilesWanted.length; i++) {\n var matched = false;\n\n for (var j = 0; j < this.tilesDrawn.length; j++) {\n if (this.tilesWanted[i].x == this.tilesDrawn[j].x && this.tilesWanted[i].y == this.tilesDrawn[j].y && this.tilesWanted[i].z == this.tilesDrawn[j].z && this.tilesWanted[i].isLODTile == this.tilesDrawn[j].isLODTile && this.tilesWanted[i].LODLevel == this.tilesDrawn[j].LODLevel && this.tilesDrawn[j].outdated != true) {\n matched = true;\n break;\n }\n }\n\n for (var j = 0; j < this.tilesToBeDrawn.length; j++) {\n if (this.tilesWanted[i].x == this.tilesToBeDrawn[j].x && this.tilesWanted[i].y == this.tilesToBeDrawn[j].y && this.tilesWanted[i].z == this.tilesToBeDrawn[j].z && this.tilesWanted[i].isLODTile == this.tilesToBeDrawn[j].isLODTile && this.tilesWanted[i].LODLevel == this.tilesToBeDrawn[j].LODLevel) {\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n this.tilesToBeDrawn.push(this.tilesWanted[i]);\n }\n }\n\n if (this.tilesToBeDrawn.length > 0) {\n var failCallback_1 = function () {\n if (_this.tilesToBeDrawn.length > 0) {\n _this.addTile(_this.tilesToBeDrawn.pop(), failCallback_1).catch(function () {\n failCallback_1();\n });\n }\n };\n\n this.addTile(this.tilesToBeDrawn.pop(), failCallback_1).catch(function () {\n failCallback_1();\n });\n }\n\n if (this.tilesToBeDrawn.length == 0 && this.tilesBeingDrawn.length == 0 || false && false) {\n for (var i = 0; i < this.tilesDrawn.length; i++) {\n var matched = false;\n\n for (var j = 0; j < this.tilesWanted.length; j++) {\n if (this.tilesDrawn[i].x == this.tilesWanted[j].x && this.tilesDrawn[i].y == this.tilesWanted[j].y && this.tilesDrawn[i].z == this.tilesWanted[j].z && this.tilesDrawn[i].isLODTile == this.tilesWanted[j].isLODTile && this.tilesDrawn[i].LODLevel == this.tilesWanted[j].LODLevel) {\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n this.removeTile(i, true);\n }\n }\n\n this.removeAllOutdatedTiles();\n }\n\n if (this.tilesToBeDrawn.length == 0) {\n if (!this.p._.firstLoad) {\n this.p._onFirstLoad();\n }\n }\n\n var spinner = document.getElementById(this.p.options.loadingSpinnerId);\n var percent = document.getElementById(this.p.options.loadingPercentId);\n\n if (this.tilesToBeDrawn.length == 0) {\n if (spinner) spinner.style.opacity = '0';\n } else if (spinner && spinner.style.opacity == '0') {\n spinner.style.opacity = '1';\n }\n\n if (percent) percent.innerHTML = this.tilesToBeDrawn.length;\n this.fadeInTiles();\n this.fadeOutTiles();\n };\n\n TiledWorld.prototype.updateDesiredTiles = function () {\n this.tilesWanted = [];\n var center = this.p.getCenter();\n var projectedXYZ = this.p.projection.latLngZ2TileXYZ(center.lat, center.lng, this.p.zoom);\n var xCenter = projectedXYZ.x;\n var yCenter = projectedXYZ.y;\n var r = this.p.options.radiusOfTiles;\n var d;\n\n for (var x = xCenter - r + 1; x < xCenter + r; x++) {\n for (var y = yCenter - r + 1; y < yCenter + r; y++) {\n d = Math.pow(x - xCenter, 2) + Math.pow(y - yCenter, 2);\n\n if (d <= r * r) {\n this.tilesWanted.push({\n x: this.p.projection.tileMapResource.proj ? parseInt(x) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(x, Math.pow(2, this.p.zoom)),\n y: this.p.projection.tileMapResource.proj ? parseInt(y) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(y, Math.pow(2, this.p.zoom)),\n z: this.p.zoom,\n d: d,\n make: true,\n isLODTile: false\n });\n }\n }\n }\n\n var lastZ = null;\n\n if (this.p.options.useLOD) {\n for (var i = 0; i < this.p.options.LOD.length; i++) {\n var lr = this.p.options.LOD[i].radiusOfTiles;\n var z = Math.max(this.p._.minNativeZoom, this.p.zoom - this.p.options.LOD[i].zoomsUp);\n if (z == lastZ) break;\n lastZ = z;\n if (Math.abs(z - this.p.zoom) <= 1) continue;\n projectedXYZ = this.p.projection.latLngZ2TileXYZ(center.lat, center.lng, z);\n xCenter = projectedXYZ.x;\n yCenter = projectedXYZ.y;\n\n for (var x = xCenter - lr + 1; x < xCenter + lr; x++) {\n for (var y = yCenter - lr + 1; y < yCenter + lr; y++) {\n d = Math.pow(x - xCenter, 2) + Math.pow(y - yCenter, 2);\n\n if (d <= lr * lr) {\n this.tilesWanted.push({\n x: this.p.projection.tileMapResource.proj ? parseInt(x) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(x, Math.pow(2, z)),\n y: this.p.projection.tileMapResource.proj ? parseInt(y) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(y, Math.pow(2, z)),\n z: z,\n d: d,\n make: true,\n isLODTile: true,\n LODLevel: i\n });\n }\n }\n }\n }\n }\n\n this.tilesWanted.sort(function (a, b) {\n return b.d - a.d;\n });\n this.tilesWanted.sort(function (a, b) {\n var aLODLevel = a.isLODTile ? a.LODLevel : -1;\n var bLODLevel = b.isLODTile ? b.LODLevel : -1;\n return bLODLevel - aLODLevel;\n });\n };\n\n TiledWorld.prototype.addTile = function (xyz, failCallback) {\n return __awaiter(this, void 0, void 0, function () {\n var tileLoaded, t, onceTileLoaded, tileGeometry, loadDemTile, layerI, i, heightArr, builtDemPath, errored_1, builtDemPathFallback, builtDemPathFallback;\n\n var _this = this;\n\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n if (xyz === undefined) return [2];\n tileLoaded = {\n raster: false,\n data: false\n };\n t = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](new three__WEBPACK_IMPORTED_MODULE_1__[\"PlaneBufferGeometry\"](this._.tileDimension, this._.tileDimension, this.p.options.tileResolution - 1, this.p.options.tileResolution - 1), new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n visible: false\n }));\n this.tilesBeingDrawn.push({\n x: xyz.x,\n y: xyz.y,\n z: xyz.z,\n isLODTile: xyz.isLODTile,\n LODLevel: xyz.LODLevel,\n make: xyz.make\n });\n this.tilesDrawn.push({\n x: xyz.x,\n y: xyz.y,\n z: xyz.z,\n isLODTile: xyz.isLODTile,\n LODLevel: xyz.LODLevel,\n t: t,\n contents: [],\n from: {\n dems: [],\n rasters: [],\n data: []\n }\n });\n\n onceTileLoaded = function (destroy) {\n if (destroy) {\n t.geometry.dispose();\n t.material.dispose();\n if (typeof failCallback === 'function') failCallback();\n }\n\n if (tileLoaded.data) {\n var differentZoomTilesToRemove = [];\n\n if (_this.p._.events._.lastZoomDelta <= 2) {\n for (var i = _this.tilesDrawn.length - 1; i >= 0; i--) {\n if (xyz.isLODTile == _this.tilesDrawn[i].isLODTile && xyz.LODLevel == _this.tilesDrawn[i].LODLevel) {\n var drawnXYZ = [_this.tilesDrawn[i].x, _this.tilesDrawn[i].y, _this.tilesDrawn[i].z];\n var thisXYZ = [xyz.x, xyz.y, xyz.z];\n\n if (xyz.z < _this.tilesDrawn[i].z) {\n if (_utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].tileIsContained(thisXYZ, drawnXYZ, true)) {\n differentZoomTilesToRemove.push(i);\n }\n } else if (xyz.z > _this.tilesDrawn[i].z) {\n if (_utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].tileIsContained(drawnXYZ, thisXYZ)) {\n _this.tilesDrawn[i].contents.push(thisXYZ);\n\n if (_this.tilesDrawn[i].contents.length >= _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].tileContains(drawnXYZ, xyz.z).length) {\n differentZoomTilesToRemove.push(i);\n }\n }\n }\n }\n }\n }\n\n for (var i = _this.tilesBeingDrawn.length - 1; i >= 0; i--) {\n if (_this.tilesBeingDrawn[i].x == xyz.x && _this.tilesBeingDrawn[i].y == xyz.y && _this.tilesBeingDrawn[i].z == xyz.z && _this.tilesBeingDrawn[i].isLODTile == xyz.isLODTile && _this.tilesBeingDrawn[i].LODLevel == xyz.LODLevel) {\n if (_this.tilesBeingDrawn[i].make) {\n if (xyz.isLODTile) {\n _this.p.planetsLOD[xyz.LODLevel].add(t);\n } else {\n _this.p.planet.add(t);\n }\n\n _this.updateRastersForTile(xyz);\n\n differentZoomTilesToRemove.forEach(function (tileI) {\n _this.removeTile(tileI, true);\n });\n } else {\n t.geometry.dispose();\n t.material.dispose();\n\n for (var j = _this.tilesDrawn.length - 1; j >= 0; j--) {\n if (_this.tilesDrawn[j].x == xyz.x && _this.tilesDrawn[j].y == xyz.y && _this.tilesDrawn[j].z == xyz.z && _this.tilesDrawn[i].isLODTile == xyz.isLODTile && _this.tilesDrawn[i].LODLevel == xyz.LODLevel) {\n _this.tilesDrawn.splice(j, 1);\n }\n }\n }\n\n _this.tilesBeingDrawn.splice(i, 1);\n\n return;\n }\n }\n }\n };\n\n tileGeometry = function (heightArr) {\n var cnt = 0;\n var verts = Math.pow(_this.p.options.tileResolution, 2);\n var colors = new Float32Array(verts * 3);\n\n if (heightArr == null) {\n heightArr = new Array(verts).fill(0);\n }\n\n var centerHeight = 0;\n var centerCnt = Math.floor(heightArr.length / 2);\n var counter = 0;\n\n while ((centerHeight == null || centerHeight > _this.p.projection.radiusOfPlanetMajor || centerHeight < -_this.p.projection.radiusOfPlanetMajor) && counter < heightArr.length) {\n centerHeight = heightArr[centerCnt];\n counter++;\n }\n\n var centerP = Math.floor(t.geometry.attributes.position.array.length / 6) * 3;\n var tx = xyz.x + centerP / 3 % _this.p.options.tileResolution / (_this.p.options.tileResolution - 1);\n var ty = xyz.y + Math.floor(centerP / 3 / _this.p.options.tileResolution) / (_this.p.options.tileResolution - 1);\n\n var projectedLL = _this.p.projection.tileXYZ2LatLng(tx, ty, xyz.z);\n\n var tlat = projectedLL.lat;\n var tlon = projectedLL.lng;\n var centerLat = tlat;\n\n var centerPos = _this.p.projection.lonLatToVector3(tlon, tlat, centerHeight * _this.p.options.exaggeration);\n\n t.position.set(centerPos.x, centerPos.y, centerPos.z);\n\n if (t.geometry.attributes.position.array.length / 3 == verts) {\n var height = 0;\n var xyzPos = void 0;\n\n for (var p = 0; p < t.geometry.attributes.position.array.length; p += 3) {\n height = heightArr[cnt] || 0;\n colors[p] = 0;\n colors[p + 1] = 0;\n colors[p + 2] = 0;\n\n if (height < -100000) {\n height = -100000;\n }\n\n var tx_1 = xyz.x + p / 3 % _this.p.options.tileResolution / (_this.p.options.tileResolution - 1);\n var ty_1 = xyz.y + Math.floor(p / 3 / _this.p.options.tileResolution) / (_this.p.options.tileResolution - 1);\n\n var projectedLL_1 = _this.p.projection.tileXYZ2LatLng(tx_1, ty_1, xyz.z, xyz);\n\n var tlat_1 = projectedLL_1.lat;\n var tlon_1 = projectedLL_1.lng;\n\n if (_this.p.zoom <= _this.p._.zCutOff) {\n if (centerLat > 75 && tlat_1 < -88) {\n tlat_1 = 90;\n } else if (centerLat < -75 && tlat_1 > 88) {\n tlat_1 = -90;\n }\n }\n\n xyzPos = _this.p.projection.lonLatToVector3(tlon_1, tlat_1, height * _this.p.options.exaggeration);\n t.geometry.attributes.position.array[p] = xyzPos.x - centerPos.x;\n t.geometry.attributes.position.array[p + 1] = xyzPos.y - centerPos.y;\n t.geometry.attributes.position.array[p + 2] = xyzPos.z - centerPos.z;\n cnt += 1;\n }\n\n t.geometry.attributes.position.needsUpdate = true;\n t.geometry.computeVertexNormals();\n t.geometry.computeBoundingSphere();\n t.geometry.setAttribute('customColor', new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferAttribute\"](colors, 3));\n tileLoaded.data = true;\n onceTileLoaded();\n }\n };\n\n loadDemTile = false;\n layerI = null;\n\n for (i = this.p.layers.tile.length - 1; i >= 0; i--) {\n if (this.p.layers.tile[i].on && (xyz.z >= this.p.layers.tile[i].minZoom && xyz.z <= this.p.layers.tile[i].maxZoom && _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent(xyz, this.p.layers.tile[i].boundingBox, this.p.projection) || this.p.layers.tile[i].path == '_vectorsastile_')) {\n layerI = i;\n\n if (this.p.layers.tile[i].demPath != undefined) {\n loadDemTile = true;\n break;\n }\n }\n }\n\n heightArr = null;\n if (!(loadDemTile && layerI != null)) return [3, 4];\n builtDemPath = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this.p.layers.tile[layerI].format, this.p.layers.tile[layerI].demPath, xyz, this.p.projection, this.p.options.tileResolution, this.p.options.trueTileResolution, this.p.layers.tile[layerI].demFormatOptions, true);\n if (!builtDemPath) return [3, 3];\n errored_1 = false;\n return [4, Object(_parsers__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(this.p.options.customParsers, builtDemPath.path, this.p.layers.tile[layerI], builtDemPath.xyz, this.p.options.tileResolution, Math.pow(this.p.options.tileResolution, 2)).catch(function () {\n errored_1 = true;\n })];\n\n case 1:\n heightArr = _a.sent();\n if (!(errored_1 && this.p.options.demFallback != null)) return [3, 3];\n builtDemPathFallback = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this.p.options.demFallback.format, this.p.options.demFallback.demPath, xyz, this.p.projection, this.p.options.tileResolution, this.p.options.trueTileResolution, this.p.layers.tile[layerI].demFormatOptions, true);\n if (!builtDemPathFallback) return [3, 3];\n return [4, Object(_parsers__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(this.p.options.customParsers, builtDemPathFallback.path, this.p.layers.tile[layerI], builtDemPathFallback.xyz, this.p.options.tileResolution, Math.pow(this.p.options.tileResolution, 2), this.p.options.demFallback.parserType).catch(function () {})];\n\n case 2:\n heightArr = _a.sent();\n _a.label = 3;\n\n case 3:\n tileGeometry(heightArr || null);\n return [3, 7];\n\n case 4:\n if (!(this.p.options.demFallback != null)) return [3, 6];\n builtDemPathFallback = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this.p.options.demFallback.format, this.p.options.demFallback.demPath, xyz, this.p.projection, this.p.options.tileResolution, this.p.options.trueTileResolution, this.p.layers.tile[layerI].demFormatOptions, true);\n if (!builtDemPathFallback) return [3, 6];\n return [4, Object(_parsers__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(this.p.options.customParsers, builtDemPathFallback.path, this.p.layers.tile[layerI], builtDemPathFallback.xyz, this.p.options.tileResolution, Math.pow(this.p.options.tileResolution, 2), this.p.options.demFallback.parserType).catch(function () {})];\n\n case 5:\n heightArr = _a.sent();\n _a.label = 6;\n\n case 6:\n tileGeometry();\n _a.label = 7;\n\n case 7:\n return [2];\n }\n });\n });\n };\n\n TiledWorld.prototype.findTileDrawnBasedOnUUID = function (uuid) {\n var foundTile = null;\n this.tilesDrawn.forEach(function (tile) {\n if (tile.t.uuid === uuid) {\n foundTile = tile;\n return;\n }\n });\n return foundTile;\n };\n\n TiledWorld.prototype.findTileDrawnBasedOnXYZLOD = function (xyz) {\n var foundTile = null;\n this.tilesDrawn.forEach(function (tile) {\n if (tile.x === xyz.x && tile.y === xyz.y && tile.z === xyz.z && tile.isLODTile === xyz.isLODTile && tile.LODLevel == xyz.LODLevel) {\n foundTile = tile;\n return;\n }\n });\n return foundTile;\n };\n\n TiledWorld.prototype.updateRastersForTile = function (xyz) {\n var _this = this;\n\n var tD = this.findTileDrawnBasedOnXYZLOD(xyz);\n if (tD == null) return;\n var textures = [];\n var tileLayersComplete = new Array(this.p.layers.tile.length).fill(false);\n var clampedLayersComplete = new Array(this.p.layers.clamped.length).fill(false);\n\n var onceTexturesLoaded = function () {\n if (tileLayersComplete.every(Boolean) && (xyz.isLODTile || clampedLayersComplete.every(Boolean))) {\n if (textures.length == 0) {\n tD.t.visible = false;\n return;\n }\n\n textures.sort(function (a, b) {\n return a.i - b.i;\n });\n tD.from.rasters = [];\n var orderingI = 0;\n\n for (var i = 0; i < textures.length; i++) {\n if (textures[i].type == 'tile') {\n tD.from.rasters.push({\n name: textures[i].name,\n type: textures[i].type,\n texture: textures[i].texture,\n opacity: textures[i].opacity,\n isVAT: 0,\n i: orderingI\n });\n orderingI++;\n }\n }\n\n for (var i = 0; i < textures.length; i++) {\n if (textures[i].type == 'clamped') {\n tD.from.rasters.push({\n name: textures[i].name,\n type: textures[i].type,\n texture: textures[i].texture,\n opacity: textures[i].opacity,\n isVAT: 1,\n i: orderingI\n });\n orderingI++;\n }\n }\n\n tD.t.material = ___WEBPACK_IMPORTED_MODULE_0__[\"Shaders\"].multiTexture(tD.from.rasters);\n\n if (_this.p.options.wireframeMode) {\n tD.t.material = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n color: 0xffffff,\n wireframe: true\n });\n }\n\n tD.t.material.needsUpdate = true;\n }\n };\n\n var _loop_1 = function (i) {\n if (this_1.p.layers.tile[i].on && tD.z >= this_1.p.layers.tile[i].minZoom && tD.z <= this_1.p.layers.tile[i].maxZoom && _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent({\n x: tD.x,\n y: tD.y,\n z: tD.z\n }, this_1.p.layers.tile[i].boundingBox, this_1.p.projection)) {\n var builtPath_1 = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this_1.p.layers.tile[i].format, this_1.p.layers.tile[i].path, tD, this_1.p.projection, this_1.p.options.trueTileResolution, this_1.p.options.trueTileResolution, this_1.p.layers.tile[i].formatOptions);\n\n if (builtPath_1) {\n ;\n\n (function (i) {\n _this._.loader.load(builtPath_1, function (texture) {\n texture.magFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n texture.minFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n if (_this.p.layers.tile[i]) textures.push({\n name: _this.p.layers.tile[i].name,\n type: 'tile',\n texture: texture,\n opacity: _this.p.layers.tile[i].opacity,\n i: i\n });\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n }, function () {\n console.log('');\n }, function () {\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n });\n })(i);\n } else {\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n }\n } else {\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n }\n };\n\n var this_1 = this;\n\n for (var i = 0; i < this.p.layers.tile.length; i++) {\n _loop_1(i);\n }\n\n if (!xyz.isLODTile) {\n for (var i = 0; i < this.p.layers.clamped.length; i++) {\n if (this.p.layers.clamped[i].on && (this.p.layers.clamped[i].minZoom == null || tD.z >= this.p.layers.clamped[i].minZoom) && (this.p.layers.clamped[i].maxZoom == null || tD.z <= this.p.layers.clamped[i].maxZoom) && (this.p.layers.clamped[i].boundingBox == null || _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent({\n x: tD.x,\n y: tD.y,\n z: tD.z\n }, this.p.layers.clamped[i].boundingBox, this.p.projection))) {\n var clampedTexture = this.p.layers._.layerers.clamped.getClampedTexture(i, {\n x: tD.x,\n y: tD.y,\n z: tD.z\n });\n\n tD.contains = tD.contains || {};\n tD.contains[this.p.layers.clamped[i].name] = clampedTexture.features;\n var texture = new three__WEBPACK_IMPORTED_MODULE_1__[\"CanvasTexture\"](clampedTexture.canvas);\n texture.magFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n texture.minFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n if (this.p.layers.clamped[i]) textures.push({\n name: this.p.layers.clamped[i].name,\n type: 'clamped',\n texture: texture,\n opacity: this.p.layers.clamped[i].opacity,\n i: i\n });\n clampedLayersComplete[i] = true;\n onceTexturesLoaded();\n } else {\n clampedLayersComplete[i] = true;\n onceTexturesLoaded();\n }\n }\n }\n };\n\n TiledWorld.prototype.updateClampedRasterForTile = function (tD, layerName) {\n if (this.p.options.wireframeMode || tD.isLODTile) return;\n var clampedLayerI = null;\n\n for (var i = 0; i < this.p.layers.clamped.length; i++) {\n if (this.p.layers.clamped[i].name === layerName) {\n clampedLayerI = i;\n break;\n }\n }\n\n var clampedLayer = clampedLayerI != null ? this.p.layers.clamped[clampedLayerI] : null;\n\n if (clampedLayer && clampedLayer.on && (clampedLayer.minZoom == null || tD.z >= clampedLayer.minZoom) && (clampedLayer.maxZoom == null || tD.z <= clampedLayer.maxZoom) && (clampedLayer.boundingBox == null || _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent({\n x: tD.x,\n y: tD.y,\n z: tD.z\n }, clampedLayer.boundingBox, this.p.projection))) {\n var clampedTexture = this.p.layers._.layerers.clamped.getClampedTexture(clampedLayerI, {\n x: tD.x,\n y: tD.y,\n z: tD.z\n });\n\n tD.contains = tD.contains || {};\n tD.contains[this.p.layers.clamped[clampedLayerI].name] = clampedTexture.features;\n var texture = new three__WEBPACK_IMPORTED_MODULE_1__[\"CanvasTexture\"](clampedTexture.canvas);\n texture.magFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n texture.minFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n\n for (var i = 0; i < tD.from.rasters.length; i++) {\n if (tD.from.rasters[i].name === layerName) {\n tD.from.rasters[i].texture = texture;\n break;\n }\n }\n\n tD.t.material = ___WEBPACK_IMPORTED_MODULE_0__[\"Shaders\"].multiTexture(tD.from.rasters);\n tD.t.material.needsUpdate = true;\n }\n };\n\n TiledWorld.prototype.updateAllRasters = function () {\n this.killDrawingTiles();\n var startingLength = this.tilesDrawn.length;\n\n for (var j = 0; j < startingLength; j++) {\n var tD = this.tilesDrawn[j];\n this.updateRastersForTile({\n x: tD.x,\n y: tD.y,\n z: tD.z,\n isLODTile: tD.isLODTile,\n LODLevel: tD.LODLevel\n });\n }\n };\n\n TiledWorld.prototype.removeTile = function (i, shouldFadeOut) {\n shouldFadeOut = false;\n\n if (this.tilesDrawn[i]) {\n if (shouldFadeOut) {\n this.tilesDrawn[i].fadeOutAndRemove = true;\n } else {\n this.tilesDrawn[i].t.geometry.dispose();\n this.tilesDrawn[i].t.material.dispose();\n if (this.tilesDrawn[i].isLODTile) this.p.planetsLOD[this.tilesDrawn[i].LODLevel].remove(this.tilesDrawn[i].t);else this.p.planet.remove(this.tilesDrawn[i].t);\n this.tilesDrawn.splice(i, 1);\n }\n }\n };\n\n TiledWorld.prototype.removeAllTiles = function () {\n this.killDrawingTiles();\n\n for (var j = 0; j < this.tilesDrawn.length; j++) {\n this.removeTile(0);\n }\n };\n\n TiledWorld.prototype.outdateAllTiles = function () {\n this.killDrawingTiles();\n this.tilesDrawn.forEach(function (tile) {\n tile.outdated = true;\n });\n };\n\n TiledWorld.prototype.removeAllOutdatedTiles = function () {\n var _this = this;\n\n var outdatedTileIndices = [];\n this.tilesDrawn.forEach(function (t, i) {\n if (t.outdated) outdatedTileIndices.push(i);\n });\n outdatedTileIndices = outdatedTileIndices.sort().reverse();\n outdatedTileIndices.forEach(function (i) {\n _this.removeTile(i);\n });\n };\n\n TiledWorld.prototype.removeTileXYZ = function (xyz) {\n for (var t in this.tilesDrawn) {\n if (this.tilesDrawn[t].x == xyz.x && this.tilesDrawn[t].y == xyz.y && this.tilesDrawn[t].z == xyz.z) {\n this.tilesDrawn[t].t.geometry.dispose();\n this.tilesDrawn[t].t.material.dispose();\n if (this.tilesDrawn[t].isLODTile) this.p.planetsLOD[this.tilesDrawn[t].LODLevel].remove(this.tilesDrawn[t].t);else this.p.planet.remove(this.tilesDrawn[t].t);\n this.tilesDrawn.splice(t, 1);\n }\n }\n };\n\n TiledWorld.prototype.killDrawingTiles = function () {\n for (var t in this.tilesToBeDrawn) {\n this.tilesToBeDrawn[t].make = false;\n }\n\n for (var t in this.tilesBeingDrawn) {\n this.tilesBeingDrawn[t].make = false;\n }\n };\n\n TiledWorld.prototype.fadeInTiles = function () {\n for (var m in this.tilesDrawn) {\n if (!this.tilesDrawn[m].fadeOutAndRemove) for (var n in this.tilesDrawn[m].from.rasters) {\n if (this.tilesDrawn[m] && this.tilesDrawn[m].t && this.tilesDrawn[m].t.material.hasOwnProperty('uniforms')) {\n var layer = this.p.layers.getLayerByName(this.tilesDrawn[m].from.rasters[n].name);\n\n if (layer) {\n var desiredOpacity = layer.opacity;\n var currentOpacity = this.tilesDrawn[m].t.material.uniforms['tA' + n].value;\n\n if (desiredOpacity > currentOpacity) {\n this.tilesDrawn[m].t.material.uniforms['tA' + n].value = Math.min(this.tilesDrawn[m].t.material.uniforms['tA' + n].value + 0.1, desiredOpacity);\n } else {\n this.tilesDrawn[m].t.material.uniforms['tA' + n].value = Math.max(this.tilesDrawn[m].t.material.uniforms['tA' + n].value - 0.1, desiredOpacity);\n }\n }\n }\n }\n }\n };\n\n TiledWorld.prototype.fadeOutTiles = function () {\n for (var i = this.tilesDrawn.length - 1; i >= 0; i--) {\n if (this.tilesDrawn[i].fadeOutAndRemove) {\n for (var n = 0; this.tilesDrawn[i] && n < this.tilesDrawn[i].from.rasters.length; n++) {\n if (this.tilesDrawn[i] && this.tilesDrawn[i].t && this.tilesDrawn[i].t.material.hasOwnProperty('uniforms') && this.tilesDrawn[i].t.material.uniforms['tA' + n] != null) {\n var nextOpacity = Math.max(this.tilesDrawn[i].t.material.uniforms['tA' + n].value - 0.1, 0);\n if (nextOpacity <= 0) this.removeTile(i);else {\n this.tilesDrawn[i].t.material.uniforms['tA' + n].value = nextOpacity;\n }\n } else {\n this.removeTile(i);\n }\n }\n }\n }\n };\n\n return TiledWorld;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (TiledWorld);\n\n//# sourceURL=webpack://LithoSphere/./src/core/tiledWorld.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ */ \"./src/core/index.ts\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _parsers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../parsers */ \"./src/parsers/index.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n/* harmony import */ var _utils_paths__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/paths */ \"./src/utils/paths.ts\");\nvar __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {\n function adopt(value) {\n return value instanceof P ? value : new P(function (resolve) {\n resolve(value);\n });\n }\n\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n }\n\n function rejected(value) {\n try {\n step(generator[\"throw\"](value));\n } catch (e) {\n reject(e);\n }\n }\n\n function step(result) {\n result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);\n }\n\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\nvar __generator = undefined && undefined.__generator || function (thisArg, body) {\n var _ = {\n label: 0,\n sent: function () {\n if (t[0] & 1) throw t[1];\n return t[1];\n },\n trys: [],\n ops: []\n },\n f,\n y,\n t,\n g;\n return g = {\n next: verb(0),\n \"throw\": verb(1),\n \"return\": verb(2)\n }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function () {\n return this;\n }), g;\n\n function verb(n) {\n return function (v) {\n return step([n, v]);\n };\n }\n\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n\n while (_) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n\n switch (op[0]) {\n case 0:\n case 1:\n t = op;\n break;\n\n case 4:\n _.label++;\n return {\n value: op[1],\n done: false\n };\n\n case 5:\n _.label++;\n y = op[1];\n op = [0];\n continue;\n\n case 7:\n op = _.ops.pop();\n\n _.trys.pop();\n\n continue;\n\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {\n _ = 0;\n continue;\n }\n\n if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {\n _.label = op[1];\n break;\n }\n\n if (op[0] === 6 && _.label < t[1]) {\n _.label = t[1];\n t = op;\n break;\n }\n\n if (t && _.label < t[2]) {\n _.label = t[2];\n\n _.ops.push(op);\n\n break;\n }\n\n if (t[2]) _.ops.pop();\n\n _.trys.pop();\n\n continue;\n }\n\n op = body.call(thisArg, _);\n } catch (e) {\n op = [6, e];\n y = 0;\n } finally {\n f = t = 0;\n }\n\n if (op[0] & 5) throw op[1];\n return {\n value: op[0] ? op[1] : void 0,\n done: true\n };\n }\n};\n\n\n\n\n\n\n\nvar TiledWorld = function () {\n function TiledWorld(parent) {\n this.p = parent;\n\n this._reset();\n }\n\n TiledWorld.prototype._reset = function () {\n this._ = {\n loader: new three__WEBPACK_IMPORTED_MODULE_1__[\"TextureLoader\"](),\n tileDimension: 6\n };\n this.tilesDrawn = [];\n this.tilesWanted = [];\n this.tilesToBeDrawn = [];\n this.tilesBeingDrawn = [];\n };\n\n TiledWorld.prototype.refreshTiles = function () {\n var _this = this;\n\n this.updateDesiredTiles();\n this.tilesToBeDrawn = [];\n\n for (var i = 0; i < this.tilesWanted.length; i++) {\n var matched = false;\n\n for (var j = 0; j < this.tilesDrawn.length; j++) {\n if (this.tilesWanted[i].x == this.tilesDrawn[j].x && this.tilesWanted[i].y == this.tilesDrawn[j].y && this.tilesWanted[i].z == this.tilesDrawn[j].z && this.tilesWanted[i].isLODTile == this.tilesDrawn[j].isLODTile && this.tilesWanted[i].LODLevel == this.tilesDrawn[j].LODLevel && this.tilesDrawn[j].outdated != true) {\n matched = true;\n break;\n }\n }\n\n for (var j = 0; j < this.tilesToBeDrawn.length; j++) {\n if (this.tilesWanted[i].x == this.tilesToBeDrawn[j].x && this.tilesWanted[i].y == this.tilesToBeDrawn[j].y && this.tilesWanted[i].z == this.tilesToBeDrawn[j].z && this.tilesWanted[i].isLODTile == this.tilesToBeDrawn[j].isLODTile && this.tilesWanted[i].LODLevel == this.tilesToBeDrawn[j].LODLevel) {\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n this.tilesToBeDrawn.push(this.tilesWanted[i]);\n }\n }\n\n if (this.tilesToBeDrawn.length > 0) {\n var failCallback_1 = function () {\n if (_this.tilesToBeDrawn.length > 0) {\n _this.addTile(_this.tilesToBeDrawn.pop(), failCallback_1).catch(function () {\n failCallback_1();\n });\n }\n };\n\n this.addTile(this.tilesToBeDrawn.pop(), failCallback_1).catch(function () {\n failCallback_1();\n });\n }\n\n if (this.tilesToBeDrawn.length == 0 && this.tilesBeingDrawn.length == 0 || false && false) {\n for (var i = 0; i < this.tilesDrawn.length; i++) {\n var matched = false;\n\n for (var j = 0; j < this.tilesWanted.length; j++) {\n if (this.tilesDrawn[i].x == this.tilesWanted[j].x && this.tilesDrawn[i].y == this.tilesWanted[j].y && this.tilesDrawn[i].z == this.tilesWanted[j].z && this.tilesDrawn[i].isLODTile == this.tilesWanted[j].isLODTile && this.tilesDrawn[i].LODLevel == this.tilesWanted[j].LODLevel) {\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n this.removeTile(i, true);\n }\n }\n\n this.removeAllOutdatedTiles();\n }\n\n if (this.tilesToBeDrawn.length == 0) {\n if (!this.p._.firstLoad) {\n this.p._onFirstLoad();\n }\n }\n\n var spinner = document.getElementById(this.p.options.loadingSpinnerId);\n var percent = document.getElementById(this.p.options.loadingPercentId);\n\n if (this.tilesToBeDrawn.length == 0) {\n if (spinner) spinner.style.opacity = '0';\n } else if (spinner && spinner.style.opacity == '0') {\n spinner.style.opacity = '1';\n }\n\n if (percent) percent.innerHTML = this.tilesToBeDrawn.length;\n this.filterEffects();\n this.fadeInTiles();\n this.fadeOutTiles();\n };\n\n TiledWorld.prototype.updateDesiredTiles = function () {\n this.tilesWanted = [];\n var center = this.p.getCenter();\n var projectedXYZ = this.p.projection.latLngZ2TileXYZ(center.lat, center.lng, this.p.zoom);\n var xCenter = projectedXYZ.x;\n var yCenter = projectedXYZ.y;\n var r = this.p.options.radiusOfTiles;\n var d;\n\n for (var x = xCenter - r + 1; x < xCenter + r; x++) {\n for (var y = yCenter - r + 1; y < yCenter + r; y++) {\n d = Math.pow(x - xCenter, 2) + Math.pow(y - yCenter, 2);\n\n if (d <= r * r) {\n this.tilesWanted.push({\n x: this.p.projection.tileMapResource.proj ? parseInt(x) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(x, Math.pow(2, this.p.zoom)),\n y: this.p.projection.tileMapResource.proj ? parseInt(y) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(y, Math.pow(2, this.p.zoom)),\n z: this.p.zoom,\n d: d,\n make: true,\n isLODTile: false\n });\n }\n }\n }\n\n var lastZ = null;\n\n if (this.p.options.useLOD) {\n for (var i = 0; i < this.p.options.LOD.length; i++) {\n var lr = this.p.options.LOD[i].radiusOfTiles;\n var z = Math.max(this.p._.minNativeZoom, this.p.zoom - this.p.options.LOD[i].zoomsUp);\n if (z == lastZ) break;\n lastZ = z;\n if (Math.abs(z - this.p.zoom) <= 1) continue;\n projectedXYZ = this.p.projection.latLngZ2TileXYZ(center.lat, center.lng, z);\n xCenter = projectedXYZ.x;\n yCenter = projectedXYZ.y;\n\n for (var x = xCenter - lr + 1; x < xCenter + lr; x++) {\n for (var y = yCenter - lr + 1; y < yCenter + lr; y++) {\n d = Math.pow(x - xCenter, 2) + Math.pow(y - yCenter, 2);\n\n if (d <= lr * lr) {\n this.tilesWanted.push({\n x: this.p.projection.tileMapResource.proj ? parseInt(x) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(x, Math.pow(2, z)),\n y: this.p.projection.tileMapResource.proj ? parseInt(y) : _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].mod(y, Math.pow(2, z)),\n z: z,\n d: d,\n make: true,\n isLODTile: true,\n LODLevel: i\n });\n }\n }\n }\n }\n }\n\n this.tilesWanted.sort(function (a, b) {\n return b.d - a.d;\n });\n this.tilesWanted.sort(function (a, b) {\n var aLODLevel = a.isLODTile ? a.LODLevel : -1;\n var bLODLevel = b.isLODTile ? b.LODLevel : -1;\n return bLODLevel - aLODLevel;\n });\n };\n\n TiledWorld.prototype.addTile = function (xyz, failCallback) {\n return __awaiter(this, void 0, void 0, function () {\n var tileLoaded, t, onceTileLoaded, tileGeometry, loadDemTile, layerI, i, heightArr, builtDemPath, errored_1, builtDemPathFallback, builtDemPathFallback;\n\n var _this = this;\n\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n if (xyz === undefined) return [2];\n tileLoaded = {\n raster: false,\n data: false\n };\n t = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](new three__WEBPACK_IMPORTED_MODULE_1__[\"PlaneBufferGeometry\"](this._.tileDimension, this._.tileDimension, this.p.options.tileResolution - 1, this.p.options.tileResolution - 1), new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n visible: false\n }));\n this.tilesBeingDrawn.push({\n x: xyz.x,\n y: xyz.y,\n z: xyz.z,\n isLODTile: xyz.isLODTile,\n LODLevel: xyz.LODLevel,\n make: xyz.make\n });\n this.tilesDrawn.push({\n x: xyz.x,\n y: xyz.y,\n z: xyz.z,\n isLODTile: xyz.isLODTile,\n LODLevel: xyz.LODLevel,\n t: t,\n contents: [],\n from: {\n dems: [],\n rasters: [],\n data: []\n }\n });\n\n onceTileLoaded = function (destroy) {\n if (destroy) {\n t.geometry.dispose();\n t.material.dispose();\n if (typeof failCallback === 'function') failCallback();\n }\n\n if (tileLoaded.data) {\n var differentZoomTilesToRemove = [];\n\n if (_this.p._.events._.lastZoomDelta <= 2) {\n for (var i = _this.tilesDrawn.length - 1; i >= 0; i--) {\n if (xyz.isLODTile == _this.tilesDrawn[i].isLODTile && xyz.LODLevel == _this.tilesDrawn[i].LODLevel) {\n var drawnXYZ = [_this.tilesDrawn[i].x, _this.tilesDrawn[i].y, _this.tilesDrawn[i].z];\n var thisXYZ = [xyz.x, xyz.y, xyz.z];\n\n if (xyz.z < _this.tilesDrawn[i].z) {\n if (_utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].tileIsContained(thisXYZ, drawnXYZ, true)) {\n differentZoomTilesToRemove.push(i);\n }\n } else if (xyz.z > _this.tilesDrawn[i].z) {\n if (_utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].tileIsContained(drawnXYZ, thisXYZ)) {\n _this.tilesDrawn[i].contents.push(thisXYZ);\n\n if (_this.tilesDrawn[i].contents.length >= _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].tileContains(drawnXYZ, xyz.z).length) {\n differentZoomTilesToRemove.push(i);\n }\n }\n }\n }\n }\n }\n\n for (var i = _this.tilesBeingDrawn.length - 1; i >= 0; i--) {\n if (_this.tilesBeingDrawn[i].x == xyz.x && _this.tilesBeingDrawn[i].y == xyz.y && _this.tilesBeingDrawn[i].z == xyz.z && _this.tilesBeingDrawn[i].isLODTile == xyz.isLODTile && _this.tilesBeingDrawn[i].LODLevel == xyz.LODLevel) {\n if (_this.tilesBeingDrawn[i].make) {\n if (xyz.isLODTile) {\n _this.p.planetsLOD[xyz.LODLevel].add(t);\n } else {\n _this.p.planet.add(t);\n }\n\n _this.updateRastersForTile(xyz);\n\n differentZoomTilesToRemove.forEach(function (tileI) {\n _this.removeTile(tileI, true);\n });\n } else {\n t.geometry.dispose();\n t.material.dispose();\n\n for (var j = _this.tilesDrawn.length - 1; j >= 0; j--) {\n if (_this.tilesDrawn[j].x == xyz.x && _this.tilesDrawn[j].y == xyz.y && _this.tilesDrawn[j].z == xyz.z && _this.tilesDrawn[i].isLODTile == xyz.isLODTile && _this.tilesDrawn[i].LODLevel == xyz.LODLevel) {\n _this.tilesDrawn.splice(j, 1);\n }\n }\n }\n\n _this.tilesBeingDrawn.splice(i, 1);\n\n return;\n }\n }\n }\n };\n\n tileGeometry = function (heightArr) {\n var cnt = 0;\n var verts = Math.pow(_this.p.options.tileResolution, 2);\n var colors = new Float32Array(verts * 3);\n\n if (heightArr == null) {\n heightArr = new Array(verts).fill(0);\n }\n\n var centerHeight = 0;\n var centerCnt = Math.floor(heightArr.length / 2);\n var counter = 0;\n\n while ((centerHeight == null || centerHeight > _this.p.projection.radiusOfPlanetMajor || centerHeight < -_this.p.projection.radiusOfPlanetMajor) && counter < heightArr.length) {\n centerHeight = heightArr[centerCnt];\n counter++;\n }\n\n var centerP = Math.floor(t.geometry.attributes.position.array.length / 6) * 3;\n var tx = xyz.x + centerP / 3 % _this.p.options.tileResolution / (_this.p.options.tileResolution - 1);\n var ty = xyz.y + Math.floor(centerP / 3 / _this.p.options.tileResolution) / (_this.p.options.tileResolution - 1);\n\n var projectedLL = _this.p.projection.tileXYZ2LatLng(tx, ty, xyz.z);\n\n var tlat = projectedLL.lat;\n var tlon = projectedLL.lng;\n var centerLat = tlat;\n\n var centerPos = _this.p.projection.lonLatToVector3(tlon, tlat, centerHeight * _this.p.options.exaggeration);\n\n t.position.set(centerPos.x, centerPos.y, centerPos.z);\n\n if (t.geometry.attributes.position.array.length / 3 == verts) {\n var height = 0;\n var xyzPos = void 0;\n\n for (var p = 0; p < t.geometry.attributes.position.array.length; p += 3) {\n height = heightArr[cnt] || 0;\n colors[p] = 0;\n colors[p + 1] = 0;\n colors[p + 2] = 0;\n height = Math.min(height, 100000);\n height = Math.max(height, -100000);\n var tx_1 = xyz.x + p / 3 % _this.p.options.tileResolution / (_this.p.options.tileResolution - 1);\n var ty_1 = xyz.y + Math.floor(p / 3 / _this.p.options.tileResolution) / (_this.p.options.tileResolution - 1);\n\n var projectedLL_1 = _this.p.projection.tileXYZ2LatLng(tx_1, ty_1, xyz.z, xyz);\n\n var tlat_1 = projectedLL_1.lat;\n var tlon_1 = projectedLL_1.lng;\n\n if (_this.p.zoom <= _this.p._.zCutOff) {\n if (centerLat > 75 && tlat_1 < -88) {\n tlat_1 = 90;\n } else if (centerLat < -75 && tlat_1 > 88) {\n tlat_1 = -90;\n }\n }\n\n xyzPos = _this.p.projection.lonLatToVector3(tlon_1, tlat_1, height * _this.p.options.exaggeration);\n t.geometry.attributes.position.array[p] = xyzPos.x - centerPos.x;\n t.geometry.attributes.position.array[p + 1] = xyzPos.y - centerPos.y;\n t.geometry.attributes.position.array[p + 2] = xyzPos.z - centerPos.z;\n cnt += 1;\n }\n\n t.geometry.attributes.position.needsUpdate = true;\n t.geometry.computeVertexNormals();\n t.geometry.computeBoundingSphere();\n t.geometry.setAttribute('customColor', new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferAttribute\"](colors, 3));\n tileLoaded.data = true;\n onceTileLoaded();\n }\n };\n\n loadDemTile = false;\n layerI = null;\n\n for (i = this.p.layers.tile.length - 1; i >= 0; i--) {\n if (this.p.layers.tile[i].on && (xyz.z >= this.p.layers.tile[i].minZoom && xyz.z <= this.p.layers.tile[i].maxZoom && _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent(xyz, this.p.layers.tile[i].boundingBox, this.p.projection) || this.p.layers.tile[i].path == '_vectorsastile_')) {\n layerI = i;\n\n if (this.p.layers.tile[i].demPath != undefined) {\n loadDemTile = true;\n break;\n }\n }\n }\n\n heightArr = null;\n if (!(loadDemTile && layerI != null)) return [3, 4];\n builtDemPath = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this.p.layers.tile[layerI].format, this.p.layers.tile[layerI].demPath, xyz, this.p.projection, this.p.options.tileResolution, this.p.options.trueTileResolution, this.p.layers.tile[layerI].demFormatOptions, true);\n if (!builtDemPath) return [3, 3];\n errored_1 = false;\n return [4, Object(_parsers__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(this.p.options.customParsers, builtDemPath.path, this.p.layers.tile[layerI], builtDemPath.xyz, this.p.options.tileResolution, Math.pow(this.p.options.tileResolution, 2)).catch(function () {\n errored_1 = true;\n })];\n\n case 1:\n heightArr = _a.sent();\n if (!(errored_1 && this.p.options.demFallback != null)) return [3, 3];\n builtDemPathFallback = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this.p.options.demFallback.format, this.p.options.demFallback.demPath, xyz, this.p.projection, this.p.options.tileResolution, this.p.options.trueTileResolution, this.p.layers.tile[layerI].demFormatOptions, true);\n if (!builtDemPathFallback) return [3, 3];\n return [4, Object(_parsers__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(this.p.options.customParsers, builtDemPathFallback.path, this.p.layers.tile[layerI], builtDemPathFallback.xyz, this.p.options.tileResolution, Math.pow(this.p.options.tileResolution, 2), this.p.options.demFallback.parserType).catch(function () {})];\n\n case 2:\n heightArr = _a.sent();\n _a.label = 3;\n\n case 3:\n tileGeometry(heightArr || null);\n return [3, 7];\n\n case 4:\n if (!(this.p.options.demFallback != null)) return [3, 6];\n builtDemPathFallback = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this.p.options.demFallback.format, this.p.options.demFallback.demPath, xyz, this.p.projection, this.p.options.tileResolution, this.p.options.trueTileResolution, this.p.layers.tile[layerI].demFormatOptions, true);\n if (!builtDemPathFallback) return [3, 6];\n return [4, Object(_parsers__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(this.p.options.customParsers, builtDemPathFallback.path, this.p.layers.tile[layerI], builtDemPathFallback.xyz, this.p.options.tileResolution, Math.pow(this.p.options.tileResolution, 2), this.p.options.demFallback.parserType).catch(function () {})];\n\n case 5:\n heightArr = _a.sent();\n _a.label = 6;\n\n case 6:\n tileGeometry();\n _a.label = 7;\n\n case 7:\n return [2];\n }\n });\n });\n };\n\n TiledWorld.prototype.findTileDrawnBasedOnUUID = function (uuid) {\n var foundTile = null;\n this.tilesDrawn.forEach(function (tile) {\n if (tile.t.uuid === uuid) {\n foundTile = tile;\n return;\n }\n });\n return foundTile;\n };\n\n TiledWorld.prototype.findTileDrawnBasedOnXYZLOD = function (xyz) {\n var foundTile = null;\n this.tilesDrawn.forEach(function (tile) {\n if (tile.x === xyz.x && tile.y === xyz.y && tile.z === xyz.z && tile.isLODTile === xyz.isLODTile && tile.LODLevel == xyz.LODLevel) {\n foundTile = tile;\n return;\n }\n });\n return foundTile;\n };\n\n TiledWorld.prototype.updateRastersForTile = function (xyz) {\n var _this = this;\n\n var tD = this.findTileDrawnBasedOnXYZLOD(xyz);\n if (tD == null) return;\n var textures = [];\n var tileLayersComplete = new Array(this.p.layers.tile.length).fill(false);\n var clampedLayersComplete = new Array(this.p.layers.clamped.length).fill(false);\n\n var onceTexturesLoaded = function () {\n if (tileLayersComplete.every(Boolean) && (xyz.isLODTile || clampedLayersComplete.every(Boolean))) {\n if (textures.length == 0) {\n tD.t.visible = false;\n return;\n }\n\n textures.sort(function (a, b) {\n return a.i - b.i;\n });\n tD.from.rasters = [];\n var orderingI = 0;\n\n for (var i = 0; i < textures.length; i++) {\n if (textures[i].type == 'tile') {\n tD.from.rasters.push({\n name: textures[i].name,\n type: textures[i].type,\n texture: textures[i].texture,\n opacity: textures[i].opacity,\n isVAT: 0,\n filters: {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n blendCode: 0,\n blend: 0\n },\n i: orderingI\n });\n orderingI++;\n }\n }\n\n for (var i = 0; i < textures.length; i++) {\n if (textures[i].type == 'clamped') {\n tD.from.rasters.push({\n name: textures[i].name,\n type: textures[i].type,\n texture: textures[i].texture,\n opacity: textures[i].opacity,\n isVAT: 1,\n filters: {\n brightness: 1,\n contrast: 1,\n saturation: 1,\n blendCode: 0,\n blend: 0\n },\n i: orderingI\n });\n orderingI++;\n }\n }\n\n tD.t.material = ___WEBPACK_IMPORTED_MODULE_0__[\"Shaders\"].multiTexture(tD.from.rasters);\n\n if (_this.p.options.wireframeMode) {\n tD.t.material = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n color: 0xffffff,\n wireframe: true\n });\n }\n\n tD.t.material.needsUpdate = true;\n }\n };\n\n var _loop_1 = function (i) {\n if (this_1.p.layers.tile[i].on && tD.z >= this_1.p.layers.tile[i].minZoom && tD.z <= this_1.p.layers.tile[i].maxZoom && _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent({\n x: tD.x,\n y: tD.y,\n z: tD.z\n }, this_1.p.layers.tile[i].boundingBox, this_1.p.projection)) {\n var builtPath_1 = _utils_paths__WEBPACK_IMPORTED_MODULE_4__[\"default\"].buildPath(this_1.p.layers.tile[i].format, this_1.p.layers.tile[i].path, tD, this_1.p.projection, this_1.p.options.trueTileResolution, this_1.p.options.trueTileResolution, this_1.p.layers.tile[i].formatOptions);\n\n if (builtPath_1) {\n ;\n\n (function (i) {\n _this._.loader.load(builtPath_1, function (texture) {\n texture.magFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n texture.minFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n if (_this.p.layers.tile[i]) textures.push({\n name: _this.p.layers.tile[i].name,\n type: 'tile',\n texture: texture,\n opacity: _this.p.layers.tile[i].opacity,\n i: i\n });\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n }, function () {\n console.log('');\n }, function () {\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n });\n })(i);\n } else {\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n }\n } else {\n tileLayersComplete[i] = true;\n onceTexturesLoaded();\n }\n };\n\n var this_1 = this;\n\n for (var i = 0; i < this.p.layers.tile.length; i++) {\n _loop_1(i);\n }\n\n if (!xyz.isLODTile) {\n for (var i = 0; i < this.p.layers.clamped.length; i++) {\n if (this.p.layers.clamped[i].on && (this.p.layers.clamped[i].minZoom == null || tD.z >= this.p.layers.clamped[i].minZoom) && (this.p.layers.clamped[i].maxZoom == null || tD.z <= this.p.layers.clamped[i].maxZoom) && (this.p.layers.clamped[i].boundingBox == null || _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent({\n x: tD.x,\n y: tD.y,\n z: tD.z\n }, this.p.layers.clamped[i].boundingBox, this.p.projection))) {\n var clampedTexture = this.p.layers._.layerers.clamped.getClampedTexture(i, {\n x: tD.x,\n y: tD.y,\n z: tD.z\n });\n\n tD.contains = tD.contains || {};\n tD.contains[this.p.layers.clamped[i].name] = clampedTexture.features;\n var texture = new three__WEBPACK_IMPORTED_MODULE_1__[\"CanvasTexture\"](clampedTexture.canvas);\n texture.magFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n texture.minFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n if (this.p.layers.clamped[i]) textures.push({\n name: this.p.layers.clamped[i].name,\n type: 'clamped',\n texture: texture,\n opacity: this.p.layers.clamped[i].opacity,\n i: i\n });\n clampedLayersComplete[i] = true;\n onceTexturesLoaded();\n } else {\n clampedLayersComplete[i] = true;\n onceTexturesLoaded();\n }\n }\n }\n };\n\n TiledWorld.prototype.updateClampedRasterForTile = function (tD, layerName) {\n if (this.p.options.wireframeMode || tD.isLODTile) return;\n var clampedLayerI = null;\n\n for (var i = 0; i < this.p.layers.clamped.length; i++) {\n if (this.p.layers.clamped[i].name === layerName) {\n clampedLayerI = i;\n break;\n }\n }\n\n var clampedLayer = clampedLayerI != null ? this.p.layers.clamped[clampedLayerI] : null;\n\n if (clampedLayer && clampedLayer.on && (clampedLayer.minZoom == null || tD.z >= clampedLayer.minZoom) && (clampedLayer.maxZoom == null || tD.z <= clampedLayer.maxZoom) && (clampedLayer.boundingBox == null || _utils__WEBPACK_IMPORTED_MODULE_3__[\"default\"].isInExtent({\n x: tD.x,\n y: tD.y,\n z: tD.z\n }, clampedLayer.boundingBox, this.p.projection))) {\n var clampedTexture = this.p.layers._.layerers.clamped.getClampedTexture(clampedLayerI, {\n x: tD.x,\n y: tD.y,\n z: tD.z\n });\n\n tD.contains = tD.contains || {};\n tD.contains[this.p.layers.clamped[clampedLayerI].name] = clampedTexture.features;\n var texture = new three__WEBPACK_IMPORTED_MODULE_1__[\"CanvasTexture\"](clampedTexture.canvas);\n texture.magFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n texture.minFilter = three__WEBPACK_IMPORTED_MODULE_1__[\"NearestFilter\"];\n\n for (var i = 0; i < tD.from.rasters.length; i++) {\n if (tD.from.rasters[i].name === layerName) {\n tD.from.rasters[i].texture = texture;\n break;\n }\n }\n\n tD.t.material = ___WEBPACK_IMPORTED_MODULE_0__[\"Shaders\"].multiTexture(tD.from.rasters);\n tD.t.material.needsUpdate = true;\n }\n };\n\n TiledWorld.prototype.updateAllRasters = function () {\n this.killDrawingTiles();\n var startingLength = this.tilesDrawn.length;\n\n for (var j = 0; j < startingLength; j++) {\n var tD = this.tilesDrawn[j];\n this.updateRastersForTile({\n x: tD.x,\n y: tD.y,\n z: tD.z,\n isLODTile: tD.isLODTile,\n LODLevel: tD.LODLevel\n });\n }\n };\n\n TiledWorld.prototype.removeTile = function (i, shouldFadeOut) {\n shouldFadeOut = false;\n\n if (this.tilesDrawn[i]) {\n if (shouldFadeOut) {\n this.tilesDrawn[i].fadeOutAndRemove = true;\n } else {\n this.tilesDrawn[i].t.geometry.dispose();\n this.tilesDrawn[i].t.material.dispose();\n if (this.tilesDrawn[i].isLODTile) this.p.planetsLOD[this.tilesDrawn[i].LODLevel].remove(this.tilesDrawn[i].t);else this.p.planet.remove(this.tilesDrawn[i].t);\n this.tilesDrawn.splice(i, 1);\n }\n }\n };\n\n TiledWorld.prototype.removeAllTiles = function () {\n this.killDrawingTiles();\n\n for (var j = 0; j < this.tilesDrawn.length; j++) {\n this.removeTile(0);\n }\n };\n\n TiledWorld.prototype.outdateAllTiles = function () {\n this.killDrawingTiles();\n this.tilesDrawn.forEach(function (tile) {\n tile.outdated = true;\n });\n };\n\n TiledWorld.prototype.removeAllOutdatedTiles = function () {\n var _this = this;\n\n var outdatedTileIndices = [];\n this.tilesDrawn.forEach(function (t, i) {\n if (t.outdated) outdatedTileIndices.push(i);\n });\n outdatedTileIndices = outdatedTileIndices.sort().reverse();\n outdatedTileIndices.forEach(function (i) {\n _this.removeTile(i);\n });\n };\n\n TiledWorld.prototype.removeTileXYZ = function (xyz) {\n for (var t in this.tilesDrawn) {\n if (this.tilesDrawn[t].x == xyz.x && this.tilesDrawn[t].y == xyz.y && this.tilesDrawn[t].z == xyz.z) {\n this.tilesDrawn[t].t.geometry.dispose();\n this.tilesDrawn[t].t.material.dispose();\n if (this.tilesDrawn[t].isLODTile) this.p.planetsLOD[this.tilesDrawn[t].LODLevel].remove(this.tilesDrawn[t].t);else this.p.planet.remove(this.tilesDrawn[t].t);\n this.tilesDrawn.splice(t, 1);\n }\n }\n };\n\n TiledWorld.prototype.killDrawingTiles = function () {\n for (var t in this.tilesToBeDrawn) {\n this.tilesToBeDrawn[t].make = false;\n }\n\n for (var t in this.tilesBeingDrawn) {\n this.tilesBeingDrawn[t].make = false;\n }\n };\n\n TiledWorld.prototype.filterEffects = function () {\n var _this = this;\n\n var transitionFilters = ['brightness', 'contrast', 'saturation', 'blendCode'];\n\n var _loop_2 = function (m) {\n var _loop_3 = function (n) {\n if (this_2.tilesDrawn[m] && this_2.tilesDrawn[m].t && this_2.tilesDrawn[m].t.material.hasOwnProperty('uniforms')) {\n var layer_1 = this_2.p.layers.getLayerByName(this_2.tilesDrawn[m].from.rasters[n].name);\n\n if (layer_1 && layer_1.filters) {\n transitionFilters.forEach(function (f) {\n var desiredFilter = layer_1.filters[f];\n if (desiredFilter == null) return;\n var currentFilter = _this.tilesDrawn[m].t.material.uniforms[\"f\" + f + n].value;\n\n if (f == 'blendCode') {\n _this.tilesDrawn[m].t.material.uniforms[\"f\" + f + n].value = desiredFilter;\n } else if (desiredFilter > currentFilter) {\n _this.tilesDrawn[m].t.material.uniforms[\"f\" + f + n].value = Math.min(_this.tilesDrawn[m].t.material.uniforms[\"f\" + f + n].value + 0.1, desiredFilter);\n } else {\n _this.tilesDrawn[m].t.material.uniforms[\"f\" + f + n].value = Math.max(_this.tilesDrawn[m].t.material.uniforms[\"f\" + f + n].value - 0.1, desiredFilter);\n }\n });\n }\n }\n };\n\n for (var n in this_2.tilesDrawn[m].from.rasters) {\n _loop_3(n);\n }\n };\n\n var this_2 = this;\n\n for (var m in this.tilesDrawn) {\n _loop_2(m);\n }\n };\n\n TiledWorld.prototype.fadeInTiles = function () {\n for (var m in this.tilesDrawn) {\n if (!this.tilesDrawn[m].fadeOutAndRemove) for (var n in this.tilesDrawn[m].from.rasters) {\n if (this.tilesDrawn[m] && this.tilesDrawn[m].t && this.tilesDrawn[m].t.material.hasOwnProperty('uniforms')) {\n var layer = this.p.layers.getLayerByName(this.tilesDrawn[m].from.rasters[n].name);\n\n if (layer) {\n var desiredOpacity = layer.opacity;\n var currentOpacity = this.tilesDrawn[m].t.material.uniforms['tA' + n].value;\n\n if (desiredOpacity > currentOpacity) {\n this.tilesDrawn[m].t.material.uniforms['tA' + n].value = Math.min(this.tilesDrawn[m].t.material.uniforms['tA' + n].value + 0.1, desiredOpacity);\n } else {\n this.tilesDrawn[m].t.material.uniforms['tA' + n].value = Math.max(this.tilesDrawn[m].t.material.uniforms['tA' + n].value - 0.1, desiredOpacity);\n }\n }\n }\n }\n }\n };\n\n TiledWorld.prototype.fadeOutTiles = function () {\n for (var i = this.tilesDrawn.length - 1; i >= 0; i--) {\n if (this.tilesDrawn[i].fadeOutAndRemove) {\n for (var n = 0; this.tilesDrawn[i] && n < this.tilesDrawn[i].from.rasters.length; n++) {\n if (this.tilesDrawn[i] && this.tilesDrawn[i].t && this.tilesDrawn[i].t.material.hasOwnProperty('uniforms') && this.tilesDrawn[i].t.material.uniforms['tA' + n] != null) {\n var nextOpacity = Math.max(this.tilesDrawn[i].t.material.uniforms['tA' + n].value - 0.1, 0);\n if (nextOpacity <= 0) this.removeTile(i);else {\n this.tilesDrawn[i].t.material.uniforms['tA' + n].value = nextOpacity;\n }\n } else {\n this.removeTile(i);\n }\n }\n }\n }\n };\n\n return TiledWorld;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (TiledWorld);\n\n//# sourceURL=webpack://LithoSphere/./src/core/tiledWorld.ts?"); /***/ }), @@ -1972,7 +2020,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var ___W /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n\nvar opacityTimeout = null;\n\nvar ClampedLayerer = function () {\n function ClampedLayerer(parent) {\n var _this = this;\n\n this.add = function (layerObj, callback) {\n if (!_this.p.p._.wasInitialized) return;\n var alreadyExists = false;\n\n var finallyAdd = function () {\n for (var i = 0; i < _this.p.clamped.length; i++) {\n if (_this.p.clamped[i].hasOwnProperty('name')) {\n if (_this.p.clamped[i].name == layerObj.name) {\n _this.p.clamped[i] = layerObj;\n alreadyExists = true;\n break;\n }\n }\n }\n\n if (!alreadyExists) {\n _this.p.clamped.push(layerObj);\n\n _this.p.clamped.sort(function (a, b) {\n return a.order - b.order;\n });\n }\n\n if (_this.p.p.zoom >= layerObj.minZoom && _this.p.p.zoom <= layerObj.maxZoom) {\n _this.p.p._.tiledWorld.updateAllRasters();\n }\n\n if (typeof callback === 'function') callback();\n };\n\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n if (layerObj.hasOwnProperty('name') && layerObj.hasOwnProperty('on') && (layerObj.preDrawn === true && layerObj.hasOwnProperty('data') || (layerObj.hasOwnProperty('geojsonPath') || layerObj.hasOwnProperty('geojson')) && layerObj.hasOwnProperty('minZoom') && layerObj.hasOwnProperty('maxZoom'))) {\n if (layerObj.hasOwnProperty('geojsonPath') && !layerObj.hasOwnProperty('geojson')) {\n if (!layerObj.hasOwnProperty('opacity')) layerObj.opacity = 1;\n var xhr_1 = new XMLHttpRequest();\n xhr_1.open('GET', layerObj.geojsonPath, true);\n xhr_1.responseType = 'json';\n xhr_1.withCredentials = layerObj.withCredentials === true || false;\n\n xhr_1.onload = function () {\n if (xhr_1.status !== 404 && xhr_1.response) {\n layerObj.geojson = xhr_1.response;\n finallyAdd();\n } else {\n console.warn(\"Failed to fetch geojson data for clamped layer: \" + layerObj.name);\n }\n };\n\n xhr_1.send();\n } else {\n finallyAdd();\n }\n } else {\n console.warn(\"Attempted to add an invalid clamped layer: \" + layerObj.name);\n }\n };\n\n this.toggle = function (name, on) {\n if (!_this.p.p._.wasInitialized) return false;\n var foundMatch = false;\n\n _this.p.clamped.forEach(function (layer) {\n if (name === layer.name) {\n layer.on = on != null ? on : !layer.on;\n foundMatch = true;\n }\n });\n\n if (foundMatch) {\n _this.p.p._.tiledWorld.updateAllRasters();\n\n return true;\n }\n\n return false;\n };\n\n this.setOpacity = function (name, opacity) {\n if (!_this.p.p._.wasInitialized) return false;\n\n var _loop_1 = function (i) {\n var layer = _this.p.clamped[i];\n\n if (name === layer.name) {\n clearTimeout(opacityTimeout);\n opacityTimeout = setTimeout(function () {\n layer.opacity = Math.max(Math.min(opacity, 1), 0);\n\n if (_this.p.p.zoom >= layer.minZoom && _this.p.p.zoom <= layer.maxZoom) {\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n _this.p.p._.tiledWorld.updateAllRasters();\n }\n }, 250);\n return {\n value: true\n };\n }\n };\n\n for (var i = 0; i < _this.p.clamped.length; i++) {\n var state_1 = _loop_1(i);\n\n if (typeof state_1 === \"object\") return state_1.value;\n }\n\n return false;\n };\n\n this.remove = function (name) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.clamped.length; i++) {\n if (_this.p.clamped[i].hasOwnProperty('name')) {\n if (_this.p.clamped[i].name == name) {\n var minZoom = _this.p.clamped[i].minZoom;\n var maxZoom = _this.p.clamped[i].maxZoom;\n\n if (_this.p.p.zoom >= minZoom && _this.p.p.zoom <= maxZoom) {\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n _this.p.p._.tiledWorld.updateAllRasters();\n }\n\n _this.p.clamped.splice(i, 1);\n\n return true;\n }\n }\n }\n\n return false;\n };\n\n this.getClampedTexture = function (i, xyz) {\n var scaleFactor = 0.5;\n var c = _this.p.clamped[i];\n var canvas = document.createElement('canvas');\n canvas.id = 'vectorsastile';\n canvas.width = 256 / scaleFactor;\n scaleFactor = scaleFactor * Math.pow(2, _this.p.p.zoom - xyz.z);\n canvas.height = canvas.width;\n var ctx = canvas.getContext('2d');\n var x;\n var y;\n var overlappedFeatures = [];\n\n if (scaleFactor < 128) {\n if (c.preDrawn) {\n ctx.imageSmoothingEnabled = false;\n\n if (c.data && c.data[xyz.z] && c.data[xyz.z][xyz.x] && c.data[xyz.z][xyz.x][xyz.y] != null) {\n ctx.drawImage(c.data[xyz.z][xyz.x][xyz.y], 0, 0, canvas.width, canvas.height);\n }\n } else {\n for (var _i = 0, _a = c.geojson.features; _i < _a.length; _i++) {\n var f = _a[_i];\n\n var style = _this.p.getFeatureStyle(c, f);\n\n var doesFeatureOverlapTile = false;\n\n if (style.fillColor.substring(0, 3).toLowerCase() != 'rgb') {\n var col = _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].hexToRGB(style.fillColor);\n\n if (col) {\n style.fillColor = 'rgba(' + col.r + ',' + col.g + ',' + col.b + ',' + style.fillOpacity + ')';\n }\n } else {\n var rgb = style.fillColor.substring(4, style.fillColor.length - 1).replace(/ /g, '').split(',');\n style.fillColor = 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + style.fillOpacity + ')';\n }\n\n ctx.fillStyle = style.fillColor;\n ctx.strokeStyle = style.color;\n ctx.lineWidth = style.weight * (1 / scaleFactor * 1);\n ctx.globalAlpha = c.opacity;\n ctx.lineCap = 'round';\n style.radius *= 1 / scaleFactor * 1 || 10;\n\n if ((f.geometry.type == 'Polygon' || f.geometry.type == 'MultiPolygon') && f.geometry.coordinates[0]) {\n for (var p = 0; p < f.geometry.coordinates.length; p++) {\n if (typeof f.geometry.coordinates[p][0][0] === 'number') {\n for (var i_1 = 0; i_1 < f.geometry.coordinates[p].length; i_1++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][i_1][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][i_1][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (i_1 == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n } else if (typeof f.geometry.coordinates[p][0][0][0] === 'number') {\n for (var i_2 = 0; i_2 < f.geometry.coordinates[p].length; i_2++) {\n for (var j = 0; j < f.geometry.coordinates[p][i_2].length; j++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][i_2][j][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][i_2][j][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (j == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n }\n }\n\n ctx.stroke();\n ctx.closePath();\n ctx.fill();\n }\n } else if (f.geometry.type == 'LineString' || f.geometry.type == 'MultiLineString') {\n if (typeof f.geometry.coordinates[0][0] === 'number') {\n for (var p = 0; p < f.geometry.coordinates.length; p++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (p == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n\n ctx.stroke();\n } else if (typeof f.geometry.coordinates[0][0][0] === 'number') {\n for (var p = 0; p < f.geometry.coordinates.length; p++) {\n for (var i_3 = 0; i_3 < f.geometry.coordinates[p].length; i_3++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][i_3][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][i_3][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (i_3 == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n\n ctx.stroke();\n }\n }\n } else if (f.geometry.type.toLowerCase() === 'point') {\n var lnglat = void 0;\n\n if (typeof f.geometry.coordinates[0] === 'number') {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[1], xyz.z);\n lnglat = {\n lng: f.geometry.coordinates[0],\n lat: f.geometry.coordinates[1]\n };\n } else {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[0][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[0][1], xyz.z);\n lnglat = {\n lng: f.geometry.coordinates[0][0],\n lat: f.geometry.coordinates[0][1]\n };\n }\n\n var lnglatRadiusAway = _this.p.p.projection.tileXYZ2LatLng(x + style.radius / canvas.width, y, _this.p.p.zoom);\n\n f._radiusInMeters = _this.p.p.projection.lngLatDistBetween(lnglat.lng, lnglat.lat, lnglatRadiusAway.lng, lnglatRadiusAway.lat);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n ctx.beginPath();\n ctx.arc(canvasX, canvasY, style.radius, 0, 2 * Math.PI, false);\n ctx.fill();\n ctx.stroke();\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n\n if (doesFeatureOverlapTile) {\n f._highlighted = f._highlighted || false;\n overlappedFeatures.push(f);\n }\n }\n }\n }\n\n return {\n canvas: canvas,\n features: overlappedFeatures\n };\n };\n\n this.p = parent;\n }\n\n return ClampedLayerer;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ClampedLayerer);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/clamped.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n\nvar opacityTimeout = null;\n\nvar ClampedLayerer = function () {\n function ClampedLayerer(parent) {\n var _this = this;\n\n this.add = function (layerObj, callback) {\n if (!_this.p.p._.wasInitialized) return;\n var alreadyExists = false;\n\n var finallyAdd = function () {\n for (var i = 0; i < _this.p.clamped.length; i++) {\n if (_this.p.clamped[i].hasOwnProperty('name')) {\n if (_this.p.clamped[i].name == layerObj.name) {\n _this.p.clamped[i] = layerObj;\n alreadyExists = true;\n break;\n }\n }\n }\n\n if (!alreadyExists) {\n _this.p.clamped.push(layerObj);\n\n _this.p.clamped.sort(function (a, b) {\n return a.order - b.order;\n });\n }\n\n if (_this.p.p.zoom >= layerObj.minZoom && _this.p.p.zoom <= layerObj.maxZoom) {\n _this.p.p._.tiledWorld.updateAllRasters();\n }\n\n if (typeof callback === 'function') callback();\n };\n\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n if (layerObj.hasOwnProperty('name') && layerObj.hasOwnProperty('on') && (layerObj.preDrawn === true && layerObj.hasOwnProperty('data') || (layerObj.hasOwnProperty('geojsonPath') || layerObj.hasOwnProperty('geojson')) && layerObj.hasOwnProperty('minZoom') && layerObj.hasOwnProperty('maxZoom'))) {\n if (layerObj.hasOwnProperty('geojsonPath') && !layerObj.hasOwnProperty('geojson')) {\n if (!layerObj.hasOwnProperty('opacity')) layerObj.opacity = 1;\n var xhr_1 = new XMLHttpRequest();\n xhr_1.open('GET', layerObj.geojsonPath, true);\n xhr_1.responseType = 'json';\n xhr_1.withCredentials = layerObj.withCredentials === true || false;\n\n xhr_1.onload = function () {\n if (xhr_1.status !== 404 && xhr_1.response) {\n layerObj.geojson = xhr_1.response;\n finallyAdd();\n } else {\n console.warn(\"Failed to fetch geojson data for clamped layer: \" + layerObj.name);\n }\n };\n\n xhr_1.send();\n } else {\n finallyAdd();\n }\n } else {\n console.warn(\"Attempted to add an invalid clamped layer: \" + layerObj.name);\n }\n };\n\n this.toggle = function (name, on) {\n if (!_this.p.p._.wasInitialized) return false;\n var foundMatch = false;\n\n _this.p.clamped.forEach(function (layer) {\n if (name === layer.name) {\n layer.on = on != null ? on : !layer.on;\n foundMatch = true;\n }\n });\n\n if (foundMatch) {\n _this.p.p._.tiledWorld.updateAllRasters();\n\n return true;\n }\n\n return false;\n };\n\n this.setOpacity = function (name, opacity) {\n if (!_this.p.p._.wasInitialized) return false;\n\n var _loop_1 = function (i) {\n var layer = _this.p.clamped[i];\n\n if (name === layer.name) {\n clearTimeout(opacityTimeout);\n opacityTimeout = setTimeout(function () {\n layer.opacity = Math.max(Math.min(opacity, 1), 0);\n\n if (_this.p.p.zoom >= layer.minZoom && _this.p.p.zoom <= layer.maxZoom) {\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n _this.p.p._.tiledWorld.updateAllRasters();\n }\n }, 250);\n return {\n value: true\n };\n }\n };\n\n for (var i = 0; i < _this.p.clamped.length; i++) {\n var state_1 = _loop_1(i);\n\n if (typeof state_1 === \"object\") return state_1.value;\n }\n\n return false;\n };\n\n this.remove = function (name) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.clamped.length; i++) {\n if (_this.p.clamped[i].hasOwnProperty('name')) {\n if (_this.p.clamped[i].name == name) {\n var minZoom = _this.p.clamped[i].minZoom;\n var maxZoom = _this.p.clamped[i].maxZoom;\n\n _this.p.clamped.splice(i, 1);\n\n if (_this.p.p.zoom >= minZoom && _this.p.p.zoom <= maxZoom) {\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n _this.p.p._.tiledWorld.updateAllRasters();\n }\n\n return true;\n }\n }\n }\n\n return false;\n };\n\n this.getClampedTexture = function (i, xyz) {\n var _a;\n\n var scaleFactor = 0.5;\n var c = _this.p.clamped[i];\n var canvas = document.createElement('canvas');\n canvas.id = 'vectorsastile';\n canvas.width = 256 / scaleFactor;\n scaleFactor = scaleFactor * Math.pow(2, _this.p.p.zoom - xyz.z);\n canvas.height = canvas.width;\n var ctx = canvas.getContext('2d');\n var x;\n var y;\n var overlappedFeatures = [];\n\n if (scaleFactor < 128) {\n if (c.preDrawn) {\n ctx.imageSmoothingEnabled = false;\n\n if (c.data && c.data[xyz.z] && c.data[xyz.z][xyz.x] && c.data[xyz.z][xyz.x][xyz.y] != null) {\n ctx.drawImage(c.data[xyz.z][xyz.x][xyz.y], 0, 0, canvas.width, canvas.height);\n }\n } else {\n for (var _i = 0, _b = c.geojson.features; _i < _b.length; _i++) {\n var f = _b[_i];\n\n var style = _this.p.getFeatureStyle(c, f);\n\n var doesFeatureOverlapTile = false;\n\n if (style.fillColor.substring(0, 3).toLowerCase() != 'rgb') {\n var col = _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].hexToRGB(style.fillColor);\n\n if (col) {\n style.fillColor = 'rgba(' + col.r + ',' + col.g + ',' + col.b + ',' + style.fillOpacity + ')';\n }\n } else {\n var rgb = style.fillColor.substring(4, style.fillColor.length - 1).replace(/ /g, '').split(',');\n style.fillColor = 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + style.fillOpacity + ')';\n }\n\n ctx.fillStyle = style.fillColor;\n ctx.strokeStyle = style.color;\n ctx.lineWidth = style.weight * (1 / scaleFactor * 1);\n ctx.globalAlpha = c.opacity;\n ctx.lineCap = 'round';\n style.radius *= 1 / scaleFactor * 1 || 10;\n\n if ((f.geometry.type == 'Polygon' || f.geometry.type == 'MultiPolygon') && f.geometry.coordinates[0]) {\n for (var p = 0; p < f.geometry.coordinates.length; p++) {\n if (typeof f.geometry.coordinates[p][0][0] === 'number') {\n for (var i_1 = 0; i_1 < f.geometry.coordinates[p].length; i_1++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][i_1][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][i_1][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (i_1 == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n } else if (typeof f.geometry.coordinates[p][0][0][0] === 'number') {\n for (var i_2 = 0; i_2 < f.geometry.coordinates[p].length; i_2++) {\n for (var j = 0; j < f.geometry.coordinates[p][i_2].length; j++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][i_2][j][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][i_2][j][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (j == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n }\n }\n\n ctx.stroke();\n ctx.closePath();\n ctx.fill();\n }\n } else if (f.geometry.type == 'LineString' || f.geometry.type == 'MultiLineString') {\n if (typeof f.geometry.coordinates[0][0] === 'number') {\n for (var p = 0; p < f.geometry.coordinates.length; p++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (p == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n\n ctx.stroke();\n } else if (typeof f.geometry.coordinates[0][0][0] === 'number') {\n for (var p = 0; p < f.geometry.coordinates.length; p++) {\n for (var i_3 = 0; i_3 < f.geometry.coordinates[p].length; i_3++) {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[p][i_3][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[p][i_3][1], xyz.z);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if (i_3 == 0) {\n ctx.beginPath();\n ctx.moveTo(canvasX, canvasY);\n } else {\n ctx.lineTo(canvasX, canvasY);\n }\n\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n\n ctx.stroke();\n }\n }\n } else if (f.geometry.type.toLowerCase() === 'point') {\n var lnglat = void 0;\n\n if (typeof f.geometry.coordinates[0] === 'number') {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[1], xyz.z);\n lnglat = {\n lng: f.geometry.coordinates[0],\n lat: f.geometry.coordinates[1]\n };\n } else {\n x = _this.p.p.projection.lon2tileUnfloored(f.geometry.coordinates[0][0], xyz.z);\n y = _this.p.p.projection.lat2tileUnfloored(f.geometry.coordinates[0][1], xyz.z);\n lnglat = {\n lng: f.geometry.coordinates[0][0],\n lat: f.geometry.coordinates[0][1]\n };\n }\n\n var lnglatRadiusAway = _this.p.p.projection.tileXYZ2LatLng(x + (style.radius + ctx.lineWidth) / canvas.width, y, _this.p.p.zoom);\n\n f._radiusInMeters = _this.p.p.projection.lngLatDistBetween(lnglat.lng, lnglat.lat, lnglatRadiusAway.lng, lnglatRadiusAway.lat);\n var canvasX = parseInt((x - xyz.x) * canvas.width);\n var canvasY = parseInt((y - xyz.y) * canvas.height);\n\n if ((_a = c.style) === null || _a === void 0 ? void 0 : _a.bearing) {\n var unit = c.style.bearing.angleUnit || 'deg';\n var bearingProp = c.style.bearing.angleProp || false;\n var yaw = 0;\n\n if (bearingProp !== false) {\n yaw = parseFloat(_utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getIn(f.properties, bearingProp, 0));\n\n if (unit === 'deg') {\n yaw = yaw * (Math.PI / 180);\n }\n }\n\n yaw += Math.PI;\n var startingPoint = _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].rotatePoint({\n x: canvasX,\n y: canvasY + style.radius + ctx.lineWidth - 2\n }, [canvasX, canvasY], yaw - 45 * (Math.PI / 180));\n var indicator = [_utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].rotatePoint({\n x: canvasX,\n y: canvasY + style.radius * 2\n }, [canvasX, canvasY], yaw), _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].rotatePoint({\n x: canvasX,\n y: canvasY + style.radius + ctx.lineWidth - 2\n }, [canvasX, canvasY], yaw + 45 * (Math.PI / 180)), startingPoint];\n ctx.fillStyle = c.style.bearing.color || 'red';\n ctx.lineWidth = 1 / scaleFactor * 1;\n ctx.beginPath();\n ctx.moveTo(startingPoint.x, startingPoint.y);\n indicator.forEach(function (ind) {\n ctx.lineTo(ind.x, ind.y);\n });\n ctx.closePath();\n ctx.fill();\n ctx.stroke();\n ctx.fillStyle = style.fillColor;\n ctx.lineWidth = style.weight * (1 / scaleFactor * 1);\n }\n\n ctx.beginPath();\n ctx.arc(canvasX, canvasY, style.radius, 0, 2 * Math.PI, false);\n ctx.fill();\n ctx.stroke();\n if (canvasX >= 0 && canvasX < canvas.width && canvasY >= 0 && canvasY < canvas.height) doesFeatureOverlapTile = true;\n }\n\n if (doesFeatureOverlapTile) {\n f._highlighted = f._highlighted || false;\n overlappedFeatures.push(f);\n }\n }\n }\n }\n\n return {\n canvas: canvas,\n features: overlappedFeatures\n };\n };\n\n this.p = parent;\n }\n\n return ClampedLayerer;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ClampedLayerer);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/clamped.ts?"); /***/ }), @@ -1984,7 +2032,19 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _uti /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n/* harmony import */ var _tile3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./tile3d */ \"./src/layers/tile3d.ts\");\n/* harmony import */ var _tile__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tile */ \"./src/layers/tile.ts\");\n/* harmony import */ var _clamped__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./clamped */ \"./src/layers/clamped.ts\");\n/* harmony import */ var _vector__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./vector */ \"./src/layers/vector.ts\");\n\n\n\n\n\n\nvar Layers = function () {\n function Layers(parent) {\n var _this = this;\n\n this.addLayer = function (type, layerObj, callback, sI) {\n if (layerObj.on == 1) layerObj.on = true;else if (layerObj.on == 0) layerObj.on = false;\n if (_this._.layerers[type]) _this._.layerers[type].add(layerObj, callback);else console.warn(\"Cannot add unknown layer type \" + type + \".\");\n };\n\n this.removeLayer = function (name) {\n var foundMatch = false;\n\n for (var type in _this._.layerers) {\n var didRemove = _this._.layerers[type].remove(name);\n\n if (didRemove) foundMatch = true;\n }\n\n if (!foundMatch) {\n return false;\n }\n\n return true;\n };\n\n this.toggleLayer = function (name, on) {\n var foundMatch = false;\n\n for (var type in _this._.layerers) {\n var didToggle = _this._.layerers[type].toggle(name, on);\n\n if (didToggle) foundMatch = true;\n }\n\n if (!foundMatch) {\n return false;\n }\n\n return true;\n };\n\n this.setLayerOpacity = function (name, opacity) {\n var foundMatch = false;\n\n for (var type in _this._.layerers) {\n var didOpacity = _this._.layerers[type].setOpacity(name, parseFloat(opacity));\n\n if (didOpacity) foundMatch = true;\n }\n\n if (!foundMatch) {\n console.warn(\"Could not find a layer named '\" + name + \"' to set the opacity of.\");\n return false;\n }\n\n return true;\n };\n\n this.findHighestMaxZoom = function () {\n var highest = 0;\n\n for (var l in _this.tile) {\n if (_this.tile[l].on) if (_this.tile[l].maxZoom > highest) {\n highest = _this.tile[l].maxZoom;\n }\n }\n\n return highest;\n };\n\n this.findLowestMinZoom = function () {\n var lowest = Infinity;\n\n for (var l in _this.tile) {\n if (_this.tile[l].on) if (_this.tile[l].minZoom < lowest) {\n lowest = _this.tile[l].minZoom;\n }\n }\n\n return lowest;\n };\n\n this.getFeatureStyleProp = function (value, feature) {\n if (value != null && typeof value === 'string' && value.includes('=')) {\n var propValue = null;\n var split = value.split('=');\n propValue = _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getIn(feature.properties, split[1].split('.'));\n return propValue;\n } else {\n return value;\n }\n };\n\n this.getLayerByName = function (layerName) {\n for (var type in _this.all) {\n for (var i = 0; i < _this.all[type].length; i++) {\n if (_this.all[type][i].name === layerName) return _this.all[type][i];\n }\n }\n\n return null;\n };\n\n this.getFeatureStyle = function (layer, feature, isStrokeless) {\n var _a;\n\n var style = JSON.parse(JSON.stringify(_this.baseStyle));\n\n if (layer.style) {\n var geomType = feature.geometry.type.toLowerCase();\n\n for (var key in style) {\n if (layer.style.default && layer.style.default[key] != null) {\n var defaultOverride = _this.getFeatureStyleProp(layer.style.default[key], feature);\n\n style[key] = defaultOverride != null ? defaultOverride : style[key];\n }\n\n if (geomType === 'point' && layer.style.point) {\n var pointOverride = _this.getFeatureStyleProp(layer.style.point[key], feature);\n\n style[key] = pointOverride != null ? pointOverride : style[key];\n } else if (geomType === 'linestring' && layer.style.line) {\n var lineOverride = _this.getFeatureStyleProp(layer.style.line[key], feature);\n\n style[key] = lineOverride != null ? lineOverride : style[key];\n } else if (geomType === 'polygon' && layer.style.polygon) {\n var polygonOverride = _this.getFeatureStyleProp(layer.style.polygon[key], feature);\n\n style[key] = polygonOverride != null ? polygonOverride : style[key];\n }\n\n if (layer.style.byProp) {\n for (var propPath in layer.style.byProp) {\n var path = propPath.split(':')[0].split('=')[1];\n var value = propPath.split(':')[1];\n\n if (_utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getIn(feature.properties, path.split('.')) === value) {\n var propOverride = _this.getFeatureStyleProp(layer.style.byProp[propPath][key], feature);\n\n style[key] = propOverride != null ? propOverride : style[key];\n }\n }\n }\n\n if (layer.style.letPropertiesStyleOverride === true) {\n var styleOverride = _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getIn((_a = feature.properties) === null || _a === void 0 ? void 0 : _a.style, key);\n style[key] = styleOverride != null ? styleOverride : style[key];\n }\n }\n }\n\n if (style.fillColor === 'none') style.fillColor = 'rgba(0,0,0,0)';\n\n if (feature._active) {\n style.fillColor = _this.p.options.activeColor || 'red';\n } else if (feature._highlighted) {\n style.fillColor = _this.p.options.highlightColor || 'yellow';\n }\n\n if (isStrokeless === true) {\n style.color = style.fillColor;\n }\n\n return style;\n };\n\n this.p = parent;\n this.baseStyle = {\n fillColor: 'rgb(0,0,0)',\n fillOpacity: 0.4,\n color: 'rgb(255,255,255)',\n weight: 2,\n radius: 6\n };\n this._ = {\n layerers: {\n tile3d: new _tile3d__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this),\n tile: new _tile__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this),\n clamped: new _clamped__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this),\n vector: new _vector__WEBPACK_IMPORTED_MODULE_4__[\"default\"](this)\n }\n };\n\n this._reset();\n }\n\n Layers.prototype._reset = function () {\n this.tile3d = [];\n this.tile = [];\n this.clamped = [];\n this.vector = [];\n this.all = {\n tile3d: this.tile3d,\n tile: this.tile,\n clamped: this.clamped,\n vector: this.vector\n };\n };\n\n return Layers;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Layers);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/index.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n/* harmony import */ var _tile3d__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./tile3d */ \"./src/layers/tile3d.ts\");\n/* harmony import */ var _tile__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./tile */ \"./src/layers/tile.ts\");\n/* harmony import */ var _clamped__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./clamped */ \"./src/layers/clamped.ts\");\n/* harmony import */ var _vector__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./vector */ \"./src/layers/vector.ts\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./model */ \"./src/layers/model.ts\");\n\n\n\n\n\n\n\nvar Layers = function () {\n function Layers(parent) {\n var _this = this;\n\n this.addLayer = function (type, layerObj, callback, sI) {\n if (layerObj.on == 1) layerObj.on = true;else if (layerObj.on == 0) layerObj.on = false;\n layerObj._type = type;\n if (_this._.layerers[type]) _this._.layerers[type].add(layerObj, callback);else console.warn(\"Cannot add unknown layer type \" + type + \".\");\n };\n\n this.removeLayer = function (name) {\n var foundMatch = false;\n\n for (var type in _this._.layerers) {\n var didRemove = _this._.layerers[type].remove(name);\n\n if (didRemove) foundMatch = true;\n }\n\n if (!foundMatch) {\n return false;\n }\n\n return true;\n };\n\n this.toggleLayer = function (name, on) {\n var foundMatch = false;\n\n for (var type in _this._.layerers) {\n var didToggle = _this._.layerers[type].toggle(name, on);\n\n if (didToggle) foundMatch = true;\n }\n\n if (!foundMatch) {\n return false;\n }\n\n return true;\n };\n\n this.setLayerOpacity = function (name, opacity) {\n var foundMatch = false;\n\n for (var type in _this._.layerers) {\n var didOpacity = _this._.layerers[type].setOpacity(name, parseFloat(opacity));\n\n if (didOpacity) foundMatch = true;\n }\n\n if (!foundMatch) {\n console.warn(\"Could not find a layer named '\" + name + \"' to set the opacity of.\");\n return false;\n }\n\n return true;\n };\n\n this.setLayerFilterEffect = function (name, filter, value) {\n var allowableFilterEffects = ['brightness', 'contrast', 'saturation', 'blendCode'];\n\n if (!allowableFilterEffects.includes(filter)) {\n console.warn(\"Filter \" + filter + \" must be one of: \" + allowableFilterEffects.toString() + \".\");\n return false;\n }\n\n var didFilter = _this._.layerers.tile.setFilterEffect(name, filter, parseFloat(value));\n\n if (!didFilter) {\n console.warn(\"Could not find tile layer named '\" + name + \"' to set the filter of.\");\n return false;\n }\n\n return true;\n };\n\n this.findHighestMaxZoom = function () {\n var highest = 0;\n\n for (var l in _this.tile) {\n if (_this.tile[l].on) if (_this.tile[l].maxZoom > highest) {\n highest = _this.tile[l].maxZoom;\n }\n }\n\n return highest;\n };\n\n this.findLowestMinZoom = function () {\n var lowest = Infinity;\n\n for (var l in _this.tile) {\n if (_this.tile[l].on) if (_this.tile[l].minZoom < lowest) {\n lowest = _this.tile[l].minZoom;\n }\n }\n\n return lowest;\n };\n\n this.getFeatureStyleProp = function (value, feature) {\n if (value != null && typeof value === 'string' && value.includes('=')) {\n var propValue = null;\n var split = value.split('=');\n propValue = _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getIn(feature.properties, split[1].split('.'));\n return propValue;\n } else {\n return value;\n }\n };\n\n this.getLayerByName = function (layerName) {\n for (var type in _this.all) {\n for (var i = 0; i < _this.all[type].length; i++) {\n if (_this.all[type][i].name === layerName) return _this.all[type][i];\n }\n }\n\n return null;\n };\n\n this.hasLayer = function (layerName) {\n return _this.getLayerByName(layerName) != null;\n };\n\n this.getFeatureStyle = function (layer, feature, isStrokeless) {\n var _a, _b;\n\n var style = JSON.parse(JSON.stringify(_this.baseStyle));\n\n if (layer.style) {\n var geomType = feature.geometry.type.toLowerCase();\n\n for (var key in style) {\n if (layer.style.default && layer.style.default[key] != null) {\n var defaultOverride = _this.getFeatureStyleProp(layer.style.default[key], feature);\n\n style[key] = defaultOverride != null ? defaultOverride : style[key];\n }\n\n if (geomType === 'point' && layer.style.point) {\n var pointOverride = _this.getFeatureStyleProp(layer.style.point[key], feature);\n\n style[key] = pointOverride != null ? pointOverride : style[key];\n } else if (geomType === 'linestring' && layer.style.line) {\n var lineOverride = _this.getFeatureStyleProp(layer.style.line[key], feature);\n\n style[key] = lineOverride != null ? lineOverride : style[key];\n } else if (geomType === 'polygon' && layer.style.polygon) {\n var polygonOverride = _this.getFeatureStyleProp(layer.style.polygon[key], feature);\n\n style[key] = polygonOverride != null ? polygonOverride : style[key];\n }\n\n if (layer.style.byProp) {\n for (var propPath in layer.style.byProp) {\n var path = propPath.split(':')[0].split('=')[1];\n var value = propPath.split(':')[1];\n\n if (_utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getIn(feature.properties, path.split('.')) === value) {\n var propOverride = _this.getFeatureStyleProp(layer.style.byProp[propPath][key], feature);\n\n style[key] = propOverride != null ? propOverride : style[key];\n }\n }\n }\n\n if (layer.style.letPropertiesStyleOverride === true) {\n var styleOverride = _utils__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getIn((_a = feature.properties) === null || _a === void 0 ? void 0 : _a.style, key);\n style[key] = styleOverride != null ? styleOverride : style[key];\n }\n }\n }\n\n if (style.fillColor === 'none') style.fillColor = 'rgba(0,0,0,0)';\n var type = ((_b = feature.geometry) === null || _b === void 0 ? void 0 : _b.type) ? feature.geometry.type.toLowerCase() : '';\n\n if (feature._active) {\n if (_this.p.options.canBecomeActive !== false && layer.canBecomeActive !== false && (layer.style[type] == null || layer.style[type] && layer.style[type].canBecomeActive !== false)) style.fillColor = _this.p.options.activeColor || 'red';\n } else if (feature._highlighted) {\n if (_this.p.options.canBecomeHighlighted !== false && layer.canBecomeHighlighted !== false && (layer.style[type] == null || layer.style[type] && layer.style[type].canBecomeHighlighted !== false)) style.fillColor = _this.p.options.highlightColor || 'yellow';\n }\n\n if (isStrokeless === true) {\n style.color = style.fillColor;\n }\n\n return style;\n };\n\n this.p = parent;\n this.baseStyle = {\n fillColor: 'rgb(0,0,0)',\n fillOpacity: 0.4,\n color: 'rgb(255,255,255)',\n weight: 2,\n radius: 6\n };\n this._ = {\n layerers: {\n tile3d: new _tile3d__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this),\n tile: new _tile__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this),\n clamped: new _clamped__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this),\n vector: new _vector__WEBPACK_IMPORTED_MODULE_4__[\"default\"](this),\n model: new _model__WEBPACK_IMPORTED_MODULE_5__[\"default\"](this)\n }\n };\n\n this._reset();\n }\n\n Layers.prototype._reset = function () {\n this.tile3d = [];\n this.tile = [];\n this.clamped = [];\n this.vector = [];\n this.model = [];\n this.all = {\n tile3d: this.tile3d,\n tile: this.tile,\n clamped: this.clamped,\n vector: this.vector,\n model: this.model\n };\n };\n\n return Layers;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Layers);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/index.ts?"); + +/***/ }), + +/***/ "./src/layers/model.ts": +/*!*****************************!*\ + !*** ./src/layers/model.ts ***! + \*****************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var three_examples_jsm_loaders_OBJLoader_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! three/examples/jsm/loaders/OBJLoader.js */ \"./node_modules/three/examples/jsm/loaders/OBJLoader.js\");\n/* harmony import */ var three_examples_jsm_loaders_MTLLoader_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! three/examples/jsm/loaders/MTLLoader.js */ \"./node_modules/three/examples/jsm/loaders/MTLLoader.js\");\n/* harmony import */ var three_examples_jsm_loaders_ColladaLoader_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! three/examples/jsm/loaders/ColladaLoader.js */ \"./node_modules/three/examples/jsm/loaders/ColladaLoader.js\");\n/* harmony import */ var three_examples_jsm_loaders_GLTFLoader_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! three/examples/jsm/loaders/GLTFLoader.js */ \"./node_modules/three/examples/jsm/loaders/GLTFLoader.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\nvar __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {\n function adopt(value) {\n return value instanceof P ? value : new P(function (resolve) {\n resolve(value);\n });\n }\n\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) {\n try {\n step(generator.next(value));\n } catch (e) {\n reject(e);\n }\n }\n\n function rejected(value) {\n try {\n step(generator[\"throw\"](value));\n } catch (e) {\n reject(e);\n }\n }\n\n function step(result) {\n result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);\n }\n\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\nvar __generator = undefined && undefined.__generator || function (thisArg, body) {\n var _ = {\n label: 0,\n sent: function () {\n if (t[0] & 1) throw t[1];\n return t[1];\n },\n trys: [],\n ops: []\n },\n f,\n y,\n t,\n g;\n return g = {\n next: verb(0),\n \"throw\": verb(1),\n \"return\": verb(2)\n }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function () {\n return this;\n }), g;\n\n function verb(n) {\n return function (v) {\n return step([n, v]);\n };\n }\n\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n\n while (_) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n\n switch (op[0]) {\n case 0:\n case 1:\n t = op;\n break;\n\n case 4:\n _.label++;\n return {\n value: op[1],\n done: false\n };\n\n case 5:\n _.label++;\n y = op[1];\n op = [0];\n continue;\n\n case 7:\n op = _.ops.pop();\n\n _.trys.pop();\n\n continue;\n\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {\n _ = 0;\n continue;\n }\n\n if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {\n _.label = op[1];\n break;\n }\n\n if (op[0] === 6 && _.label < t[1]) {\n _.label = t[1];\n t = op;\n break;\n }\n\n if (t && _.label < t[2]) {\n _.label = t[2];\n\n _.ops.push(op);\n\n break;\n }\n\n if (t[2]) _.ops.pop();\n\n _.trys.pop();\n\n continue;\n }\n\n op = body.call(thisArg, _);\n } catch (e) {\n op = [6, e];\n y = 0;\n } finally {\n f = t = 0;\n }\n\n if (op[0] & 5) throw op[1];\n return {\n value: op[0] ? op[1] : void 0,\n done: true\n };\n }\n};\n\n\n\n\n\n\n\nvar objLoader = new three_examples_jsm_loaders_OBJLoader_js__WEBPACK_IMPORTED_MODULE_1__[\"OBJLoader\"]();\nvar mtlLoader = new three_examples_jsm_loaders_MTLLoader_js__WEBPACK_IMPORTED_MODULE_2__[\"MTLLoader\"]();\nvar colladaLoader = new three_examples_jsm_loaders_ColladaLoader_js__WEBPACK_IMPORTED_MODULE_3__[\"ColladaLoader\"]();\nvar gltfLoader = new three_examples_jsm_loaders_GLTFLoader_js__WEBPACK_IMPORTED_MODULE_4__[\"GLTFLoader\"]();\n\nvar ModelLayerer = function () {\n function ModelLayerer(parent) {\n var _this = this;\n\n this.add = function (layerObj, callback) {\n if (!_this.p.p._.wasInitialized) return;\n var alreadyExists = false;\n\n if (layerObj.hasOwnProperty('name') && layerObj.hasOwnProperty('on') && layerObj.hasOwnProperty('path')) {\n for (var i = 0; i < _this.p.model.length; i++) {\n if (_this.p.model[i].hasOwnProperty('name')) {\n if (_this.p.model[i].name == layerObj.name) {\n _this.p.model[i] = layerObj;\n alreadyExists = true;\n break;\n }\n }\n }\n\n if (!alreadyExists) {\n _this.generateModel(layerObj, function (model) {\n if (model) {\n model = _this.localizeModel(layerObj, model);\n\n _this.p.p.planet.add(model);\n\n layerObj.model = model;\n\n _this.p.model.push(layerObj);\n\n _this.p.model.sort(function (a, b) {\n return b.order - a.order;\n });\n\n _this.setOpacity(layerObj.name, layerObj.opacity);\n }\n\n if (typeof callback === 'function') callback();\n });\n } else if (typeof callback === 'function') callback();\n } else {\n console.warn(\"Attempted to add an invalid model layer: \" + layerObj.name + \". Required props: name, on, path\");\n }\n };\n\n this.toggle = function (name, on) {\n if (!_this.p.p._.wasInitialized) return false;\n\n _this.p.model.forEach(function (layer) {\n if (name === layer.name) {\n layer.on = on != null ? on : !layer.on;\n layer.model.visible = layer.on;\n return true;\n }\n });\n\n return false;\n };\n\n this.setOpacity = function (name, opacity) {\n if (!_this.p.p._.wasInitialized) return false;\n if (opacity == null) opacity = 1;\n\n for (var i = 0; i < _this.p.model.length; i++) {\n var layer = _this.p.model[i];\n\n if (name === layer.name) {\n layer.opacity = Math.max(Math.min(opacity, 1), 0);\n _utils__WEBPACK_IMPORTED_MODULE_5__[\"default\"].setAllMaterialOpacity(layer.model, layer.opacity);\n return true;\n }\n }\n\n return false;\n };\n\n this.remove = function (name) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.model.length; i++) {\n if (_this.p.model[i].name === name) {\n _this.p.p.planet.remove(_this.p.model[i].model);\n\n _this.p.model.splice(i, 1);\n\n return true;\n }\n }\n\n return false;\n };\n\n this.generateModel = function (layerObj, callback) {\n var modelType = _utils__WEBPACK_IMPORTED_MODULE_5__[\"default\"].getExtension(layerObj.path).toLowerCase();\n\n if (_this.modelCache[layerObj.path]) {\n callback(_this.modelCache[layerObj.path].clone());\n return;\n }\n\n var callback2 = function (model) {\n if (model && layerObj.cache !== false) {\n _this.modelCache[layerObj.path] = model.clone();\n }\n\n callback(model);\n };\n\n switch (modelType) {\n case 'obj':\n _this.objToModel(layerObj, callback2);\n\n break;\n\n case 'dae':\n _this.daeToModel(layerObj, callback2);\n\n break;\n\n case 'glb':\n case 'gltf':\n _this.gltfToModel(layerObj, callback2);\n\n break;\n\n default:\n console.warn(\"WARNING - Unsupported model file type: \" + modelType + \" in layer \" + layerObj.name + \". Must be one of: obj, dae, glb\");\n callback(false);\n }\n };\n\n this.objToModel = function (layerObj, callback) {\n return __awaiter(_this, void 0, void 0, function () {\n return __generator(this, function (_a) {\n if (layerObj.mtlPath) {\n mtlLoader.load(layerObj.mtlPath, function (materials) {\n var objMtlLoader = new three_examples_jsm_loaders_OBJLoader_js__WEBPACK_IMPORTED_MODULE_1__[\"OBJLoader\"]();\n objMtlLoader.setMaterials(materials);\n materials.preload();\n objMtlLoader.load(layerObj.path, function (mesh) {\n callback(mesh);\n }, function (xhr) {}, function (error) {\n console.warn('Failed to load .obj at: ' + layerObj.path);\n callback(false);\n });\n });\n } else {\n objLoader.load(layerObj.path, function (mesh) {\n callback(mesh);\n }, function (xhr) {}, function (error) {\n console.warn('Failed to load .obj at: ' + layerObj.path);\n callback(false);\n });\n }\n\n return [2];\n });\n });\n };\n\n this.daeToModel = function (layerObj, callback, options) {\n options = options || {};\n colladaLoader.load(layerObj.path, function (mesh) {\n callback(mesh.scene);\n }, function (xhr) {}, function (error) {\n console.warn('Failed to load .dae at: ' + layerObj.path);\n callback(false);\n });\n };\n\n this.gltfToModel = function (layerObj, callback) {\n return __awaiter(_this, void 0, void 0, function () {\n return __generator(this, function (_a) {\n gltfLoader.load(layerObj.path, function (mesh) {\n callback(mesh.scene);\n }, function (xhr) {}, function (error) {\n console.warn('Failed to load gltf at: ' + layerObj.path);\n callback(false);\n });\n return [2];\n });\n });\n };\n\n this.localizeModel = function (layerObj, model) {\n var parentMesh = new three__WEBPACK_IMPORTED_MODULE_0__[\"Object3D\"]();\n var position;\n var rotation;\n var scale;\n\n if (layerObj.isArrayed) {\n var models = [];\n\n var _loop_1 = function (i) {\n var modelC = model.clone();\n var lng = layerObj.position[i].longitude || layerObj.position[i].lng || 0;\n var lat = layerObj.position[i].latitude || layerObj.position[i].lat || 0;\n var elev = (layerObj.position[i].elevation || layerObj.position[i].elev || 0) * _this.p.p.options.exaggeration;\n\n var pos = _this.p.p.projection.lonLatToVector3(lng, lat, elev);\n\n modelC.position.set(pos.x, pos.y, pos.z);\n var quaternion = new three__WEBPACK_IMPORTED_MODULE_0__[\"Quaternion\"]();\n quaternion.setFromUnitVectors(new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](0, 1, 0), new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](pos.x, pos.y, pos.z).normalize());\n modelC.applyQuaternion(quaternion);\n modelC.rotateY(-lng * (Math.PI / 180));\n\n if (layerObj.rotation) {\n var rotation_1 = layerObj.rotation.length != null ? layerObj.rotation.length > i ? layerObj.rotation[i] : layerObj.rotation[layerObj.rotation.length - 1] : layerObj.rotation;\n var order = rotation_1.order || 'YXZ';\n\n if (order.length != 3) {\n console.warn(\"Lithosphere: Warning - Model Layer \\\"\" + layerObj.name + \"\\\" has an invalid rotation.order. Defaulting back to 'YXZ'\");\n order = 'YXZ';\n }\n\n modelC.rotation.order = order;\n order.split('').forEach(function (axis) {\n switch (axis) {\n case 'X':\n modelC.rotateX(rotation_1.x || 0);\n break;\n\n case 'Y':\n modelC.rotateY(-rotation_1.y || 0);\n break;\n\n case 'Z':\n modelC.rotateZ(rotation_1.z || 0);\n break;\n\n default:\n console.warn(\"Lithosphere: Warning - Model Layer \\\"\" + layerObj.name + \"\\\" has an invalid rotation.order axis: \" + axis + \". Must be one of X, Y, Z\");\n break;\n }\n });\n }\n\n if (layerObj.scale != null) {\n var s = layerObj.scale[i] || layerObj.scale || 1;\n modelC.scale.set(s || 1, s || 1, s || 1);\n }\n\n parentMesh.add(modelC);\n };\n\n for (var i = 0; i < layerObj.position.length; i++) {\n _loop_1(i);\n }\n } else {\n var lng = layerObj.position.longitude || layerObj.position.lng || 0;\n var lat = layerObj.position.latitude || layerObj.position.lat || 0;\n var elev = (layerObj.position.elevation || layerObj.position.elev || 0) * _this.p.p.options.exaggeration;\n\n var pos = _this.p.p.projection.lonLatToVector3(lng, lat, elev);\n\n model.position.set(pos.x, pos.y, pos.z);\n var quaternion = new three__WEBPACK_IMPORTED_MODULE_0__[\"Quaternion\"]();\n quaternion.setFromUnitVectors(new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](0, 1, 0), new three__WEBPACK_IMPORTED_MODULE_0__[\"Vector3\"](pos.x, pos.y, pos.z).normalize());\n model.applyQuaternion(quaternion);\n model.rotateY(-lng * (Math.PI / 180));\n\n if (layerObj.rotation) {\n var order = layerObj.rotation.order || 'YXZ';\n\n if (order.length != 3) {\n console.warn(\"Lithosphere: Warning - Model Layer \\\"\" + layerObj.name + \"\\\" has an invalid rotation.order. Defaulting back to 'YXZ'\");\n order = 'YXZ';\n }\n\n model.rotation.order = order;\n order.split('').forEach(function (axis) {\n switch (axis) {\n case 'X':\n model.rotateX(layerObj.rotation.x || 0);\n break;\n\n case 'Y':\n model.rotateY(-layerObj.rotation.y || 0);\n break;\n\n case 'Z':\n model.rotateZ(layerObj.rotation.z || 0);\n break;\n\n default:\n console.warn(\"Lithosphere: Warning - Model Layer \\\"\" + layerObj.name + \"\\\" has an invalid rotation.order axis: \" + axis + \". Must be one of X, Y, Z\");\n break;\n }\n });\n }\n\n if (layerObj.scale != null) {\n var s = layerObj.scale;\n model.scale.set(s || 1, s || 1, s || 1);\n }\n\n parentMesh.add(model);\n }\n\n if (layerObj.on == false) {\n parentMesh.visible = false;\n }\n\n return parentMesh;\n };\n\n this.p = parent;\n this.modelCache = {};\n }\n\n return ModelLayerer;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ModelLayerer);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/model.ts?"); /***/ }), @@ -1996,7 +2056,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _uti /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\nvar TileLayerer = function () {\n function TileLayerer(parent) {\n var _this = this;\n\n this.add = function (layerObj) {\n if (!_this.p.p._.wasInitialized) return;\n\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n var alreadyExists = false;\n\n if (layerObj.hasOwnProperty('name') && layerObj.hasOwnProperty('on') && layerObj.hasOwnProperty('path') && layerObj.hasOwnProperty('opacity') && layerObj.hasOwnProperty('minZoom') && layerObj.hasOwnProperty('maxZoom')) {\n for (var i = 0; i < _this.p.tile.length; i++) {\n if (_this.p.tile[i].hasOwnProperty('name')) {\n if (_this.p.tile[i].name == layerObj.name) {\n _this.p.tile[i] = layerObj;\n alreadyExists = true;\n break;\n }\n }\n }\n\n if (!alreadyExists) {\n _this.p.tile.push(layerObj);\n\n _this.p.tile.sort(function (a, b) {\n return a.order - b.order;\n });\n }\n\n if (_this.p.p.zoom >= layerObj.minZoom && _this.p.p.zoom <= layerObj.maxZoom) {\n _this.p.p._.tiledWorld.removeAllTiles();\n }\n\n _this.p.p._.maxZoom = _this.p.findHighestMaxZoom();\n _this.p.p._.minNativeZoom = _this.p.findLowestMinZoom();\n } else {\n console.warn('Attempted to add an invalid tile layer.');\n }\n };\n\n this.toggle = function (name, on) {\n if (!_this.p.p._.wasInitialized) return false;\n var foundMatch = false;\n\n _this.p.tile.forEach(function (t) {\n if (name === t.name) {\n t.on = on != null ? on : !t.on;\n foundMatch = true;\n }\n });\n\n if (foundMatch) {\n _this.p.p._.tiledWorld.outdateAllTiles();\n\n _this.p.p._.maxZoom = _this.p.findHighestMaxZoom();\n _this.p.p._.minNativeZoom = _this.p.findLowestMinZoom();\n return true;\n }\n\n return false;\n };\n\n this.setOpacity = function (name, opacity) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.tile.length; i++) {\n if (_this.p.tile[i].hasOwnProperty('name')) {\n if (_this.p.tile[i].name == name) {\n _this.p.tile[i].opacity = opacity;\n return true;\n }\n }\n }\n\n return false;\n };\n\n this.remove = function (name) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.tile.length; i++) {\n if (_this.p.tile[i].hasOwnProperty('name')) {\n if (_this.p.tile[i].name == name) {\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n if (_this.p.p.zoom >= _this.p.tile[i].minZoom && _this.p.p.zoom <= _this.p.tile[i].maxZoom) {\n var startingLength = _this.p.p._.tiledWorld.tilesDrawn.length;\n\n for (var j = 0; j < startingLength; j++) {\n _this.p.p._.tiledWorld.removeTile(0);\n }\n }\n\n _this.p.tile.splice(i, 1);\n\n _this.p.p._.maxZoom = _this.p.findHighestMaxZoom();\n _this.p.p._.minNativeZoom = _this.p.findLowestMinZoom();\n return true;\n }\n }\n }\n\n return false;\n };\n\n this.p = parent;\n }\n\n return TileLayerer;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (TileLayerer);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/tile.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\nvar TileLayerer = function () {\n function TileLayerer(parent) {\n var _this = this;\n\n this.add = function (layerObj) {\n if (!_this.p.p._.wasInitialized) return;\n\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n var alreadyExists = false;\n\n if (layerObj.hasOwnProperty('name') && layerObj.hasOwnProperty('on') && layerObj.hasOwnProperty('path') && layerObj.hasOwnProperty('opacity') && layerObj.hasOwnProperty('minZoom') && layerObj.hasOwnProperty('maxZoom')) {\n for (var i = 0; i < _this.p.tile.length; i++) {\n if (_this.p.tile[i].hasOwnProperty('name')) {\n if (_this.p.tile[i].name == layerObj.name) {\n _this.p.tile[i] = layerObj;\n alreadyExists = true;\n break;\n }\n }\n }\n\n if (!alreadyExists) {\n _this.p.tile.push(layerObj);\n\n _this.p.tile.sort(function (a, b) {\n return a.order - b.order;\n });\n }\n\n if (_this.p.p.zoom >= layerObj.minZoom && _this.p.p.zoom <= layerObj.maxZoom) {\n _this.p.p._.tiledWorld.removeAllTiles();\n }\n\n _this.p.p._.maxZoom = _this.p.findHighestMaxZoom();\n _this.p.p._.minNativeZoom = _this.p.findLowestMinZoom();\n } else {\n console.warn('Attempted to add an invalid tile layer.');\n }\n };\n\n this.toggle = function (name, on) {\n if (!_this.p.p._.wasInitialized) return false;\n var foundMatch = false;\n\n _this.p.tile.forEach(function (t) {\n if (name === t.name) {\n t.on = on != null ? on : !t.on;\n foundMatch = true;\n }\n });\n\n if (foundMatch) {\n _this.p.p._.tiledWorld.outdateAllTiles();\n\n _this.p.p._.maxZoom = _this.p.findHighestMaxZoom();\n _this.p.p._.minNativeZoom = _this.p.findLowestMinZoom();\n return true;\n }\n\n return false;\n };\n\n this.setOpacity = function (name, opacity) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.tile.length; i++) {\n if (_this.p.tile[i].hasOwnProperty('name')) {\n if (_this.p.tile[i].name == name) {\n _this.p.tile[i].opacity = opacity;\n return true;\n }\n }\n }\n\n return false;\n };\n\n this.setFilterEffect = function (name, filter, value) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.tile.length; i++) {\n if (_this.p.tile[i].hasOwnProperty('name')) {\n _this.p.tile[i].filters = _this.p.tile[i].filters || {};\n\n if (_this.p.tile[i].name == name) {\n _this.p.tile[i].filters[filter] = value;\n return true;\n }\n }\n }\n\n return false;\n };\n\n this.remove = function (name) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.tile.length; i++) {\n if (_this.p.tile[i].hasOwnProperty('name')) {\n if (_this.p.tile[i].name == name) {\n _this.p.p._.tiledWorld.killDrawingTiles();\n\n if (_this.p.p.zoom >= _this.p.tile[i].minZoom && _this.p.p.zoom <= _this.p.tile[i].maxZoom) {\n var startingLength = _this.p.p._.tiledWorld.tilesDrawn.length;\n\n for (var j = 0; j < startingLength; j++) {\n _this.p.p._.tiledWorld.removeTile(0);\n }\n }\n\n _this.p.tile.splice(i, 1);\n\n _this.p.p._.maxZoom = _this.p.findHighestMaxZoom();\n _this.p.p._.minNativeZoom = _this.p.findLowestMinZoom();\n return true;\n }\n }\n }\n\n return false;\n };\n\n this.p = parent;\n }\n\n return TileLayerer;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (TileLayerer);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/tile.ts?"); /***/ }), @@ -2008,7 +2068,7 @@ eval("__webpack_require__.r(__webpack_exports__);\nvar TileLayerer = function () /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _3d_tiles_renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! 3d-tiles-renderer */ \"./node_modules/3d-tiles-renderer/src/index.js\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./src/utils/index.ts\");\n\n\n\n\nvar Tile3dLayerer = function () {\n function Tile3dLayerer(parent) {\n var _this = this;\n\n this.add = function (layerObj) {\n if (!_this.p.p._.wasInitialized) return;\n\n if (layerObj.hasOwnProperty('name') && layerObj.hasOwnProperty('on') && layerObj.hasOwnProperty('path') && layerObj.hasOwnProperty('opacity') && layerObj.hasOwnProperty('minZoom') && layerObj.hasOwnProperty('maxZoom')) {\n var alreadyExists = false;\n\n for (var i = 0; i < _this.p.tile3d.length; i++) {\n if (_this.p.tile3d[i].hasOwnProperty('name')) {\n if (_this.p.tile3d[i].name == layerObj.name) {\n _this.p.tile3d[i] = layerObj;\n alreadyExists = true;\n break;\n }\n }\n }\n\n if (!alreadyExists) {\n var tilesRenderer = _this.generateTile3ds(layerObj);\n\n var meshes = tilesRenderer.group;\n var tile3dLayer = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n tile3dLayer.material = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n transparent: true,\n opacity: 0.5,\n color: 0xaaaaaa\n });\n tile3dLayer.add(meshes);\n\n _this.p.p.planet.add(tile3dLayer);\n\n _this.localizeTile3ds(layerObj, tilesRenderer);\n\n layerObj.meshes = meshes;\n layerObj.renderer = tilesRenderer;\n layerObj.tile3dLayer = tile3dLayer;\n\n _this.p.tile3d.push(layerObj);\n\n _this.p.tile3d.sort(function (a, b) {\n return b.order - a.order;\n });\n }\n } else {\n console.warn(\"Attempted to add an invalid tile3d layer: \" + layerObj.name);\n }\n };\n\n this.toggle = function (name, on) {\n if (!_this.p.p._.wasInitialized) return false;\n\n _this.p.vector.forEach(function (layer) {\n if (name === layer.name) {\n layer.on = on != null ? on : !layer.on;\n layer.meshes.visible = layer.on;\n\n _this.p.p._.events._attenuate();\n\n return true;\n }\n });\n\n return false;\n };\n\n this.setOpacity = function (name, opacity) {\n if (!_this.p.p._.wasInitialized) return false;\n opacity = Math.max(Math.min(opacity, 1), 0);\n\n _this.p.tile3d.forEach(function (layer) {\n if (name === layer.name) {\n layer.opacity = Math.max(Math.min(opacity, 1), 0);\n layer.meshes.children.forEach(function (mesh) {\n mesh.material.opacity = layer.opacity;\n });\n return true;\n }\n });\n\n return false;\n };\n\n this.remove = function (name) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.tile3d.length; i++) {\n if (_this.p.tile3d[i].name === name) {\n _this.p.p.planet.remove(_this.p.tile3d[i].tile3dLayer);\n\n _this.p.tile3d.splice(i, 1);\n\n return true;\n }\n }\n\n return false;\n };\n\n this.generateTile3ds = function (layerObj) {\n var tilesRenderer = new _3d_tiles_renderer__WEBPACK_IMPORTED_MODULE_0__[\"TilesRenderer\"](layerObj.path);\n tilesRenderer.setCamera(_this.p.p._.cameras.camera);\n tilesRenderer.setResolutionFromRenderer(_this.p.p._.cameras.camera, _this.p.p._.renderer);\n return tilesRenderer;\n };\n\n this.localizeTile3ds = function (layerObj, tilesRenderer) {\n var v = _this.p.p.projection.lonLatToVector3(layerObj.position.longitude || layerObj.position.lng || 0, layerObj.position.latitude || layerObj.position.lat || 0, (layerObj.position.elevation || layerObj.position.elev || 0) * _this.p.p.options.exaggeration);\n\n tilesRenderer.group.position.set(v.x, v.y, v.z);\n var scale = layerObj.scale;\n if (scale == null) scale = 1;\n tilesRenderer.group.scale.set(scale, scale, scale);\n var rotation = layerObj.rotation || {};\n rotation.x = rotation.x || 0;\n var order = rotation.order || 'XYZ';\n\n if (order.length != 3) {\n console.warn(\"Lithosphere: Warning - Tile3d Layer \\\"\" + layerObj.name + \"\\\" has an invalid rotation.order. Defaulting back to 'XYZ'\");\n order = 'XYZ';\n }\n\n tilesRenderer.group.rotation.order = order;\n order = order.toLowerCase();\n\n for (var _i = 0, _a = order.split(''); _i < _a.length; _i++) {\n var a = _a[_i];\n\n switch (a) {\n case 'x':\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].rotateAroundArbAxis(tilesRenderer.group, new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](1, 0, 0), rotation.x || 0);\n break;\n\n case 'y':\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].rotateAroundArbAxis(tilesRenderer.group, new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 1, 0), rotation.y || 0);\n break;\n\n case 'z':\n _utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].rotateAroundArbAxis(tilesRenderer.group, new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, 1), rotation.z || 0);\n break;\n\n default:\n console.warn(\"Lithosphere: Warning - Tile3d Layer \\\"\" + layerObj.name + \"\\\" has an unknown rotation.order axis: \" + a);\n break;\n }\n }\n };\n\n this.p = parent;\n }\n\n return Tile3dLayerer;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Tile3dLayerer);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/tile3d.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _3d_tiles_renderer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! 3d-tiles-renderer */ \"./node_modules/3d-tiles-renderer/src/index.js\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n\n\n\nvar Tile3dLayerer = function () {\n function Tile3dLayerer(parent) {\n var _this = this;\n\n this.add = function (layerObj) {\n if (!_this.p.p._.wasInitialized) return;\n\n if (layerObj.hasOwnProperty('name') && layerObj.hasOwnProperty('on') && layerObj.hasOwnProperty('path') && layerObj.hasOwnProperty('opacity') && layerObj.hasOwnProperty('minZoom') && layerObj.hasOwnProperty('maxZoom')) {\n var alreadyExists = false;\n\n for (var i = 0; i < _this.p.tile3d.length; i++) {\n if (_this.p.tile3d[i].hasOwnProperty('name')) {\n if (_this.p.tile3d[i].name == layerObj.name) {\n _this.p.tile3d[i] = layerObj;\n alreadyExists = true;\n break;\n }\n }\n }\n\n if (!alreadyExists) {\n var tilesRenderer = _this.generateTile3ds(layerObj);\n\n var tile3dLayer = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n tile3dLayer.material = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n transparent: true,\n opacity: 0.5,\n color: 0xaaaaaa\n });\n\n _this.p.p.planet.add(tile3dLayer);\n\n var model = _this.localizeTile3ds(layerObj, tilesRenderer);\n\n tile3dLayer.add(model);\n layerObj.meshes = model;\n layerObj.renderer = tilesRenderer;\n layerObj.tile3dLayer = tile3dLayer;\n\n _this.p.tile3d.push(layerObj);\n\n _this.p.tile3d.sort(function (a, b) {\n return b.order - a.order;\n });\n }\n } else {\n console.warn(\"Attempted to add an invalid tile3d layer: \" + layerObj.name);\n }\n };\n\n this.toggle = function (name, on) {\n if (!_this.p.p._.wasInitialized) return false;\n\n _this.p.vector.forEach(function (layer) {\n if (name === layer.name) {\n layer.on = on != null ? on : !layer.on;\n layer.meshes.visible = layer.on;\n\n _this.p.p._.events._attenuate();\n\n return true;\n }\n });\n\n return false;\n };\n\n this.setOpacity = function (name, opacity) {\n if (!_this.p.p._.wasInitialized) return false;\n opacity = Math.max(Math.min(opacity, 1), 0);\n\n _this.p.tile3d.forEach(function (layer) {\n if (name === layer.name) {\n layer.opacity = Math.max(Math.min(opacity, 1), 0);\n layer.meshes.children.forEach(function (mesh) {\n mesh.material.opacity = layer.opacity;\n });\n return true;\n }\n });\n\n return false;\n };\n\n this.remove = function (name) {\n if (!_this.p.p._.wasInitialized) return false;\n\n for (var i = 0; i < _this.p.tile3d.length; i++) {\n if (_this.p.tile3d[i].name === name) {\n _this.p.p.planet.remove(_this.p.tile3d[i].tile3dLayer);\n\n _this.p.tile3d.splice(i, 1);\n\n return true;\n }\n }\n\n return false;\n };\n\n this.generateTile3ds = function (layerObj) {\n var tilesRenderer = new _3d_tiles_renderer__WEBPACK_IMPORTED_MODULE_0__[\"TilesRenderer\"](layerObj.path);\n tilesRenderer.setCamera(_this.p.p._.cameras.camera);\n tilesRenderer.setResolutionFromRenderer(_this.p.p._.cameras.camera, _this.p.p._.renderer);\n return tilesRenderer;\n };\n\n this.localizeTile3ds = function (layerObj, tilesRenderer) {\n var parentMesh = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n var lng = layerObj.position.longitude || layerObj.position.lng || 0;\n var lat = layerObj.position.latitude || layerObj.position.lat || 0;\n var elev = (layerObj.position.elevation || layerObj.position.elev || 0) * _this.p.p.options.exaggeration;\n\n var pos = _this.p.p.projection.lonLatToVector3(lng, lat, elev);\n\n tilesRenderer.group.position.set(pos.x, pos.y, pos.z);\n var quaternion = new three__WEBPACK_IMPORTED_MODULE_1__[\"Quaternion\"]();\n quaternion.setFromUnitVectors(new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 1, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](pos.x, pos.y, pos.z).normalize());\n tilesRenderer.group.applyQuaternion(quaternion);\n tilesRenderer.group.rotateY(-lng * (Math.PI / 180));\n\n if (layerObj.rotation) {\n var order = layerObj.rotation.order || 'YXZ';\n\n if (order.length != 3) {\n console.warn(\"Lithosphere: Warning - Model Layer \\\"\" + layerObj.name + \"\\\" has an invalid rotation.order. Defaulting back to 'YXZ'\");\n order = 'YXZ';\n }\n\n tilesRenderer.group.rotation.order = order;\n order.split('').forEach(function (axis) {\n switch (axis) {\n case 'X':\n tilesRenderer.group.rotateX(layerObj.rotation.x || 0);\n break;\n\n case 'Y':\n tilesRenderer.group.rotateY(layerObj.rotation.y || 0);\n break;\n\n case 'Z':\n tilesRenderer.group.rotateZ(layerObj.rotation.z || 0);\n break;\n\n default:\n console.warn(\"Lithosphere: Warning - Model Layer \\\"\" + layerObj.name + \"\\\" has an invalid rotation.order axis: \" + axis + \". Must be one of X, Y, Z\");\n break;\n }\n });\n }\n\n if (layerObj.scale != null) {\n var s = layerObj.scale;\n tilesRenderer.group.scale.set(s || 1, s || 1, s || 1);\n }\n\n if (layerObj.on == false) {\n tilesRenderer.group.visible = false;\n }\n\n parentMesh.add(tilesRenderer.group);\n return parentMesh;\n };\n\n this.p = parent;\n }\n\n return Tile3dLayerer;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Tile3dLayerer);\n\n//# sourceURL=webpack://LithoSphere/./src/layers/tile3d.ts?"); /***/ }), @@ -2032,7 +2092,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var thre /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ \"./src/core/index.ts\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _layers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./layers */ \"./src/layers/index.ts\");\n/* harmony import */ var _controls__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./controls */ \"./src/controls/index.ts\");\n/* harmony import */ var _secondary_loadingScreen__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./secondary/loadingScreen */ \"./src/secondary/loadingScreen.ts\");\nvar __assign = undefined && undefined.__assign || function () {\n __assign = Object.assign || function (t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n\n return t;\n };\n\n return __assign.apply(this, arguments);\n};\n\n\n\n\n\n\n\nvar LithoSphere = function () {\n function LithoSphere(containerId, options) {\n var _this = this;\n\n this._animate = function () {\n window.requestAnimationFrame(_this._animate);\n\n _this._render();\n };\n\n this._onFirstLoad = function () {\n _this._.firstLoad = true;\n\n _this._.events._rotateGlobe({\n pageX: 0,\n pageY: 0\n }, {\n x: 0.0001,\n y: 0.0001\n });\n\n setTimeout(function () {\n _this.setCenter(_this.options.initialView, false, true);\n\n _this._.events._onZoom();\n\n _this._.loadingScreen.end();\n }, 100);\n };\n\n this.setCenter = function (latLngZoom, ignoreZoom, accountForHeight) {\n if (!_this._.wasInitialized) return false;\n var rotLat = (90 - (latLngZoom.lat || 0)) * (Math.PI / 180);\n var rotLng = (latLngZoom.lng || 0) * (Math.PI / 180);\n\n _this.planet.rotation.set(rotLat, rotLng, 0);\n\n _this._.events._matchPlanetsLODToPlanet();\n\n if (latLngZoom.zoom != null && ignoreZoom != true) {\n _this.zoom = latLngZoom.zoom;\n\n var center = _this.getCenter(true);\n\n _this._.cameras.orbit.camera.position.y = -(40000000 / _this.projection.radiusScale / Math.pow(2, _this.zoom));\n if (accountForHeight) _this._.cameras.orbit.camera.position.y -= center.height;\n _this._.cameras.firstPerson.controls.getObject().position.y = -(40000000 / _this.projection.radiusScale / Math.pow(2, _this.zoom));\n if (accountForHeight) _this._.cameras.firstPerson.controls.getObject().position.y -= center.height;\n }\n\n _this._.events._refreshFrontGroupRotation();\n\n return true;\n };\n\n this.getCenterXYZ = function (raycasted) {\n if (raycasted) {\n _this._.raycaster.set(new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, _this.planetCenter.y, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 1, 0));\n\n var planeArr = [];\n\n for (var i = 0; i < _this._.tiledWorld.tilesDrawn.length; i++) {\n if (!_this._.tiledWorld.tilesDrawn[i].isLODTile) planeArr.push(_this._.tiledWorld.tilesDrawn[i].t);\n }\n\n var intersects = _this._.raycaster.intersectObjects(planeArr);\n\n if (intersects.length > 0) {\n intersects[0].point.y += _this.planetCenter.y;\n return intersects[0].point;\n }\n\n return new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, 0);\n } else {\n var centerPoint = {\n x: _this.planetCenter.x,\n y: _this.planetCenter.y,\n z: _this.planetCenter.z\n };\n centerPoint = _this.projection.rotatePoint3D(centerPoint, {\n x: -_this.planet.rotation.x,\n y: 0,\n z: 0\n });\n centerPoint = _this.projection.rotatePoint3D(centerPoint, {\n x: 0,\n y: -_this.planet.rotation.y,\n z: 0\n });\n centerPoint = _this.projection.rotatePoint3D(centerPoint, {\n x: 0,\n y: 0,\n z: -_this.planet.rotation.z\n });\n return new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](centerPoint.x, centerPoint.y, centerPoint.z);\n }\n };\n\n this.getCenter = function (raycasted) {\n var centerXYZ = _this.getCenterXYZ(raycasted);\n\n if (raycasted) {\n var center = JSON.parse(JSON.stringify(centerXYZ));\n center = _this.projection.rotatePoint3D(center, {\n x: -_this.planet.rotation.x,\n y: 0,\n z: 0\n });\n center = _this.projection.rotatePoint3D(center, {\n x: 0,\n y: -_this.planet.rotation.y,\n z: 0\n });\n center = _this.projection.rotatePoint3D(center, {\n x: 0,\n y: 0,\n z: -_this.planet.rotation.z\n });\n center = _this.projection.vector3ToLatLng(center);\n center.height = centerXYZ.length() * _this.projection.radiusScale - _this.projection.radii.major;\n return center;\n }\n\n return _this.projection.vector3ToLatLng(centerXYZ);\n };\n\n this.getCenterElevation = function () {\n return _this.getCenterXYZ(true).length() * _this.projection.radiusScale - _this.projection.radii.major;\n };\n\n this.getCenterElevationRaw = function () {\n var elev = _this.getCenterXYZ(true).length();\n\n if (elev <= 0.1 && elev >= -0.1) return;\n return elev;\n };\n\n this.getElevationAtLngLat = function (lng, lat) {\n var v = _this.projection.lonLatToVector3(lng, lat, 100000 * _this.options.exaggeration);\n\n var tempObj = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n tempObj.position.set(0, -_this.planetCenter.y, 0);\n tempObj.rotation.set(_this.planet.rotation.x, _this.planet.rotation.y, _this.planet.rotation.z);\n var geometry = new three__WEBPACK_IMPORTED_MODULE_1__[\"SphereBufferGeometry\"](200, 32, 32);\n var material = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n color: 0xffff00\n });\n var tempObj2 = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](geometry, material);\n tempObj2.position.set(v.x, v.y, v.z);\n tempObj.add(tempObj2);\n tempObj.updateMatrixWorld();\n var vector = new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"]();\n vector.setFromMatrixPosition(tempObj2.matrixWorld);\n\n _this._.raycaster.set(vector, new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, -_this.planetCenter.y, 0).normalize());\n\n var planeArr = [];\n\n for (var i = 0; i < _this._.tiledWorld.tilesDrawn.length; i++) {\n if (!_this._.tiledWorld.tilesDrawn[i].isLODTile) planeArr.push(_this._.tiledWorld.tilesDrawn[i].t);\n }\n\n var intersects = _this._.raycaster.intersectObjects(planeArr);\n\n if (intersects.length > 0) {\n intersects[intersects.length - 1].point.y += _this.planetCenter.y;\n return intersects[intersects.length - 1].point.length() * _this.projection.radiusScale - _this.projection.radii.major;\n }\n\n return 0;\n };\n\n this.getCenterTile = function () {\n var centerll = _this.getCenter();\n\n return _this.projection.latLngZ2TileXYZ(centerll.lat, centerll.lng, _this.zoom);\n };\n\n this.getCameras = function () {\n return {\n camera: _this._.cameras.camera,\n isFirstPerson: _this._.cameras.isFirstPerson,\n firstPerson: _this._.cameras.firstPerson,\n orbit: _this._.cameras.orbit\n };\n };\n\n this.getContainer = function () {\n return _this._.container;\n };\n\n this.invalidateSize = function () {\n if (_this._.wasInitialized) {\n _this._.renderer.setSize(_this._.sceneContainer.offsetWidth, _this._.sceneContainer.offsetHeight);\n\n _this._.cameras.updateSize();\n }\n };\n\n var sceneContainer = document.getElementById(containerId).appendChild(document.createElement('div'));\n sceneContainer.id = '_lithosphere_scene';\n sceneContainer.style.width = '100%';\n sceneContainer.style.height = '100%';\n this._ = {\n containerId: containerId,\n container: document.getElementById(containerId),\n sceneContainer: sceneContainer,\n wasInitialized: false,\n renderer: null,\n cameras: null,\n cameraPositionTarget: null,\n tiledWorld: null,\n events: null,\n maxZoom: 0,\n minNativeZoom: 0,\n loader: new three__WEBPACK_IMPORTED_MODULE_1__[\"TextureLoader\"](),\n raycaster: new three__WEBPACK_IMPORTED_MODULE_1__[\"Raycaster\"](),\n updateEveryNthRender: 2,\n counters: {\n update: 0,\n frame: 0\n },\n lastCameraWasFirst: false,\n firstUpdate: true,\n firstLoad: false,\n loadingScreen: null,\n renderOnlyWhenOpen: true,\n zCutOff: 3,\n firstViewOverride: null,\n mouseIsInScene: false,\n marsRadius: 3396190\n };\n this._.container.style.position = 'relative';\n this.scene = new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]();\n this.scenesLOD = [new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]()];\n this.sceneBack = new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]();\n this.sceneFront = new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]();\n this.planet = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n this.planetsLOD = [new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]()];\n this.frontGroup = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n var defaultOptions = {\n loadingScreen: true,\n tileMapResource: null,\n customParsers: {},\n radiusOfTiles: 4,\n useLOD: true,\n LOD: [{\n radiusOfTiles: 4,\n zoomsUp: 3\n }, {\n radiusOfTiles: 2,\n zoomsUp: 7\n }, {\n radiusOfTiles: 2,\n zoomsUp: 11\n }],\n tileResolution: 32,\n trueTileResolution: 256,\n showAxes: false,\n wireframeMode: false,\n exaggeration: 1,\n renderOnlyWhenOpen: true,\n targetYOffset: 0,\n highlightColor: 'yellow',\n activeColor: 'red'\n };\n options = options || {};\n this.options = __assign(__assign({}, defaultOptions), options);\n\n this._init();\n }\n\n LithoSphere.prototype._init = function () {\n this._.renderer = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Renderer\"](this._.sceneContainer).renderer;\n\n if (this._.renderer) {\n this._.wasInitialized = true;\n } else return false;\n\n this.projection = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Projection\"](this.options.majorRadius, this.options.minorRadius, this.options.tileMapResource, this.options.trueTileResolution);\n this._.cameras = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Cameras\"](this._.container, this._.sceneContainer, this.scene, this.projection);\n this.layers = new _layers__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this);\n this.addLayer = this.layers.addLayer;\n this.removeLayer = this.layers.removeLayer;\n this.toggleLayer = this.layers.toggleLayer;\n this.setLayerOpacity = this.layers.setLayerOpacity;\n this._.tiledWorld = new _core__WEBPACK_IMPORTED_MODULE_0__[\"TiledWorld\"](this);\n this.zoom = 10;\n this.trueZoom = this.zoom;\n this.mouse = {\n lat: null,\n lng: null,\n elev: null\n };\n this.planetCenter = new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, -(this.projection.radii.major / this.projection.radiusScale), 0);\n this.planet.position.set(this.planetCenter.x, -this.planetCenter.y, this.planetCenter.z);\n this.scene.add(this.planet);\n this.scenesLOD[0].add(this.planetsLOD[0]);\n this.scenesLOD[1].add(this.planetsLOD[1]);\n this.scenesLOD[2].add(this.planetsLOD[2]);\n this.frontGroup.position.set(this.planetCenter.x, -this.planetCenter.y, this.planetCenter.z);\n this.sceneFront.add(this.frontGroup);\n this.scene.add(new three__WEBPACK_IMPORTED_MODULE_1__[\"AmbientLight\"](0xfefefe));\n\n if (this.options.starsphere) {\n var starsphereGeometry = new three__WEBPACK_IMPORTED_MODULE_1__[\"SphereBufferGeometry\"](this.planetCenter.y * 1000, 64, 64);\n var starsphereMaterial = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n color: this.options.starsphere.color || 0xaaaaaa\n });\n if (this.options.starsphere.url) starsphereMaterial.map = this._.loader.load(this.options.starsphere.url);\n starsphereMaterial.opacity = 1;\n this.starsphere = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](starsphereGeometry, starsphereMaterial);\n this.sceneBack.add(this.starsphere);\n }\n\n if (this.options.atmosphere) {\n this.atmosphere = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](new three__WEBPACK_IMPORTED_MODULE_1__[\"SphereBufferGeometry\"](this.planetCenter.y * 1.5, 128, 128), _core__WEBPACK_IMPORTED_MODULE_0__[\"Shaders\"].atmosphere(this.options.atmosphere.color));\n this.sceneBack.add(this.atmosphere);\n }\n\n if (this.options.showAxes === true) {\n var materialx = new three__WEBPACK_IMPORTED_MODULE_1__[\"LineBasicMaterial\"]({\n color: 0xff0000\n });\n var geometryx = new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferGeometry\"]().setFromPoints([new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0 * 2, 0, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](this.planetCenter.y * 2, 0, 0)]);\n var linex = new three__WEBPACK_IMPORTED_MODULE_1__[\"Line\"](geometryx, materialx);\n this.scene.add(linex);\n var materialy = new three__WEBPACK_IMPORTED_MODULE_1__[\"LineBasicMaterial\"]({\n color: 0x00ff00\n });\n var geometryy = new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferGeometry\"]().setFromPoints([new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, this.planetCenter.y * 2, 0)]);\n var liney = new three__WEBPACK_IMPORTED_MODULE_1__[\"Line\"](geometryy, materialy);\n this.scene.add(liney);\n var materialz = new three__WEBPACK_IMPORTED_MODULE_1__[\"LineBasicMaterial\"]({\n color: 0x0000ff\n });\n var geometryz = new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferGeometry\"]().setFromPoints([new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, this.planetCenter.y * 2)]);\n var linez = new three__WEBPACK_IMPORTED_MODULE_1__[\"Line\"](geometryz, materialz);\n this.scene.add(linez);\n }\n\n this.controls = new _controls__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this);\n this.addControl = this.controls.addControl;\n this.removeControl = this.controls.removeControl;\n\n if (this.options.renderOnlyWhenOpen === false) {\n this._.renderOnlyWhenOpen = false;\n }\n\n this._.loadingScreen = new _secondary_loadingScreen__WEBPACK_IMPORTED_MODULE_4__[\"default\"](this);\n this._.events = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Events\"](this);\n this.setCenter(this.options.initialView);\n\n this._animate();\n\n return true;\n };\n\n LithoSphere.prototype._render = function () {\n this._.renderer.clear();\n\n if (this._.renderOnlyWhenOpen) {\n var containerRect = this._.container.getBoundingClientRect();\n\n if (containerRect.width <= 0 || containerRect.height <= 0) return;\n }\n\n this._.counters.update = (this._.counters.update + 1) % this._.updateEveryNthRender;\n if (this._.counters.update === 0) this._update();else if (!this._.cameras.isFirstPerson) this._.cameras.orbit.controls.update();\n this.layers.tile3d.forEach(function (tile3d) {\n tile3d.renderer.update();\n });\n\n this._.renderer.render(this.sceneBack, this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scenesLOD[2], this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scenesLOD[1], this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scenesLOD[0], this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scene, this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.sceneFront, this._.cameras.camera);\n };\n\n LithoSphere.prototype._update = function () {\n if (!this._.wasInitialized) return;\n\n if (this._.renderOnlyWhenOpen) {\n var containerRect = this._.container.getBoundingClientRect();\n\n if (containerRect.width <= 0 || containerRect.height <= 0) return;\n }\n\n this._.counters.frame = (this._.counters.frame + 1) % 4;\n this.scene.rotation.x = 0;\n this.scene.position.y = 0;\n\n if (!this._.firstUpdate) {\n this._.tiledWorld.refreshTiles();\n }\n\n this._.events._checkDesiredZoom();\n\n this.controls._onUpdateEvent();\n\n if (this._.cameras.isFirstPerson) {\n this._.lastCameraWasFirst = true;\n this._.cameras.firstPerson.controls.getObject().position.y = this._.cameras.orbit.controls.target.y - this._.cameras.firstPerson.height / this.projection.radiusScale;\n\n var v2 = this._.cameras.update();\n\n this._.events._rotateGlobe(v2);\n\n this._.events._onMouseMove();\n\n this.controls._onFirstPersonUpdate();\n } else if (this._.lastCameraWasFirst) {\n this._.lastCameraWasFirst = false;\n\n this.controls._onOrbitalUpdate();\n }\n\n if (this._.firstUpdate) {\n if (this._.firstViewOverride != null) this.setCenter(this._.firstViewOverride);else this.setCenter(this.options.initialView, true);\n var o = this._.cameras.orbit;\n var cam = o.camera;\n var con = o.controls;\n var pos = cam.position;\n var tar = con.target;\n this._.cameraPositionTarget = [pos.x, pos.y, pos.z, tar.x, tar.y, tar.z];\n this._.firstUpdate = false;\n }\n };\n\n return LithoSphere;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (LithoSphere);\n\n//# sourceURL=webpack://LithoSphere/./src/lithosphere.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ \"./src/core/index.ts\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var _layers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./layers */ \"./src/layers/index.ts\");\n/* harmony import */ var _controls__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./controls */ \"./src/controls/index.ts\");\n/* harmony import */ var _secondary_loadingScreen__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./secondary/loadingScreen */ \"./src/secondary/loadingScreen.ts\");\nvar __assign = undefined && undefined.__assign || function () {\n __assign = Object.assign || function (t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n\n return t;\n };\n\n return __assign.apply(this, arguments);\n};\n\n\n\n\n\n\n\nvar LithoSphere = function () {\n function LithoSphere(containerId, options) {\n var _this = this;\n\n this._animate = function () {\n window.requestAnimationFrame(_this._animate);\n\n _this._render();\n };\n\n this._onFirstLoad = function () {\n _this._.firstLoad = true;\n\n _this._.events._rotateGlobe({\n pageX: 0,\n pageY: 0\n }, {\n x: 0.0001,\n y: 0.0001\n });\n\n _this._.rendererWrapper.updateSize();\n\n setTimeout(function () {\n _this.setCenter(_this.options.initialView, false, true);\n\n _this._.events._onZoom();\n\n _this._.loadingScreen.end();\n }, 100);\n };\n\n this.setCenter = function (latLngZoom, ignoreZoom, accountForHeight) {\n if (!_this._.wasInitialized) return false;\n var rotLat = (90 - (latLngZoom.lat || 0)) * (Math.PI / 180);\n var rotLng = (latLngZoom.lng || 0) * (Math.PI / 180);\n\n _this.planet.rotation.set(rotLat, rotLng, 0);\n\n _this._.events._matchPlanetsLODToPlanet();\n\n if (latLngZoom.zoom != null && ignoreZoom != true) {\n _this.zoom = latLngZoom.zoom;\n\n var center = _this.getCenter(true);\n\n _this._.cameras.orbit.camera.position.y = -(40000000 / _this.projection.radiusScale / Math.pow(2, _this.zoom));\n if (accountForHeight) _this._.cameras.orbit.camera.position.y -= center.height;\n _this._.cameras.firstPerson.controls.getObject().position.y = -(40000000 / _this.projection.radiusScale / Math.pow(2, _this.zoom));\n if (accountForHeight) _this._.cameras.firstPerson.controls.getObject().position.y -= center.height;\n }\n\n _this._.events._refreshFrontGroupRotation();\n\n return true;\n };\n\n this.getCenterXYZ = function (raycasted) {\n if (raycasted) {\n _this._.raycaster.set(new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, _this.planetCenter.y, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 1, 0));\n\n var planeArr = [];\n\n for (var i = 0; i < _this._.tiledWorld.tilesDrawn.length; i++) {\n if (!_this._.tiledWorld.tilesDrawn[i].isLODTile) planeArr.push(_this._.tiledWorld.tilesDrawn[i].t);\n }\n\n var intersects = _this._.raycaster.intersectObjects(planeArr);\n\n if (intersects.length > 0) {\n intersects[0].point.y += _this.planetCenter.y;\n return intersects[0].point;\n }\n\n return new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, 0);\n } else {\n var centerPoint = {\n x: _this.planetCenter.x,\n y: _this.planetCenter.y,\n z: _this.planetCenter.z\n };\n centerPoint = _this.projection.rotatePoint3D(centerPoint, {\n x: -_this.planet.rotation.x,\n y: 0,\n z: 0\n });\n centerPoint = _this.projection.rotatePoint3D(centerPoint, {\n x: 0,\n y: -_this.planet.rotation.y,\n z: 0\n });\n centerPoint = _this.projection.rotatePoint3D(centerPoint, {\n x: 0,\n y: 0,\n z: -_this.planet.rotation.z\n });\n return new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](centerPoint.x, centerPoint.y, centerPoint.z);\n }\n };\n\n this.getCenter = function (raycasted) {\n var centerXYZ = _this.getCenterXYZ(raycasted);\n\n if (raycasted) {\n var center = JSON.parse(JSON.stringify(centerXYZ));\n center = _this.projection.rotatePoint3D(center, {\n x: -_this.planet.rotation.x,\n y: 0,\n z: 0\n });\n center = _this.projection.rotatePoint3D(center, {\n x: 0,\n y: -_this.planet.rotation.y,\n z: 0\n });\n center = _this.projection.rotatePoint3D(center, {\n x: 0,\n y: 0,\n z: -_this.planet.rotation.z\n });\n center = _this.projection.vector3ToLatLng(center);\n center.height = centerXYZ.length() * _this.projection.radiusScale - _this.projection.radii.major;\n return center;\n }\n\n return _this.projection.vector3ToLatLng(centerXYZ);\n };\n\n this.getCenterElevation = function () {\n return _this.getCenterXYZ(true).length() * _this.projection.radiusScale - _this.projection.radii.major;\n };\n\n this.getCenterElevationRaw = function () {\n var elev = _this.getCenterXYZ(true).length();\n\n if (elev <= 0.1 && elev >= -0.1) return;\n return elev;\n };\n\n this.getElevationAtLngLat = function (lng, lat) {\n var v = _this.projection.lonLatToVector3(lng, lat, 100000 * _this.options.exaggeration);\n\n var tempObj = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n tempObj.position.set(0, -_this.planetCenter.y, 0);\n tempObj.rotation.set(_this.planet.rotation.x, _this.planet.rotation.y, _this.planet.rotation.z);\n var geometry = new three__WEBPACK_IMPORTED_MODULE_1__[\"SphereBufferGeometry\"](200, 32, 32);\n var material = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n color: 0xffff00\n });\n var tempObj2 = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](geometry, material);\n tempObj2.position.set(v.x, v.y, v.z);\n tempObj.add(tempObj2);\n tempObj.updateMatrixWorld();\n var vector = new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"]();\n vector.setFromMatrixPosition(tempObj2.matrixWorld);\n\n _this._.raycaster.set(vector, new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, -_this.planetCenter.y, 0).normalize());\n\n var planeArr = [];\n\n for (var i = 0; i < _this._.tiledWorld.tilesDrawn.length; i++) {\n if (!_this._.tiledWorld.tilesDrawn[i].isLODTile) planeArr.push(_this._.tiledWorld.tilesDrawn[i].t);\n }\n\n var intersects = _this._.raycaster.intersectObjects(planeArr);\n\n if (intersects.length > 0) {\n intersects[intersects.length - 1].point.y += _this.planetCenter.y;\n return intersects[intersects.length - 1].point.length() * _this.projection.radiusScale - _this.projection.radii.major;\n }\n\n return 0;\n };\n\n this.getCenterTile = function () {\n var centerll = _this.getCenter();\n\n return _this.projection.latLngZ2TileXYZ(centerll.lat, centerll.lng, _this.zoom);\n };\n\n this.getCameras = function () {\n return {\n camera: _this._.cameras.camera,\n isFirstPerson: _this._.cameras.isFirstPerson,\n firstPerson: _this._.cameras.firstPerson,\n orbit: _this._.cameras.orbit\n };\n };\n\n this.getContainer = function () {\n return _this._.container;\n };\n\n this.invalidateSize = function () {\n if (_this._.wasInitialized) {\n _this._.renderer.setSize(_this._.sceneContainer.offsetWidth, _this._.sceneContainer.offsetHeight);\n\n _this._.cameras.updateSize();\n }\n };\n\n var sceneContainer = document.getElementById(containerId).appendChild(document.createElement('div'));\n sceneContainer.id = '_lithosphere_scene';\n sceneContainer.style.width = '100%';\n sceneContainer.style.height = '100%';\n this._ = {\n containerId: containerId,\n container: document.getElementById(containerId),\n sceneContainer: sceneContainer,\n wasInitialized: false,\n rendererWrapper: null,\n renderer: null,\n cameras: null,\n cameraPositionTarget: null,\n tiledWorld: null,\n events: null,\n maxZoom: 0,\n minNativeZoom: 0,\n loader: new three__WEBPACK_IMPORTED_MODULE_1__[\"TextureLoader\"](),\n raycaster: new three__WEBPACK_IMPORTED_MODULE_1__[\"Raycaster\"](),\n updateEveryNthRender: 1,\n counters: {\n update: 0,\n frame: 0\n },\n lastCameraWasFirst: false,\n firstUpdate: true,\n firstLoad: false,\n loadingScreen: null,\n renderOnlyWhenOpen: true,\n zCutOff: 3,\n firstViewOverride: null,\n mouseIsInScene: false,\n marsRadius: 3396190\n };\n this._.container.style.position = 'relative';\n this.scene = new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]();\n this.scenesLOD = [new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]()];\n this.sceneBack = new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]();\n this.sceneFront = new three__WEBPACK_IMPORTED_MODULE_1__[\"Scene\"]();\n this.planet = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n this.planetsLOD = [new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"](), new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]()];\n this.frontGroup = new three__WEBPACK_IMPORTED_MODULE_1__[\"Object3D\"]();\n var defaultOptions = {\n loadingScreen: true,\n tileMapResource: null,\n customParsers: {},\n radiusOfTiles: 4,\n useLOD: true,\n LOD: [{\n radiusOfTiles: 4,\n zoomsUp: 3\n }, {\n radiusOfTiles: 2,\n zoomsUp: 7\n }, {\n radiusOfTiles: 2,\n zoomsUp: 11\n }],\n tileResolution: 32,\n trueTileResolution: 256,\n showAxes: false,\n wireframeMode: false,\n exaggeration: 1,\n renderOnlyWhenOpen: true,\n targetYOffset: 0,\n highlightColor: 'yellow',\n activeColor: 'red'\n };\n options = options || {};\n this.options = __assign(__assign({}, defaultOptions), options);\n\n this._init();\n }\n\n LithoSphere.prototype._init = function () {\n this._.rendererWrapper = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Renderer\"](this._.sceneContainer);\n this._.renderer = this._.rendererWrapper.renderer;\n\n if (this._.renderer) {\n this._.wasInitialized = true;\n } else return false;\n\n this.projection = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Projection\"](this.options.majorRadius, this.options.minorRadius, this.options.tileMapResource, this.options.trueTileResolution);\n this._.cameras = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Cameras\"](this._.container, this._.sceneContainer, this.scene, this.projection);\n this.layers = new _layers__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this);\n this.addLayer = this.layers.addLayer;\n this.removeLayer = this.layers.removeLayer;\n this.toggleLayer = this.layers.toggleLayer;\n this.setLayerOpacity = this.layers.setLayerOpacity;\n this.setLayerFilterEffect = this.layers.setLayerFilterEffect;\n this.getLayerByName = this.layers.getLayerByName;\n this.hasLayer = this.layers.hasLayer;\n this._.tiledWorld = new _core__WEBPACK_IMPORTED_MODULE_0__[\"TiledWorld\"](this);\n this.zoom = 10;\n this.trueZoom = this.zoom;\n this.mouse = {\n lat: null,\n lng: null,\n elev: null\n };\n this.planetCenter = new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, -(this.projection.radii.major / this.projection.radiusScale), 0);\n this.planet.position.set(this.planetCenter.x, -this.planetCenter.y, this.planetCenter.z);\n this.scene.add(this.planet);\n this.scenesLOD[0].add(this.planetsLOD[0]);\n this.scenesLOD[1].add(this.planetsLOD[1]);\n this.scenesLOD[2].add(this.planetsLOD[2]);\n this.frontGroup.position.set(this.planetCenter.x, -this.planetCenter.y, this.planetCenter.z);\n this.sceneFront.add(this.frontGroup);\n this.scene.add(new three__WEBPACK_IMPORTED_MODULE_1__[\"AmbientLight\"](0xfefefe));\n\n if (this.options.starsphere) {\n var starsphereGeometry = new three__WEBPACK_IMPORTED_MODULE_1__[\"SphereBufferGeometry\"](this.planetCenter.y * 1000, 64, 64);\n var starsphereMaterial = new three__WEBPACK_IMPORTED_MODULE_1__[\"MeshBasicMaterial\"]({\n color: this.options.starsphere.color || 0xaaaaaa\n });\n if (this.options.starsphere.url) starsphereMaterial.map = this._.loader.load(this.options.starsphere.url);\n starsphereMaterial.opacity = 1;\n this.starsphere = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](starsphereGeometry, starsphereMaterial);\n this.sceneBack.add(this.starsphere);\n }\n\n if (this.options.atmosphere) {\n this.atmosphere = new three__WEBPACK_IMPORTED_MODULE_1__[\"Mesh\"](new three__WEBPACK_IMPORTED_MODULE_1__[\"SphereBufferGeometry\"](this.planetCenter.y * 1.5, 128, 128), _core__WEBPACK_IMPORTED_MODULE_0__[\"Shaders\"].atmosphere(this.options.atmosphere.color));\n this.sceneBack.add(this.atmosphere);\n }\n\n if (this.options.showAxes === true) {\n var materialx = new three__WEBPACK_IMPORTED_MODULE_1__[\"LineBasicMaterial\"]({\n color: 0xff0000\n });\n var geometryx = new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferGeometry\"]().setFromPoints([new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0 * 2, 0, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](this.planetCenter.y * 2, 0, 0)]);\n var linex = new three__WEBPACK_IMPORTED_MODULE_1__[\"Line\"](geometryx, materialx);\n this.scene.add(linex);\n var materialy = new three__WEBPACK_IMPORTED_MODULE_1__[\"LineBasicMaterial\"]({\n color: 0x00ff00\n });\n var geometryy = new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferGeometry\"]().setFromPoints([new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, this.planetCenter.y * 2, 0)]);\n var liney = new three__WEBPACK_IMPORTED_MODULE_1__[\"Line\"](geometryy, materialy);\n this.scene.add(liney);\n var materialz = new three__WEBPACK_IMPORTED_MODULE_1__[\"LineBasicMaterial\"]({\n color: 0x0000ff\n });\n var geometryz = new three__WEBPACK_IMPORTED_MODULE_1__[\"BufferGeometry\"]().setFromPoints([new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, 0), new three__WEBPACK_IMPORTED_MODULE_1__[\"Vector3\"](0, 0, this.planetCenter.y * 2)]);\n var linez = new three__WEBPACK_IMPORTED_MODULE_1__[\"Line\"](geometryz, materialz);\n this.scene.add(linez);\n }\n\n this.controls = new _controls__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this);\n this.addControl = this.controls.addControl;\n this.removeControl = this.controls.removeControl;\n\n if (this.options.renderOnlyWhenOpen === false) {\n this._.renderOnlyWhenOpen = false;\n }\n\n this._.loadingScreen = new _secondary_loadingScreen__WEBPACK_IMPORTED_MODULE_4__[\"default\"](this);\n this._.events = new _core__WEBPACK_IMPORTED_MODULE_0__[\"Events\"](this);\n this.setCenter(this.options.initialView);\n\n this._animate();\n\n return true;\n };\n\n LithoSphere.prototype._render = function () {\n this._.renderer.clear();\n\n if (this._.renderOnlyWhenOpen) {\n var containerRect = this._.container.getBoundingClientRect();\n\n if (containerRect.width <= 0 || containerRect.height <= 0) return;\n }\n\n this._.counters.update = (this._.counters.update + 1) % this._.updateEveryNthRender;\n if (this._.counters.update === 0) this._update();\n if (!this._.cameras.isFirstPerson) this._.cameras.orbit.controls.update();\n this.layers.tile3d.forEach(function (tile3d) {\n tile3d.renderer.update();\n });\n\n this._.renderer.render(this.sceneBack, this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scenesLOD[2], this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scenesLOD[1], this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scenesLOD[0], this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.scene, this._.cameras.camera);\n\n this._.renderer.clearDepth();\n\n this._.renderer.render(this.sceneFront, this._.cameras.camera);\n };\n\n LithoSphere.prototype._update = function () {\n if (!this._.wasInitialized) return;\n\n if (this._.renderOnlyWhenOpen) {\n var containerRect = this._.container.getBoundingClientRect();\n\n if (containerRect.width <= 0 || containerRect.height <= 0) return;\n }\n\n this._.counters.frame = (this._.counters.frame + 1) % 4;\n this.scene.rotation.x = 0;\n this.scene.position.y = 0;\n\n if (!this._.firstUpdate) {\n this._.tiledWorld.refreshTiles();\n }\n\n this._.events._checkDesiredZoom();\n\n this.controls._onUpdateEvent();\n\n if (this._.cameras.isFirstPerson) {\n this._.lastCameraWasFirst = true;\n this._.cameras.firstPerson.controls.getObject().position.y = this._.cameras.orbit.controls.target.y - this._.cameras.firstPerson.height / this.projection.radiusScale;\n\n var v2 = this._.cameras.update();\n\n this._.events._rotateGlobe(v2);\n\n this._.events._onMouseMove();\n\n this.controls._onFirstPersonUpdate();\n } else if (this._.lastCameraWasFirst) {\n this._.lastCameraWasFirst = false;\n\n this.controls._onOrbitalUpdate();\n }\n\n if (this._.firstUpdate) {\n if (this._.firstViewOverride != null) this.setCenter(this._.firstViewOverride);else this.setCenter(this.options.initialView, true);\n var o = this._.cameras.orbit;\n var cam = o.camera;\n var con = o.controls;\n var pos = cam.position;\n var tar = con.target;\n this._.cameraPositionTarget = [pos.x, pos.y, pos.z, tar.x, tar.y, tar.z];\n this._.firstUpdate = false;\n }\n };\n\n return LithoSphere;\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (LithoSphere);\n\n//# sourceURL=webpack://LithoSphere/./src/lithosphere.ts?"); /***/ }), @@ -2185,7 +2245,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var thre /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n\nvar Utils = {\n getIn: function (obj, keyArray, notSetValue) {\n if (obj == null) return notSetValue != null ? notSetValue : null;\n if (typeof keyArray === 'string') keyArray = keyArray.split('.');\n if (keyArray == null) return notSetValue != null ? notSetValue : null;\n var object = Object.assign({}, obj);\n\n for (var i = 0; i < keyArray.length; i++) {\n if (object.hasOwnProperty(keyArray[i])) object = object[keyArray[i]];else return notSetValue != null ? notSetValue : null;\n }\n\n return object;\n },\n mod: function (n, m) {\n var remain = n % m;\n return Math.floor(remain >= 0 ? remain : remain + m);\n },\n findHighestMaxZoom: function (tileLayers) {\n var highest = 0;\n\n for (var l in tileLayers) {\n if (tileLayers[l].name != 'Vectors As Tiles') if (tileLayers[l].maxZoom > highest) {\n highest = tileLayers[l].maxZoom;\n }\n }\n\n return highest;\n },\n findLowestMinZoom: function (tileLayers) {\n var lowest = Infinity;\n\n for (var l in tileLayers) {\n if (tileLayers[l].path !== '_vectorsastile_') {\n if (tileLayers[l].minZoom < lowest) {\n lowest = tileLayers[l].minZoom;\n }\n }\n }\n\n return lowest;\n },\n isInExtent: function (xyz, bb, projection) {\n var inExtent = true;\n\n if (bb) {\n var tx_ext = xyz.x + 0;\n var ty_ext = xyz.y + 0;\n var projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n var tlat_ext = projectedLL.lat;\n var tlon_ext = projectedLL.lng;\n inExtent = tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n tx_ext = xyz.x + 1;\n ty_ext = xyz.y + 0;\n projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n tlat_ext = projectedLL.lat;\n tlon_ext = projectedLL.lng;\n inExtent = inExtent || tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n tx_ext = xyz.x + 1;\n ty_ext = xyz.y + 1;\n projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n tlat_ext = projectedLL.lat;\n tlon_ext = projectedLL.lng;\n inExtent = inExtent || tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n tx_ext = xyz.x + 0;\n ty_ext = xyz.y + 1;\n projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n tlat_ext = projectedLL.lat;\n tlon_ext = projectedLL.lng;\n inExtent = inExtent || tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n }\n\n return inExtent;\n },\n clone: function (obj) {\n var copy;\n if (null == obj || 'object' != typeof obj) return obj;\n\n if (obj instanceof Date) {\n copy = new Date();\n copy.setTime(obj.getTime());\n return copy;\n }\n\n if (obj instanceof Array) {\n copy = [];\n\n for (var i = 0, len = obj.length; i < len; i++) {\n copy[i] = Utils.clone(obj[i]);\n }\n\n return copy;\n }\n\n if (obj instanceof Object) {\n copy = {};\n\n for (var attr in obj) {\n if (obj.hasOwnProperty(attr)) copy[attr] = Utils.clone(obj[attr]);\n }\n\n return copy;\n }\n\n throw new Error(\"Unable to copy obj! Its type isn't supported.\");\n },\n capitalizeFirstLetter: function (string) {\n return string.charAt(0).toUpperCase() + string.slice(1);\n },\n getExtension: function (string) {\n return /(?:\\.([^.]+))?$/.exec(string)[1] || '';\n },\n getRadiansPerPixel: function (zoom) {\n return 360 / Math.pow(2, zoom) * (Math.PI / 180) / 256;\n },\n lastTileContains: [],\n tileContains: function (xyz, z, useLast) {\n if (useLast) {\n for (var i = 0; i < Utils.lastTileContains.length; i++) {\n var lastxyz = Utils.lastTileContains[i].call.xyz;\n\n if (lastxyz[0] == xyz[0] && lastxyz[1] == xyz[1] && lastxyz[2] == xyz[2] && Utils.lastTileContains[i].call.z == z) {\n return Utils.lastTileContains[i].result;\n }\n }\n }\n\n var contained = [];\n var zoomRatio = Math.pow(2, z) / Math.pow(2, xyz[2]);\n var max = [(xyz[0] + 1) * zoomRatio - 1, (xyz[1] + 1) * zoomRatio - 1];\n var min = [max[0] - zoomRatio + 1, max[1] - zoomRatio + 1];\n\n for (var x = min[0]; x <= max[0]; x++) {\n for (var y = min[1]; y <= max[1]; y++) {\n contained.push([x, y, z]);\n }\n }\n\n Utils.lastTileContains.unshift({\n call: {\n xyz: xyz,\n z: z\n },\n result: contained\n });\n if (Utils.lastTileContains.length > 3) Utils.lastTileContains.pop();\n return contained;\n },\n tileIsContained: function (xyzContainer, xyzContained, useLast) {\n var contains = this.tileContains(xyzContainer, xyzContained[2], useLast);\n\n for (var i = 0; i < contains.length; i++) {\n if (contains[i][0] == xyzContained[0] && contains[i][1] == xyzContained[1]) return true;\n }\n\n return false;\n },\n arrayAverage: function (array, key) {\n var total = 0;\n\n for (var i = 0; i < array.length; i++) {\n if (key != null) total += array[i][key];else total += array[i];\n }\n\n return total / array.length;\n },\n hexToRGB: function (hex) {\n var shorthandRegex = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\n hex = hex.replace(shorthandRegex, function (m, r, g, b) {\n return r + r + g + g + b + b;\n });\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16)\n } : null;\n },\n rotatePoint: function (pt, center, angle) {\n var cosAngle = Math.cos(angle);\n var sinAngle = Math.sin(angle);\n var dx = pt.x - center[0];\n var dy = pt.y - center[1];\n return {\n x: center[0] + dx * cosAngle - dy * sinAngle,\n y: center[1] + dx * sinAngle + dy * cosAngle\n };\n },\n rotateAroundArbAxis: function (object, axis, radians, noPremultiply) {\n object.updateWorldMatrix(true);\n var invWorldRot = object.getWorldQuaternion(new three__WEBPACK_IMPORTED_MODULE_0__[\"Quaternion\"]()).invert();\n axis.applyQuaternion(invWorldRot);\n var deltaLocalRot = new three__WEBPACK_IMPORTED_MODULE_0__[\"Quaternion\"]();\n deltaLocalRot.setFromAxisAngle(axis, radians);\n object.quaternion.multiply(deltaLocalRot);\n },\n getParamString: function (params, baseUrl, isUppercase) {\n var str = [];\n var urlParams = new URLSearchParams(baseUrl.toUpperCase());\n\n for (var o in params) {\n if (!urlParams.has(o.toUpperCase())) str.push(encodeURIComponent(isUppercase ? o.toUpperCase() : o) + '=' + encodeURIComponent(params[o]));\n }\n\n return (baseUrl && baseUrl.indexOf('?') !== -1 ? '&' : '?') + str.join('&');\n },\n isArray: function (object) {\n return Object.prototype.toString.call(object) === '[object Array]';\n }\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (Utils);\n\n//# sourceURL=webpack://LithoSphere/./src/utils/index.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n\nvar Utils = {\n getIn: function (obj, keyArray, notSetValue) {\n if (obj == null) return notSetValue != null ? notSetValue : null;\n if (typeof keyArray === 'string') keyArray = keyArray.split('.');\n if (keyArray == null) return notSetValue != null ? notSetValue : null;\n var object = Object.assign({}, obj);\n\n for (var i = 0; i < keyArray.length; i++) {\n if (object.hasOwnProperty(keyArray[i])) object = object[keyArray[i]];else return notSetValue != null ? notSetValue : null;\n }\n\n return object;\n },\n mod: function (n, m) {\n var remain = n % m;\n return Math.floor(remain >= 0 ? remain : remain + m);\n },\n findHighestMaxZoom: function (tileLayers) {\n var highest = 0;\n\n for (var l in tileLayers) {\n if (tileLayers[l].name != 'Vectors As Tiles') if (tileLayers[l].maxZoom > highest) {\n highest = tileLayers[l].maxZoom;\n }\n }\n\n return highest;\n },\n findLowestMinZoom: function (tileLayers) {\n var lowest = Infinity;\n\n for (var l in tileLayers) {\n if (tileLayers[l].path !== '_vectorsastile_') {\n if (tileLayers[l].minZoom < lowest) {\n lowest = tileLayers[l].minZoom;\n }\n }\n }\n\n return lowest;\n },\n isInExtent: function (xyz, bb, projection) {\n var inExtent = true;\n\n if (bb) {\n var tx_ext = xyz.x + 0;\n var ty_ext = xyz.y + 0;\n var projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n var tlat_ext = projectedLL.lat;\n var tlon_ext = projectedLL.lng;\n inExtent = tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n tx_ext = xyz.x + 1;\n ty_ext = xyz.y + 0;\n projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n tlat_ext = projectedLL.lat;\n tlon_ext = projectedLL.lng;\n inExtent = inExtent || tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n tx_ext = xyz.x + 1;\n ty_ext = xyz.y + 1;\n projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n tlat_ext = projectedLL.lat;\n tlon_ext = projectedLL.lng;\n inExtent = inExtent || tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n tx_ext = xyz.x + 0;\n ty_ext = xyz.y + 1;\n projectedLL = projection.tileXYZ2LatLng(tx_ext, ty_ext, xyz.z);\n tlat_ext = projectedLL.lat;\n tlon_ext = projectedLL.lng;\n inExtent = inExtent || tlat_ext < bb[3] && tlat_ext > bb[1] && tlon_ext < bb[2] && tlon_ext > bb[0];\n }\n\n return inExtent;\n },\n clone: function (obj) {\n var copy;\n if (null == obj || 'object' != typeof obj) return obj;\n\n if (obj instanceof Date) {\n copy = new Date();\n copy.setTime(obj.getTime());\n return copy;\n }\n\n if (obj instanceof Array) {\n copy = [];\n\n for (var i = 0, len = obj.length; i < len; i++) {\n copy[i] = Utils.clone(obj[i]);\n }\n\n return copy;\n }\n\n if (obj instanceof Object) {\n copy = {};\n\n for (var attr in obj) {\n if (obj.hasOwnProperty(attr)) copy[attr] = Utils.clone(obj[attr]);\n }\n\n return copy;\n }\n\n throw new Error(\"Unable to copy obj! Its type isn't supported.\");\n },\n capitalizeFirstLetter: function (string) {\n return string.charAt(0).toUpperCase() + string.slice(1);\n },\n getExtension: function (string) {\n return /(?:\\.([^.]+))?$/.exec(string)[1] || '';\n },\n getRadiansPerPixel: function (zoom) {\n return 360 / Math.pow(2, zoom) * (Math.PI / 180) / 256;\n },\n lastTileContains: [],\n tileContains: function (xyz, z, useLast) {\n if (useLast) {\n for (var i = 0; i < Utils.lastTileContains.length; i++) {\n var lastxyz = Utils.lastTileContains[i].call.xyz;\n\n if (lastxyz[0] == xyz[0] && lastxyz[1] == xyz[1] && lastxyz[2] == xyz[2] && Utils.lastTileContains[i].call.z == z) {\n return Utils.lastTileContains[i].result;\n }\n }\n }\n\n var contained = [];\n var zoomRatio = Math.pow(2, z) / Math.pow(2, xyz[2]);\n var max = [(xyz[0] + 1) * zoomRatio - 1, (xyz[1] + 1) * zoomRatio - 1];\n var min = [max[0] - zoomRatio + 1, max[1] - zoomRatio + 1];\n\n for (var x = min[0]; x <= max[0]; x++) {\n for (var y = min[1]; y <= max[1]; y++) {\n contained.push([x, y, z]);\n }\n }\n\n Utils.lastTileContains.unshift({\n call: {\n xyz: xyz,\n z: z\n },\n result: contained\n });\n if (Utils.lastTileContains.length > 3) Utils.lastTileContains.pop();\n return contained;\n },\n tileIsContained: function (xyzContainer, xyzContained, useLast) {\n var contains = this.tileContains(xyzContainer, xyzContained[2], useLast);\n\n for (var i = 0; i < contains.length; i++) {\n if (contains[i][0] == xyzContained[0] && contains[i][1] == xyzContained[1]) return true;\n }\n\n return false;\n },\n arrayAverage: function (array, key) {\n var total = 0;\n\n for (var i = 0; i < array.length; i++) {\n if (key != null) total += array[i][key];else total += array[i];\n }\n\n return total / array.length;\n },\n hexToRGB: function (hex) {\n var shorthandRegex = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\n hex = hex.replace(shorthandRegex, function (m, r, g, b) {\n return r + r + g + g + b + b;\n });\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16)\n } : null;\n },\n rotatePoint: function (pt, center, angle) {\n var cosAngle = Math.cos(angle);\n var sinAngle = Math.sin(angle);\n var dx = pt.x - center[0];\n var dy = pt.y - center[1];\n return {\n x: center[0] + dx * cosAngle - dy * sinAngle,\n y: center[1] + dx * sinAngle + dy * cosAngle\n };\n },\n rotateAroundArbAxis: function (object, axis, radians, noPremultiply) {\n object.updateWorldMatrix(true);\n var invWorldRot = object.getWorldQuaternion(new three__WEBPACK_IMPORTED_MODULE_0__[\"Quaternion\"]()).invert();\n axis.applyQuaternion(invWorldRot);\n var deltaLocalRot = new three__WEBPACK_IMPORTED_MODULE_0__[\"Quaternion\"]();\n deltaLocalRot.setFromAxisAngle(axis, radians);\n object.quaternion.multiply(deltaLocalRot);\n },\n getParamString: function (params, baseUrl, isUppercase) {\n var str = [];\n var urlParams = new URLSearchParams(baseUrl.toUpperCase());\n\n for (var o in params) {\n if (!urlParams.has(o.toUpperCase())) str.push(encodeURIComponent(isUppercase ? o.toUpperCase() : o) + '=' + encodeURIComponent(params[o]));\n }\n\n return (baseUrl && baseUrl.indexOf('?') !== -1 ? '&' : '?') + str.join('&');\n },\n isArray: function (object) {\n return Object.prototype.toString.call(object) === '[object Array]';\n },\n setChildrenMaterialOpacity: function (model, opacity, recurse) {\n model.children.forEach(function (mesh) {\n if (mesh.material) {\n mesh.material.transparent = true;\n mesh.material.opacity = opacity;\n }\n\n if (typeof recurse === 'function' && mesh.children && mesh.children.length > 0) {\n recurse(mesh);\n }\n });\n },\n setAllMaterialOpacity: function (model, opacity) {\n if (model.material) {\n model.material.transparent = true;\n model.material.opacity = opacity;\n }\n\n Utils.setChildrenMaterialOpacity(model, opacity, function (mesh) {\n Utils.setAllMaterialOpacity(mesh, opacity);\n });\n }\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (Utils);\n\n//# sourceURL=webpack://LithoSphere/./src/utils/index.ts?"); /***/ }), diff --git a/dist/src/constants.d.ts b/dist/src/constants.d.ts new file mode 100644 index 0000000..f719e40 --- /dev/null +++ b/dist/src/constants.d.ts @@ -0,0 +1 @@ +export declare const NO_DATA_VALUE_INTERNAL = -1100101; diff --git a/dist/src/controls/altitude.d.ts b/dist/src/controls/altitude.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/src/controls/compass.d.ts b/dist/src/controls/compass.d.ts new file mode 100644 index 0000000..1647cdc --- /dev/null +++ b/dist/src/controls/compass.d.ts @@ -0,0 +1,15 @@ +import { Corners } from '../generalTypes.d.ts'; +interface Private { +} +export default class Compass { + _: Private; + p: any; + name: string; + corner: Corners; + constructor(parent: any, name: string); + getControl: () => string; + attachEvents: () => void; + onUpdate: () => void; + setDirection: () => void; +} +export {}; diff --git a/dist/src/controls/controls.d.ts b/dist/src/controls/controls.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/src/controls/coordinates.d.ts b/dist/src/controls/coordinates.d.ts new file mode 100644 index 0000000..ea00e2c --- /dev/null +++ b/dist/src/controls/coordinates.d.ts @@ -0,0 +1,19 @@ +import { Corners } from '../generalTypes.d.ts'; +interface Private { +} +interface Params { + existingDivId?: string; +} +export default class Coordinates { + _: Private; + p: any; + name: string; + params: Params; + corner: Corners; + constructor(parent: any, name: string, params?: object); + getControl: () => string; + attachEvents: () => void; + onUpdate: () => void; + private updateMouseCoords; +} +export {}; diff --git a/dist/src/controls/crop.d.ts b/dist/src/controls/crop.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/src/controls/exaggerate.d.ts b/dist/src/controls/exaggerate.d.ts new file mode 100644 index 0000000..f2c1d1e --- /dev/null +++ b/dist/src/controls/exaggerate.d.ts @@ -0,0 +1,18 @@ +import { Corners } from '../generalTypes.d.ts'; +interface Private { +} +export default class Exaggerate { + _: Private; + id: string; + p: any; + name: string; + corner: Corners; + exaggeration: number; + constructor(parent: any, name: string); + getControl: () => string; + attachEvents: () => void; + private getInactiveContent; + private getActiveContent; + setExaggeration: (multiplier: number) => void; +} +export {}; diff --git a/dist/src/controls/home.d.ts b/dist/src/controls/home.d.ts new file mode 100644 index 0000000..47bcf19 --- /dev/null +++ b/dist/src/controls/home.d.ts @@ -0,0 +1,13 @@ +import { Corners } from '../generalTypes'; +interface Private { +} +export default class Home { + _: Private; + p: any; + name: string; + corner: Corners; + constructor(parent: any, name: string); + getControl: () => string; + attachEvents: () => void; +} +export {}; diff --git a/dist/src/controls/index.d.ts b/dist/src/controls/index.d.ts new file mode 100644 index 0000000..37d3725 --- /dev/null +++ b/dist/src/controls/index.d.ts @@ -0,0 +1,29 @@ +import { Corners } from '../generalTypes'; +export default class Controls { + p: any; + controlContainer: HTMLElement; + corners: { + TopLeft: HTMLElement; + TopRight: HTMLElement; + BottomLeft: HTMLElement; + BottomRight: HTMLElement; + }; + activeControls: any; + compass: any; + coordinates: any; + home: any; + layers: any; + exaggerate: any; + observe: any; + walk: any; + link: any; + constructor(parent: any); + addControl: (name: string, control: any, params?: object, corner?: Corners) => any; + removeControl: (name: any) => void; + _onUpdateEvent: () => void; + _onMove: (lng: any, lat: any, height: any) => void; + _onMouseMove: (lng: any, lat: any, height: any) => void; + _onMouseOut: (e?: any) => void; + _onFirstPersonUpdate: () => void; + _onOrbitalUpdate: (e?: any) => void; +} diff --git a/dist/src/controls/layers.d.ts b/dist/src/controls/layers.d.ts new file mode 100644 index 0000000..f9d1646 --- /dev/null +++ b/dist/src/controls/layers.d.ts @@ -0,0 +1,17 @@ +import { Corners } from '../generalTypes.d.ts'; +interface Private { +} +export default class Layers { + _: Private; + id: string; + p: any; + name: string; + corner: Corners; + constructor(parent: any, name: string); + getControl: () => string; + attachEvents: () => void; + private getInactiveContent; + private getActiveContent; + private attachEventsInternal; +} +export {}; diff --git a/dist/src/controls/link.d.ts b/dist/src/controls/link.d.ts new file mode 100644 index 0000000..054ff1d --- /dev/null +++ b/dist/src/controls/link.d.ts @@ -0,0 +1,29 @@ +import { Corners } from '../generalTypes'; +import { Object3D } from 'three'; +interface Private { + linkPanned: boolean; + linkPannedTimeout: any; + targetPoint?: Object3D; +} +export default class Link { + _: Private; + p: any; + name: string; + params: any; + corner: Corners; + return: any; + constructor(parent: any, name: string, params?: object); + getControl: () => string; + attachEvents: () => void; + getReturn: () => any; + onMove: (lng: any, lat: any, height: any) => void; + onMouseMove: (lng: any, lat: any, height: any) => void; + onMouseOut: () => void; + onFirstPersonUpdate: () => void; + onOrbitalUpdate: () => void; + setLink: (latlng?: any, style?: any, spriteId?: string) => void; + linkMove: (lng: number, lat: number) => void; + linkMouseMove: (lng: number, lat: number) => void; + linkMouseOut: () => void; +} +export {}; diff --git a/dist/src/controls/observe.d.ts b/dist/src/controls/observe.d.ts new file mode 100644 index 0000000..ff6c83c --- /dev/null +++ b/dist/src/controls/observe.d.ts @@ -0,0 +1,23 @@ +import { Corners } from '../generalTypes.d.ts'; +interface Private { +} +export default class Observe { + _: Private; + p: any; + name: string; + id: string; + helpDiv: HTMLElement; + corner: Corners; + constructor(parent: any, name: string); + getControl: () => string; + private getInactiveContent; + private getActiveContent; + attachEvents: () => void; + private setCamera; + private leaveObserver; + private getObserverValues; + private keydownObserverSettings; + private toggleFOVOverlay; + private updateFOVOverlayBounds; +} +export {}; diff --git a/dist/src/controls/walk.d.ts b/dist/src/controls/walk.d.ts new file mode 100644 index 0000000..df7bcef --- /dev/null +++ b/dist/src/controls/walk.d.ts @@ -0,0 +1,16 @@ +import { Corners } from '../generalTypes.d.ts'; +interface Private { +} +export default class Walk { + _: Private; + p: any; + name: string; + helpDiv: HTMLElement; + corner: Corners; + constructor(parent: any, name: string); + getControl: () => string; + attachEvents: () => void; + private setCamera; + private leaveWalking; +} +export {}; diff --git a/dist/src/core/events.d.ts b/dist/src/core/events.d.ts index 32da82c..a949cf5 100644 --- a/dist/src/core/events.d.ts +++ b/dist/src/core/events.d.ts @@ -36,6 +36,7 @@ export default class Events { _matchPlanetsLODToPlanet(): void; _refreshFrontGroupRotation(): void; private _onClick; + private _onKeyDown; _onMouseMove: (e?: any) => void; private _updateMouseCoords; private updateHoverInfoPosition; diff --git a/dist/src/core/renderer.d.ts b/dist/src/core/renderer.d.ts new file mode 100644 index 0000000..a928eea --- /dev/null +++ b/dist/src/core/renderer.d.ts @@ -0,0 +1,8 @@ +export default class Renderer { + renderer: any; + container: HTMLElement; + constructor(container: HTMLElement); + _init(): void; + updateSize: () => void; + remove(): void; +} diff --git a/dist/src/core/shaders.d.ts b/dist/src/core/shaders.d.ts new file mode 100644 index 0000000..da70435 --- /dev/null +++ b/dist/src/core/shaders.d.ts @@ -0,0 +1,7 @@ +import { ShaderMaterial } from 'three'; +declare const Shaders: { + simplePoint: () => ShaderMaterial; + multiTexture: (textures: any, fadeIn?: boolean) => ShaderMaterial; + atmosphere: (color?: string) => ShaderMaterial; +}; +export default Shaders; diff --git a/dist/src/core/tiledWorld.d.ts b/dist/src/core/tiledWorld.d.ts index 977c3b9..33fe014 100644 --- a/dist/src/core/tiledWorld.d.ts +++ b/dist/src/core/tiledWorld.d.ts @@ -27,6 +27,7 @@ export default class TiledWorld { removeAllOutdatedTiles(): void; removeTileXYZ(xyz: XYZ): void; killDrawingTiles(): void; + filterEffects(): void; fadeInTiles(): void; fadeOutTiles(): void; } diff --git a/dist/src/layers/curtain.d.ts b/dist/src/layers/curtain.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/src/layers/index.d.ts b/dist/src/layers/index.d.ts index 3bc8652..2529e6d 100644 --- a/dist/src/layers/index.d.ts +++ b/dist/src/layers/index.d.ts @@ -2,12 +2,14 @@ import Tile3dLayerer from './tile3d'; import TileLayerer from './tile'; import ClampedLayerer from './clamped'; import VectorLayerer from './vector'; +import ModelLayerer from './model'; interface Private { layerers: { tile3d: Tile3dLayerer; tile: TileLayerer; clamped: ClampedLayerer; vector: VectorLayerer; + model: ModelLayerer; }; } export default class Layers { @@ -18,6 +20,7 @@ export default class Layers { tile: any; clamped: any; vector: any; + model: any; all: any; constructor(parent: any); _reset(): void; @@ -25,10 +28,12 @@ export default class Layers { removeLayer: (name: string) => boolean; toggleLayer: (name: string, on?: boolean) => boolean; setLayerOpacity: (name: string, opacity: number) => boolean; + setLayerFilterEffect: (name: string, filter: string, value: number) => boolean; findHighestMaxZoom: () => number; findLowestMinZoom: () => number; private getFeatureStyleProp; getLayerByName: (layerName: string) => any; + hasLayer: (layerName: string) => boolean; getFeatureStyle: (layer: any, feature: any, isStrokeless?: boolean) => any; } export {}; diff --git a/dist/src/layers/model.d.ts b/dist/src/layers/model.d.ts new file mode 100644 index 0000000..f9a487b --- /dev/null +++ b/dist/src/layers/model.d.ts @@ -0,0 +1,14 @@ +export default class ModelLayerer { + p: any; + modelCache: any; + constructor(parent: any); + add: (layerObj: any, callback?: Function) => void; + toggle: (name: string, on?: boolean) => boolean; + setOpacity: (name: string, opacity: number) => boolean; + remove: (name: string) => boolean; + private generateModel; + private objToModel; + private daeToModel; + private gltfToModel; + private localizeModel; +} diff --git a/dist/src/layers/overlay.d.ts b/dist/src/layers/overlay.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/src/layers/tile.d.ts b/dist/src/layers/tile.d.ts new file mode 100644 index 0000000..2527afb --- /dev/null +++ b/dist/src/layers/tile.d.ts @@ -0,0 +1,9 @@ +export default class TileLayerer { + p: any; + constructor(parent: any); + add: (layerObj: any) => void; + toggle: (name: string, on?: boolean) => boolean; + setOpacity: (name: string, opacity: number) => boolean; + setFilterEffect: (name: string, filter: string, value: number) => boolean; + remove: (name: string) => boolean; +} diff --git a/dist/src/layers/vector.d.ts b/dist/src/layers/vector.d.ts new file mode 100644 index 0000000..8b5ff02 --- /dev/null +++ b/dist/src/layers/vector.d.ts @@ -0,0 +1,11 @@ +export default class VectorLayerer { + p: any; + baseStyle: any; + constructor(parent: any); + add: (layerObj: any, callback?: Function) => void; + toggle: (name: string, on?: boolean) => boolean; + setOpacity: (name: string, opacity: number) => boolean; + remove: (name: string) => boolean; + private generateVectors; + private geomTo; +} diff --git a/dist/src/lithosphere.d.ts b/dist/src/lithosphere.d.ts index afa3d87..2bf29b6 100644 --- a/dist/src/lithosphere.d.ts +++ b/dist/src/lithosphere.d.ts @@ -8,6 +8,7 @@ interface Private { container: HTMLElement; sceneContainer: HTMLElement; wasInitialized: boolean; + rendererWrapper: any; renderer: any; cameras: any; cameraPositionTarget: number[]; @@ -42,6 +43,9 @@ export default class LithoSphere { removeLayer: Function; toggleLayer: Function; setLayerOpacity: Function; + setLayerFilterEffect: Function; + getLayerByName: Function; + hasLayer: Function; addControl: Function; removeControl: Function; scene: Scene; diff --git a/dist/src/parsers/demt.d.ts b/dist/src/parsers/demt.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/dist/src/parsers/rgba.d.ts b/dist/src/parsers/rgba.d.ts new file mode 100644 index 0000000..78d8857 --- /dev/null +++ b/dist/src/parsers/rgba.d.ts @@ -0,0 +1 @@ +export default function RGBAParser(tilePath: string, layerObj?: any, xyz?: any, tileResolution?: number, numberOfVertices?: number): Promise; diff --git a/dist/src/parsers/tif.d.ts b/dist/src/parsers/tif.d.ts new file mode 100644 index 0000000..60e1e10 --- /dev/null +++ b/dist/src/parsers/tif.d.ts @@ -0,0 +1 @@ +export default function TifParser(tilePath: string, layerObj?: any, xyz?: any, tileResolution?: number, numberOfVertices?: number): Promise; diff --git a/dist/src/secondary/OrbitControls.d.ts b/dist/src/secondary/OrbitControls.d.ts new file mode 100644 index 0000000..cd0b176 --- /dev/null +++ b/dist/src/secondary/OrbitControls.d.ts @@ -0,0 +1,5 @@ +declare function OrbitControls(object: any, domElement: any): void; +declare namespace OrbitControls { + var prototype: any; +} +export default OrbitControls; diff --git a/dist/src/secondary/PNG/png.d.ts b/dist/src/secondary/PNG/png.d.ts new file mode 100644 index 0000000..60f1afc --- /dev/null +++ b/dist/src/secondary/PNG/png.d.ts @@ -0,0 +1,16 @@ +export default class PNG { + static load(url: any, options: any, callback: any, failureCallback: any): void; + constructor(data1: any); + read(bytes: any): any[]; + readUInt32(): number; + readUInt16(): number; + decodePixels(data: any): Uint8Array; + decodePalette(): Uint8Array; + copyToImageData(imageData: any, pixels: any): void; + decode(): Uint8Array; + decodeFrames(ctx: any): void; + renderFrame(ctx: any, number: any): any; + animate(ctx: any): void; + stopAnimation(): void; + render(canvas: any): any; +} diff --git a/dist/src/secondary/PNG/zlib.d.ts b/dist/src/secondary/PNG/zlib.d.ts new file mode 100644 index 0000000..9668a19 --- /dev/null +++ b/dist/src/secondary/PNG/zlib.d.ts @@ -0,0 +1,4 @@ +export declare const FlateStream: { + (bytes: any): void; + prototype: any; +}; diff --git a/dist/src/secondary/PointerLockControls.d.ts b/dist/src/secondary/PointerLockControls.d.ts new file mode 100644 index 0000000..6ee89e9 --- /dev/null +++ b/dist/src/secondary/PointerLockControls.d.ts @@ -0,0 +1 @@ +export default function PointerLockControls(camera: any): void; diff --git a/dist/src/secondary/loadingScreen.d.ts b/dist/src/secondary/loadingScreen.d.ts new file mode 100644 index 0000000..46b2871 --- /dev/null +++ b/dist/src/secondary/loadingScreen.d.ts @@ -0,0 +1,7 @@ +import './loadingScreen.scss'; +export default class Controls { + p: any; + loadingContainer: HTMLElement; + constructor(parent: any); + end: (name: any) => void; +} diff --git a/dist/src/secondary/sprites.d.ts b/dist/src/secondary/sprites.d.ts new file mode 100644 index 0000000..e9fd951 --- /dev/null +++ b/dist/src/secondary/sprites.d.ts @@ -0,0 +1,8 @@ +import { Sprite } from 'three'; +declare const Sprites: { + spriteMaterials: {}; + makeMarkerSprite: (parameters: any, id: any, forceNewMaterial?: boolean) => Sprite; + makeMarkerMaterial: (parameters: any, id: any, forceNewMaterial?: boolean) => any; + makeTextSprite: (message: any, parameters: any) => Sprite; +}; +export default Sprites; diff --git a/dist/src/utils/index.d.ts b/dist/src/utils/index.d.ts index 3977a43..8a123d9 100644 --- a/dist/src/utils/index.d.ts +++ b/dist/src/utils/index.d.ts @@ -18,5 +18,7 @@ declare const Utils: { rotateAroundArbAxis(object: any, axis: any, radians: any, noPremultiply?: boolean): void; getParamString(params: any, baseUrl: string, isUppercase?: boolean): string; isArray(object: any): boolean; + setChildrenMaterialOpacity(model: any, opacity: number, recurse?: Function): void; + setAllMaterialOpacity(model: any, opacity: any): void; }; export default Utils; diff --git a/docs/pages/Constructor/constructor.markdown b/docs/pages/Constructor/constructor.markdown index 3906105..e7fe02d 100644 --- a/docs/pages/Constructor/constructor.markdown +++ b/docs/pages/Constructor/constructor.markdown @@ -28,27 +28,29 @@ new LithoSphere(containerId, options) ## Options -| Parameter | Type | Default | Description | -| :--------------------: | :--------: | :--------------------------------------------------------------------------------: | :------------------------------------------------------------------------------: | -| **initialView** | _object_ | See [initialView]({{ site.baseurl }}/constructor#optionsinitialview) below | Sets the initial coordinate view of the scene | -| **majorRadius** | _integer_ | 6371000 | Major planetary radius in meters | -| **minorRadius** | _integer_ | majorRadius | Minor planetary radius in meters | -| **loadingScreen** | _boolean_ | true | If true, shows a loading screen until all lithosphere content first loads | -| **customParsers** | _object_ | See [Parsers]({{ site.baseurl }}/parsers) | Allows the use of custom elevation tile parsers | -| **demFallback** | _object_ | See [demFallback]({{ site.baseurl }}/constructor#optionsdemfallback) below | A DEM to fallback to if any layer's DEM fails | -| **tileMapResource** | _object_ | See [tileMapResource]({{ site.baseurl }}/constructor#optionstilemapresource) below | Configures projections | -| **radiusOfTiles** | _integer_ | 4 | How many tiles outward from the center to use for the base tiles | -| **wireframeMode** | _boolean_ | false | If true, all tiles are rendered with a wireframe material | -| **exaggeration** | _number_ | 1 | A multiplier to scale terrain heights by | -| **showAxes** | _boolean_ | false | If true, XYZ axes are rendered | -| **useLOD** | _boolean_ | true | If true, Level of Detail (LOD) tiles are rendered in the background | -| **LOD** | _object[]_ | See [LOD]({{ site.baseurl }}/constructor#optionslod) below | Fine tune Level of Detail (LOD) layers | -| **tileResolution** | _number_ | 32 | Square tile pixel dimension | -| **renderOnlyWhenOpen** | _boolean_ | true | Only update and render the scene if the containerId element has an non-zero area | -| **starsphere** | _object_ | See [starsphere]({{ site.baseurl }}/constructor#optionsstarsphere) below | Setup a skydome/skybox/skysphere | -| **atmosphere** | _object_ | See [atmosphere]({{ site.baseurl }}/constructor#optionsatmosphere) below | Setup an atmosphere for your planet | -| **highlightColor** | _string_ | 'yellow' | What color should highlight things be? (If hovered) | -| **activeColor** | _string_ | 'red' | What color should active things be? (If clicked) | +| Parameter | Type | Default | Description | +| :----------------------: | :--------: | :--------------------------------------------------------------------------------: | :------------------------------------------------------------------------------: | +| **initialView** | _object_ | See [initialView]({{ site.baseurl }}/constructor#optionsinitialview) below | Sets the initial coordinate view of the scene | +| **majorRadius** | _integer_ | 6371000 | Major planetary radius in meters | +| **minorRadius** | _integer_ | majorRadius | Minor planetary radius in meters | +| **loadingScreen** | _boolean_ | true | If true, shows a loading screen until all lithosphere content first loads | +| **customParsers** | _object_ | See [Parsers]({{ site.baseurl }}/parsers) | Allows the use of custom elevation tile parsers | +| **demFallback** | _object_ | See [demFallback]({{ site.baseurl }}/constructor#optionsdemfallback) below | A DEM to fallback to if any layer's DEM fails | +| **tileMapResource** | _object_ | See [tileMapResource]({{ site.baseurl }}/constructor#optionstilemapresource) below | Configures projections | +| **radiusOfTiles** | _integer_ | 4 | How many tiles outward from the center to use for the base tiles | +| **wireframeMode** | _boolean_ | false | If true, all tiles are rendered with a wireframe material | +| **exaggeration** | _number_ | 1 | A multiplier to scale terrain heights by | +| **showAxes** | _boolean_ | false | If true, XYZ axes are rendered | +| **useLOD** | _boolean_ | true | If true, Level of Detail (LOD) tiles are rendered in the background | +| **LOD** | _object[]_ | See [LOD]({{ site.baseurl }}/constructor#optionslod) below | Fine tune Level of Detail (LOD) layers | +| **tileResolution** | _number_ | 32 | Square tile pixel dimension | +| **renderOnlyWhenOpen** | _boolean_ | true | Only update and render the scene if the containerId element has an non-zero area | +| **starsphere** | _object_ | See [starsphere]({{ site.baseurl }}/constructor#optionsstarsphere) below | Setup a skydome/skybox/skysphere | +| **atmosphere** | _object_ | See [atmosphere]({{ site.baseurl }}/constructor#optionsatmosphere) below | Setup an atmosphere for your planet | +| **canBecomeHighlighted** | _boolean_ | true | Globally disable highlighting | +| **highlightColor** | _string_ | 'yellow' | What color should highlight things be? (If hovered) | +| **canBecomeActive** | _boolean_ | true | Globally disable coloring active features | +| **activeColor** | _string_ | 'red' | What color should active things be? (If clicked) | ### options.initialView diff --git a/docs/pages/Functions/functions.markdown b/docs/pages/Functions/functions.markdown index 51bf849..4d1d867 100644 --- a/docs/pages/Functions/functions.markdown +++ b/docs/pages/Functions/functions.markdown @@ -9,4 +9,62 @@ nav_order: 7 A collection of potentially useful functions within the `Litho` object. You can explore on your own too — just don't break things and know that, generally, items prefixed with or buried under `_`s are meant to be more private/readonly. -TODO +### addLayer() + +Adds a new layer to the globe. +`addLayer = (type: string, layerObj: any, callback?: Function): void` + +type | _string_ | Type of layer to add. | One of ['tile', 'tile3d', 'clamped', 'vector', 'model', ...] +layerObj | _object_ | The new layer's object | See layer type docs for examples +callback | _Function_ | Called when a layer finishes loading (i.e. a vector layer downloads its geojson) | Not all layer types support this + +### removeLayer() + +Removes an existing layer from the globe. +`removeLayer = (name: string): boolean` + +name | _string_ | Layer name to remove +_returns_ | _boolean_ | `true` only if layer was found and removed + +### toggleLayer() + +`toggleLayer = (name: string, on?: boolean): boolean` + +### setLayerOpacity() + +`setLayerOpacity = (name: string, opacity: number): boolean` + +### setLayerFilterEffect() + +Sets a tile layer's filter effects. Multiple filters can be applied at once. The possible filter effects are: + +- brightness (default 1.0) +- saturation (default 1.0) +- contrast (default 1.0) +- blendCode (default 0) + 0: Blending off + 1: An overlay blend + 2: A color blend + +`setLayerFilterEffect = (name: string, filter: string, value: number): boolean` + +_name_ | _string_ | Name of the tile layer to apply a filter to +_filter_ | _string_ | Filter name to apply | One of ['brightness', 'saturation', 'contrast', 'blendCode'] +_value_ | _string_ | The value to set the filter to +_returns_ | _boolean_ | `true` only if layer was found and filtered upon + +### getLayerByName() + +`getLayerByName = (layerName: string): any` + +### hasLayer() + +`hasLayer = (layerName: string): boolean` + +### addControl() + +`addControl = (name: string, control: any, params?: object, corner?: Corners): any` + +### removeControl() + +`removeControl = (name): void` diff --git a/docs/pages/Layers/Clamped/clamped.markdown b/docs/pages/Layers/Clamped/clamped.markdown index 57c0de2..f219874 100644 --- a/docs/pages/Layers/Clamped/clamped.markdown +++ b/docs/pages/Layers/Clamped/clamped.markdown @@ -33,10 +33,18 @@ Litho.addLayer( }, point: {}, line: {}, - polygon: {}, + polygon: { + canBecomeHighlighted: false, //default true + canBecomeActive: false, //default true + }, byProp: { 'prop=images.0.test:blue': {}, }, + bearing: { + angleProp: 'yaw_rad', // path.to.bearing.prop + angleUnit: 'rad', //rad | deg + color: 'cyan', //css color + }, }, opacity: 1, minZoom: 11, @@ -47,6 +55,8 @@ Litho.addLayer( 137.42500036372522, -4.62500251269999, ], + canBecomeHighlighted: true, //default true + canBecomeActive: true, //default true //preDrawn?: boolean //override all clamped tiles with pre drawn tiles //data?: { {z}: { {x}: { {y}: { pre_drawn_tile_canvas_data } }}} if preDrawn, use these tiles. }, diff --git a/docs/pages/Layers/Model/model.markdown b/docs/pages/Layers/Model/model.markdown new file mode 100644 index 0000000..f455fa6 --- /dev/null +++ b/docs/pages/Layers/Model/model.markdown @@ -0,0 +1,53 @@ +--- +layout: page +title: Model +permalink: /layers/model +parent: Layers +--- + +# Model + +Adds a model to the scene. + +Supports: .glb, .gltf, .dae, .obj + +Example + +```javascript +Litho.addLayer( + 'model', + { + name: 'roverGLTF', + order: 1, + on: true, + path: 'http://localhost:8888/Missions/MSL/Data/models/Perseverance.glb', + // mtlPath: '', //if path is to an obj + opacity: 0.5, + position: { + longitude: 137.3572927368641, // default 0 + latitude: -4.674971631163808, // default 0 + elevation: -4443.613, // default 0 + }, + scale: 10, // default 1 + rotation: { + // y-up is away from planet center. x is pitch, y is yaw, z is roll + x: Math.PI / 12, // in radians | default 0 + y: Math.PI / 1.5, // default 0 + z: 0, // default 0 + order: 'YXZ', //default YXZ + }, + // cache: true, // default true // If true, uses cloned meshes from the first download + }, + () => { + console.log('Rover loaded') + //Litho.setLayerOpacity('roverGLTF', 0.25) + //Litho.removeLayer('roverGLTF') + /* + Litho.toggleLayer('roverGLTF', false) + setTimeout(() => { + Litho.toggleLayer('roverGLTF', true) + }, 10000) + */ + } +) +``` diff --git a/docs/pages/Layers/Tile/tile.markdown b/docs/pages/Layers/Tile/tile.markdown index 7d39582..a5f40ec 100644 --- a/docs/pages/Layers/Tile/tile.markdown +++ b/docs/pages/Layers/Tile/tile.markdown @@ -32,6 +32,13 @@ Litho.addLayer('tile', { opacity: 1, minZoom: 10, maxZoom: 17, + filters: { + brightness: 1, + contrast: 1, + saturation: 1, + blendCode: 0, //0 = none, 1 = overlay - caveat - tile zooms for all layers should line up, + blend: 0, + }, boundingBox: [ 137.09995782300004, -5.10494553812677, diff --git a/docs/pages/Layers/layers.markdown b/docs/pages/Layers/layers.markdown index 857d65c..48afac0 100644 --- a/docs/pages/Layers/layers.markdown +++ b/docs/pages/Layers/layers.markdown @@ -19,4 +19,6 @@ Litho.addLayer(type, options) Litho.setLayerOpacity(name, opacity) Litho.toggleLayer(name) Litho.removeLayer(name) +Litho.getLayerByName(name) +Litho.hasLayer(name) ``` diff --git a/examples/example.html b/examples/example.html index 3ef5408..eaa0ac5 100644 --- a/examples/example.html +++ b/examples/example.html @@ -69,6 +69,7 @@ resunitsperpixel: 34, reszoomlevel: 0, }, + radiusOfTiles: 4, //default 4 //wireframeMode: true, //exaggeration: 1, //default 1 showAxes: true, @@ -82,7 +83,9 @@ atmosphere: { color: '#111111', }, + canBecomeHighlighted: true, // default true highlightColor: 'yellow', //css color for vector hover highlights | default 'yellow' + canBecomeActive: true, // default true activeColor: 'red', //css color for active vector features | default 'red' }) @@ -105,6 +108,13 @@ opacity: 1, minZoom: 10, maxZoom: 17, + filters: { + brightness: 1, + contrast: 1, + saturation: 1, + blendCode: 0, //0 = none, 1 = overlay - caveat - tile zooms for all layers should line up, + blend: 0, + }, boundingBox: [ 137.09995782300004, -5.10494553812677, @@ -136,6 +146,8 @@ ], noDataValue: 0, //opt (number) - no data dem value //unused }) + Litho.setLayerFilterEffect('HiRISE', 'blendCode', 2) + //Litho.options.radiusOfTiles = 10 Litho.addLayer('tile3d', { name: '3dTileExample', @@ -147,16 +159,16 @@ minZoom: 11, maxZoom: 18, position: { - longitude: 137.4091927368641, // default 0 + longitude: 137.4071927368641, // default 0 latitude: -4.626571631163808, // default 0 - elevation: -4470, // default 0 + elevation: -4480, // default 0 }, - scale: 2, // default 1 + scale: 1, // default 1 rotation: { - x: 0, // in radians | default 0 + x: Math.PI / 2, // in radians | default 0 y: -Math.PI / 2, // default 0 - z: Math.PI / 4, // default 0 - order: 'ZXY', //default 'XYZ' + z: 0, // default 0 + order: 'YXZ', //default 'YXZ' }, }) //Litho.removeLayer('3dTileExample') @@ -174,18 +186,25 @@ // Prefer feature[f].properties.style values letPropertiesStyleOverride: true, // default false default: { - fillColor: 'white', //Use only rgb and hex. No css color names + fillColor: '#444444', //Use only rgb and hex. No css color names fillOpacity: 1, color: 'black', weight: 2, radius: 'prop=radius', }, - point: {}, + point: { + radius: 8, + }, line: {}, polygon: {}, byProp: { 'prop=images.0.test:blue': {}, }, + bearing: { + angleProp: 'yaw_rad', + angleUnit: 'rad', + color: 'lime', + }, }, opacity: 1, minZoom: 11, @@ -204,49 +223,60 @@ } ) - Litho.addLayer('clamped', { - name: 'styledFeatures', - on: true, - geojson: { - type: 'FeatureCollection', - features: [ - { - type: 'Feature', - geometry: { - type: 'Polygon', - coordinates: [ - [ - [137.358048, -4.673226], - [137.362189, -4.673632], - [137.36176, -4.675279], - [137.357833, -4.674638], - [137.358048, -4.673226], + Litho.addLayer( + 'clamped', + { + name: 'styledFeatures', + on: true, + geojson: { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + type: 'Polygon', + coordinates: [ + [ + [137.358048, -4.673226], + [137.362189, -4.673632], + [137.36176, -4.675279], + [137.357833, -4.674638], + [137.358048, -4.673226], + ], ], - ], - }, - properties: { - style: { - color: 'rgb(194, 28, 190)', - dashArray: '', - fillColor: 'rgb(104, 28, 190)', - fillOpacity: 0.2, - opacity: 1, - radius: 2, - symbol: '', + }, + properties: { + style: { + color: 'rgb(194, 28, 190)', + dashArray: '', + fillColor: 'rgb(104, 28, 190)', + fillOpacity: 0.2, + opacity: 1, + radius: 2, + symbol: '', + }, }, }, - }, - ], - }, - opacity: 1, - minZoom: 0, - maxZoom: 30, - style: { - // Prefer feature[f].properties.style values - letPropertiesStyleOverride: true, + ], + }, + opacity: 1, + minZoom: 0, + maxZoom: 30, + style: { + // Prefer feature[f].properties.style values + letPropertiesStyleOverride: true, + }, }, - }) + () => { + //console.log('loaded') + setTimeout(() => { + //console.log('removing') + //Litho.removeLayer('styledFeatures') + }, 10000) + } + ) + /* Litho.addLayer('clamped', { name: 'clampedCCam', order: 5, @@ -283,6 +313,7 @@ //preDrawn?: boolean //override all clamped tiles with pre drawn tiles //data?: { {z}: { {x}: { {y}: { pre_drawn_tile_canvas_data } }}} if preDrawn, use these tiles. }) + */ Litho.addLayer('clamped', { name: 'clampedPoly', @@ -332,7 +363,10 @@ }, point: {}, line: {}, - polygon: {}, + polygon: { + canBecomeHighlighted: false, //default true + canBecomeActive: false, //default true + }, byProp: { 'prop=images.0.test:blue': {}, }, @@ -463,6 +497,148 @@ maxZoom: 18, }) //Litho.removeLayer('vectorPoint') + /* + Litho.addLayer( + 'model', + { + name: 'roverGLTF', + order: 1, + on: true, + path: + 'http://localhost:8888/Missions/MSL/Data/models/Perseverance.glb', + opacity: 0.5, + isArrayed: false, // default false // if true, position, scale and rotation are arrays for a series of models + position: { + longitude: 137.3572927368641, // default 0 + latitude: -4.674971631163808, // default 0 + elevation: -4443.613, // default 0 + }, + scale: 10, // default 1 + rotation: { + // y-up is away from planet center. x is pitch, y is yaw, z is roll + x: Math.PI / 12, // in radians | default 0 + y: Math.PI / 2, // default 0 + z: 0, // default 0 + order: 'YXZ', //default YXZ + }, + cache: false, // default true // If true, uses cloned meshes from the first download + }, + () => { + console.log('Rover loaded') + //Litho.setLayerOpacity('roverGLTF', 0.25) + //Litho.removeLayer('roverGLTF') + + //Litho.toggleLayer('roverGLTF', false) + //setTimeout(() => { + // Litho.toggleLayer('roverGLTF', true) + //}, 10000) + + } + ) + */ + /* + Litho.addLayer( + 'model', + { + name: 'roverGLTFArrays', + order: 1, + on: true, + path: + 'http://localhost:8888/Missions/MSL/Data/models/Perseverance.glb', + opacity: 0.5, + isArrayed: true, // default false // if true, position, scale and rotation can be arrays for a series of models layer (at least position must be an array now, performance may suffer) + position: Array.from({ length: 4 }, (v, i) => { + return { + longitude: 137.3572927368641 + (i % 3) * 0.001, // default 0 + latitude: + -4.674971631163808 + Math.floor(i / 3) * 0.001, // default 0 + elevation: -4435, // default 0 + } + }), + + //[ + // { + // longitude: 137.3572927368641, // default 0 + // latitude: -4.674971631163808, // default 0 + // elevation: -4300, // default 0 + // }, + // { + // longitude: 137.3592927368641, // default 0 + // latitude: -4.674971631163808, // default 0 + // elevation: -4300, // default 0 + // }, + // { + // longitude: 137.3612927368641, // default 0 + // latitude: -4.674971631163808, // default 0 + // elevation: -4443.613, // default 0 + // }, + //], + + scale: 10, // default 1 + rotation: { + // y-up is away from planet center. x is pitch, y is yaw, z is roll + x: Math.PI / 12, // in radians | default 0 + y: Math.PI / 2, // default 0 + z: 0, // default 0 + order: 'YXZ', //default YXZ + }, + cache: true, // default true // If true, uses cloned meshes from the first download + }, + () => { + console.log('Rover Array loaded') + //Litho.setLayerOpacity('roverGLTF', 0.25) + //Litho.removeLayer('roverGLTF') + + //Litho.toggleLayer('roverGLTF', false) + //setTimeout(() => { + //Litho.toggleLayer('roverGLTF', true) + //}, 10000) + + } + ) + */ + /* + Litho.addLayer('model', { + name: 'moonOBJ', + order: 1, + on: true, + path: + 'http://localhost:8888/Missions/MSL/Data/models/moon/moon.obj', + mtlPath: + 'http://localhost:8888/Missions/MSL/Data/models/moon/moon.mtl', + opacity: 1, + position: { + longitude: 137.3572927368641, // default 0 + latitude: -4.674971631163808, // default 0 + elevation: -4000, // default 0 + }, + scale: 1, // default 1 + rotation: { + x: 0, // in radians | default 0 + y: 0, // default 0 + z: 0, // default 0 + }, + }) + Litho.addLayer('model', { + name: 'whaleDAE', + order: 1, + on: true, + path: + 'http://localhost:8888/Missions/MSL/Data/models/Killer_Whale.dae', + opacity: 1, + position: { + longitude: 137.3582927368641, // default 0 + latitude: -4.674971631163808, // default 0 + elevation: -4420, // default 0 + }, + scale: 4, // default 1 + rotation: { + x: -Math.PI / 2, // in radians | default 0 + y: 0, // default 0 + z: 0, // default 0 + }, + }) + */ Litho.addControl('myHome', Litho.controls.home) Litho.addControl('myExaggerate', Litho.controls.exaggerate) @@ -489,32 +665,32 @@ onToggle: (isLinked) => {}, onFirstPersonUpdate: () => { /* - const playerll = Litho.getCenter() - L_.Map_.setPlayerArrow( - playerll.lon, - playerll.lat, - (Litho.cameras.firstPerson.controls.getObject().rotation.y % (Math.PI * 2)) + - Math.PI - ) - L_.Map_.setPlayerLookat(Globe_.mouseLngLat.Lng, Globe_.mouseLngLat.Lat) - */ + const playerll = Litho.getCenter() + L_.Map_.setPlayerArrow( + playerll.lon, + playerll.lat, + (Litho.cameras.firstPerson.controls.getObject().rotation.y % (Math.PI * 2)) + + Math.PI + ) + L_.Map_.setPlayerLookat(Globe_.mouseLngLat.Lng, Globe_.mouseLngLat.Lat) + */ }, onOrbitalUpdate: () => { //L_.Map_.hidePlayer() }, }) /* - Map_.map.on('move', (e) => { - const c = Map_.map.getCenter() - myLink.linkMove(c.lng, c.lat) - }) - Map_.map.on('mousemove', (e) => { - myLink.linkMouseMove(e.latlng.lng, e.latlng.lat) - }) - Map_.map.on('mouseout', (e) => { - myLink.linkMouseOut() - }) - */ + Map_.map.on('move', (e) => { + const c = Map_.map.getCenter() + myLink.linkMove(c.lng, c.lat) + }) + Map_.map.on('mousemove', (e) => { + myLink.linkMouseMove(e.latlng.lng, e.latlng.lat) + }) + Map_.map.on('mouseout', (e) => { + myLink.linkMouseOut() + }) + */ diff --git a/examples/exampleProj.html b/examples/exampleProj.html index ee2781a..4d9612a 100644 --- a/examples/exampleProj.html +++ b/examples/exampleProj.html @@ -43,7 +43,7 @@ majorRadius: 1737400, tileMapResource: { // minx, miny, maxx, maxy - bounds: [-1095700 - 1095600, 1095600, 1095700], + bounds: [-1095700, -1095600, 1095600, 1095700], origin: [-1095700, -1095600], crsCode: 'IAU2000:30166,0,-89.9', proj: diff --git a/package.json b/package.json index d2ab960..4fd9ee5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lithosphere", - "version": "1.0.3", + "version": "1.2.0", "description": "LithoSphere is a GIS JavaScript library for building 3D tile-based globes in the web browser.", "author": "Tariq Soliman", "license": "Apache-2.0", @@ -16,6 +16,7 @@ "scripts": { "start": "npm run start:dev", "start:dev": "webpack --mode=development --watch --progress", + "start:docs": "cd ./docs && bundle exec jekyll serve", "build": "npm run build:prod", "build:prod": "webpack --mode=production", "prepublishOnly": "webpack --mode=production", diff --git a/src/core/events.ts b/src/core/events.ts index b578e3a..d36f830 100644 --- a/src/core/events.ts +++ b/src/core/events.ts @@ -96,6 +96,8 @@ export default class Events { }, false ) + + window.addEventListener('keydown', this._onKeyDown, false) //container.addEventListener('click', onGlobeClick, false) //document.addEventListener('click', onGlobeClickPointerLock, false) @@ -397,6 +399,71 @@ export default class Events { } } + private _onKeyDown = (e): void => { + if (this.p._.cameras.isFirstPerson) return + + const speed = e.shiftKey ? 20 : 8 + + switch (e.key) { + case 'w': + case 'ArrowUp': + this._rotateGlobe({ pageX: 0, pageY: speed }, { x: 0, y: 0 }) + break + case 'a': + case 'ArrowLeft': + this._rotateGlobe({ pageX: speed, pageY: 0 }, { x: 0, y: 0 }) + break + case 's': + case 'ArrowDown': + this._rotateGlobe({ pageX: 0, pageY: -speed }, { x: 0, y: 0 }) + break + case 'd': + case 'ArrowRight': + this._rotateGlobe({ pageX: -speed, pageY: 0 }, { x: 0, y: 0 }) + break + case 'g': + case 'PageDown': + const lerpedDown = new Vector3().lerpVectors( + this.p._.cameras.orbit.camera.position, + this.p._.cameras.orbit.controls.target, + e.shiftKey ? -0.035 : -0.02 + ) + this.p._.cameras.orbit.camera.position.set( + lerpedDown.x, + lerpedDown.y, + lerpedDown.z + ) + this._onZoom() + break + case 't': + case 'PageUp': + const lerpedUp = new Vector3().lerpVectors( + this.p._.cameras.orbit.camera.position, + this.p._.cameras.orbit.controls.target, + e.shiftKey ? 0.035 : 0.02 + ) + this.p._.cameras.orbit.camera.position.set( + lerpedUp.x, + lerpedUp.y, + lerpedUp.z + ) + this._onZoom() + break + case 'q': + this.p._.cameras.orbit.controls.rotateLeft(Math.PI / 64) + break + case 'e': + this.p._.cameras.orbit.controls.rotateLeft(-Math.PI / 64) + break + case 'r': + this.p._.cameras.orbit.controls.rotateUp(Math.PI / 64) + break + case 'f': + this.p._.cameras.orbit.controls.rotateUp(-Math.PI / 64) + break + } + } + _onMouseMove = (e?): void => { this.p._.mouseIsInScene = true diff --git a/src/core/projection.ts b/src/core/projection.ts index fee9233..7f8ef6c 100644 --- a/src/core/projection.ts +++ b/src/core/projection.ts @@ -121,7 +121,17 @@ export default class Projection { this.radii.minor = radius || this.radii.major || this.baseRadius } - invertY = (y: number, z: number): number => Math.pow(2, z) - 1 - y + invertY = (y: number, z: number): number => { + const b = this.crs.projection.bounds + if (this.tileMapResource.crsCode === 'EPSG:4326') { + // Map uses default projection + return Math.pow(2, z) - 1 - y + } + const s = this.crs.scale(z) + const max = this.crs.transformation.transform(b.min, s) + const yMax = Math.ceil(max.y / 256) - 1 + return yMax - y + } toBounds = (a: XY, b: XY) => { const bounds = { diff --git a/src/core/shaders.ts b/src/core/shaders.ts index 8358625..f656eed 100644 --- a/src/core/shaders.ts +++ b/src/core/shaders.ts @@ -34,46 +34,98 @@ const Shaders = { 'precision highp float;\n' + '#endif\n' + 'varying vec2 vUv;\n' + - 'attribute vec3 customColor;\n' + - 'varying vec3 vColor;\n' + 'void main() {\n' + 'vUv = uv;\n' + - 'vColor = customColor;\n' + 'vec4 mvPosition = viewMatrix * modelMatrix * vec4(position, 1.0);\n' + 'gl_Position = projectionMatrix * mvPosition;\n' + '}' let baseShaderFrag = - '#ifdef GL_ES\n' + 'precision highp float;\n' + '#endif\n' + `${getColorSpaceFunctions()}\n\n` + + '#ifdef GL_ES\n' + + 'precision highp float;\n' + + '#endif\n' for (let i = 0; i < numberOfTextures; i++) { // prettier-ignore baseShaderFrag += 'uniform sampler2D t' + i + ';\n' + 'uniform float tA' + i + ';\n' + - 'uniform float tVAT' + i + ';\n' + 'uniform float fbrightness' + i + ';\n' + + 'uniform float fcontrast' + i + ';\n' + + 'uniform float fsaturation' + i + ';\n' + + 'uniform float fblendCode' + i + ';\n' } // prettier-ignore baseShaderFrag += 'varying vec2 vUv;\n' + - 'varying vec3 vColor;\n' + + 'float sat;\n' + + 'float x;\n' + + 'float y;\n' + + 'vec4 Csat;\n' + // saturation related + 'vec3 backdropHSL;\nvec3 currentHSL;\n' + // color blend related 'void main(void) {\n' + - 'vec4 C;\n' + - 'vec4 B = vec4(0,0,0,0);\n' + //transparent base layer - 'vec4 C0 = texture2D(t0, vUv);\n' + - 'float highestA = tA0;\n' - - baseShaderFrag += - 'C = vec4( C0.rgb * (C0.a * tA0) + B.rgb * B.a * (1.0 - (C0.a * tA0)), 1);\n' // blending equation - for (let i = 1; i < numberOfTextures; i++) { + 'vec4 C = vec4(0,0,0,0);\n' //transparent base layer + // This will be our base alpha + let highestA = 0 + for (let i = 0; i < numberOfTextures; i++) { // prettier-ignore baseShaderFrag += - 'if ( tVAT' + i + ' == 0.0 && tA' + i +' > highestA ){ highestA = tA' + i + '; }\n' + - 'vec4 C' + i + ' = texture2D(t' + i + ', vUv);\n' + - 'C = vec4( C' + i + '.rgb * (C' + i + '.a * tA' + i + ') + C.rgb * C.a * (1.0 - (C' + i + '.a * tA' + i + ')), 1);\n' + `vec4 C${i} = texture2D(t${i}, vUv);\n` + + (( textures[i].isVAT === 0) ? + (( i > 0 ) ? + // Color Blend + `if (fblendCode${i} == 2.0) {\n` + + `backdropHSL = RGBtoHSL(C.rgb);\n` + + `currentHSL = RGBtoHSL(C${i}.rgb);\n` + + `currentHSL.z = backdropHSL.z;\n` + + `C${i}.rgb = HSLtoRGB(currentHSL);\n` + + `}\n` + : '') + + // Apply Contrast + `C${i}.rgb = ((C${i}.rgb - 0.5f) * max(fcontrast${i}, 0.0f)) + 0.5f;\n` + + // Apply Brightness + `C${i}.rgb *= fbrightness${i};\n` + + // Apply Saturation + `sat = fsaturation${i} - 1.0f;\n` + + `x = sat * (2.0f / 3.0f) + 1.0f;\n` + + `y = (x - 1.0f) * -0.5f;\n` + + `Csat = C${i};\n` + + `C${i}.r = Csat.r * x + Csat.g * y + Csat.b * y;\n` + + `C${i}.g = Csat.r * y + Csat.g * x + Csat.b * y;\n` + + `C${i}.b = Csat.r * y + Csat.g * y + Csat.b * x;\n` + + (( i > 0 ) ? + // Overlay Blend + `if (fblendCode${i} == 1.0) {\n` + + `if (C${i}.r < 0.5f) {\n` + + `C${i}.r = 2.0f * C${i}.r * C.r;\n` + + `} else {\n` + + `C${i}.r = 1.0f - (2.0f * (1.0f - C.r) * (1.0f - C${i}.r));\n` + + `}\n` + + `if (C${i}.g < 0.5f) {\n` + + `C${i}.g = 2.0f * C${i}.g * C.g;\n` + + `} else {\n` + + `C${i}.g = 1.0f - (2.0f * (1.0f - C.g) * (1.0f - C${i}.g));\n` + + `}\n` + + `if (C${i}.b < 0.5f) {\n` + + `C${i}.b = 2.0f * C${i}.b * C.b;\n` + + `} else {\n` + + `C${i}.b = 1.0f - (2.0f * (1.0f - C.b) * (1.0f - C${i}.b));\n` + + `}\n` + + `}\n` + : '') + : '') + + // prettier-ignore + `C = vec4( C${i}.rgb * (C${i}.a * tA${i}) + C.rgb * C.a * (1.0 - (C${i}.a * tA${i})), 1);\n` + + // Find highest alpha of non-vector-as-tile-layers (VAT) too + if (textures[i].isVat === 0 && textures[i].opacity > highestA) + highestA = textures[i].opacity } + if (highestA === 0) highestA = 1 + // discard if all transparent baseShaderFrag += 'if (' for (let i = 0; i < numberOfTextures; i++) { baseShaderFrag += ' C' + i + '.a == 0.0' @@ -86,13 +138,8 @@ const Shaders = { '){\n' + 'discard;\n' + '}\n' + - 'if (vColor.r * vColor.g * vColor.b == 1.0){\n' + - 'discard;\n' + - '}\n' + - 'if (!(vColor.r == 0.0 && vColor.g == 0.0 && vColor.b == 0.0)){\n' + - 'C = vec4(vColor, 1);\n' + - '}\n' + - 'C.a = highestA;\n' + + + `C.a = ${highestA.toFixed(1)}f;\n` + 'gl_FragColor = C;\n' + '}' @@ -101,7 +148,16 @@ const Shaders = { for (let i = 0; i < numberOfTextures; i++) { uniforms['t' + i] = { value: textures[i].texture } uniforms['tA' + i] = { value: fadeIn ? 0 : textures[i].opacity } - uniforms['tVAT' + i] = { value: textures[i].isVAT } + uniforms['fbrightness' + i] = { + value: textures[i].filters.brightness, + } + uniforms['fcontrast' + i] = { value: textures[i].filters.contrast } + uniforms['fsaturation' + i] = { + value: textures[i].filters.saturation, + } + uniforms['fblendCode' + i] = { + value: textures[i].filters.blendCode, + } } //Now make the material @@ -184,4 +240,58 @@ const Shaders = { }, } +function getColorSpaceFunctions() { + // prettier-ignore + return [ + 'vec3 RGBtoHSL(in vec3 RGB) {\n', + 'float cMax = max(max(RGB.r, RGB.g), RGB.b);\n', + 'float cMin = min(min(RGB.r, RGB.g), RGB.b);\n', + 'float delta = cMax - cMin;\n', + + 'float lightness = (cMax + cMin) / 2.0f;\n', //(0.299f*RGB.r + 0.587f*RGB.g + 0.114f*RGB.b);\n', + + 'float hue = 0.0f;\n', + 'if (delta == 0.0f) {\n', + 'hue = 0.0f;\n', + '}\n', + 'else if (cMax == RGB.r) {\n', + 'hue = (60.0f / 360.0f) * mod((RGB.g - RGB.b) / delta , 6.0f);\n', + '}\n', + 'else if (cMax == RGB.g) {\n', + 'hue = (60.0f / 360.0f) * (((RGB.b - RGB.r) / delta) + 2.0f);\n', + '}\n', + 'else if (cMax == RGB.b) {\n', + 'hue = (60.0f / 360.0f) * (((RGB.r - RGB.g) / delta) + 4.0f);\n', + '}\n', + + 'float saturation = 0.0f;\n', + 'if (delta > 0.0f) {\n', + 'saturation = delta / (1.0f - abs((2.0f * lightness) - 1.0f));\n', + '}\n', + + 'return vec3(hue, saturation, lightness);\n', + '}', + 'vec3 HSLtoRGB(in vec3 HSL) {', + 'float C = (1.0f - abs((2.0f * HSL.z) - 1.0f)) * HSL.y;\n', + 'float X = C * (1.0f - abs(mod(HSL.x / (60.0f / 360.0f), 2.0f) - 1.0f));\n', + 'float m = HSL.z - C / 2.0f;\n', + 'vec3 rgb;\n', + 'if (HSL.x < (60.0f / 360.0f)) {\n', + 'rgb = vec3(C, X, 0);\n', + '} else if (HSL.x < (120.0f / 360.0f)) {\n', + 'rgb = vec3(X, C, 0);\n', + '} else if (HSL.x < (180.0f / 360.0f)) {\n', + 'rgb = vec3(0, C, X);\n', + '} else if (HSL.x < (240.0f / 360.0f)) {\n', + 'rgb = vec3(0, X, C);\n', + '} else if (HSL.x < (300.0f / 360.0f)) {\n', + 'rgb = vec3(X, 0, C);\n', + '} else {\n', + 'rgb = vec3(C, 0, X);\n', + '}\n', + 'return vec3(rgb.r + m, rgb.g + m, rgb.b + m);\n', + '}', + ].join('\n') +} + export default Shaders diff --git a/src/core/tiledWorld.ts b/src/core/tiledWorld.ts index 13c3223..0f16079 100644 --- a/src/core/tiledWorld.ts +++ b/src/core/tiledWorld.ts @@ -168,6 +168,8 @@ export default class TiledWorld { } if (percent) percent.innerHTML = this.tilesToBeDrawn.length + // Adjust brightness, contrast, blend, &c. + this.filterEffects() //Fade in existing tiles // Tile by default start at 0 opacity and increase until the set opacity this.fadeInTiles() @@ -497,9 +499,8 @@ export default class TiledWorld { colors[p] = 0 colors[p + 1] = 0 colors[p + 2] = 0 - if (height < -100000) { - height = -100000 - } + height = Math.min(height, 100000) + height = Math.max(height, -100000) const tx = xyz.x + @@ -739,6 +740,13 @@ export default class TiledWorld { texture: textures[i].texture, opacity: textures[i].opacity, isVAT: 0, + filters: { + brightness: 1, + contrast: 1, + saturation: 1, + blendCode: 0, //0 = none, 1 = overlay, 2 = color + blend: 0, + }, i: orderingI, }) orderingI++ @@ -752,6 +760,13 @@ export default class TiledWorld { texture: textures[i].texture, opacity: textures[i].opacity, isVAT: 1, + filters: { + brightness: 1, + contrast: 1, + saturation: 1, + blendCode: 0, //0 = none, 1 = overlay, 2 = color + blend: 0, + }, i: orderingI, }) orderingI++ @@ -1048,6 +1063,61 @@ export default class TiledWorld { } } + // Smoothly transitions filter effects + filterEffects(): void { + const transitionFilters = [ + 'brightness', + 'contrast', + 'saturation', + 'blendCode', + ] + for (const m in this.tilesDrawn) { + for (const n in this.tilesDrawn[m].from.rasters) { + if ( + this.tilesDrawn[m] && + this.tilesDrawn[m].t && + this.tilesDrawn[m].t.material.hasOwnProperty('uniforms') + ) { + const layer = this.p.layers.getLayerByName( + this.tilesDrawn[m].from.rasters[n].name + ) + if (layer && layer.filters) { + // Brightness + transitionFilters.forEach((f) => { + const desiredFilter = layer.filters[f] + if (desiredFilter == null) return + const currentFilter = this.tilesDrawn[m].t.material + .uniforms[`f${f}${n}`].value + if (f == 'blendCode') { + this.tilesDrawn[m].t.material.uniforms[ + `f${f}${n}` + ].value = desiredFilter + } else if (desiredFilter > currentFilter) { + this.tilesDrawn[m].t.material.uniforms[ + `f${f}${n}` + ].value = Math.min( + this.tilesDrawn[m].t.material.uniforms[ + `f${f}${n}` + ].value + 0.1, + desiredFilter + ) + } else { + this.tilesDrawn[m].t.material.uniforms[ + `f${f}${n}` + ].value = Math.max( + this.tilesDrawn[m].t.material.uniforms[ + `f${f}${n}` + ].value - 0.1, + desiredFilter + ) + } + }) + } + } + } + } + } + // Will also need to set initial multi-shader uniform opacity to 0 fadeInTiles(): void { for (const m in this.tilesDrawn) { diff --git a/src/layers/clamped.ts b/src/layers/clamped.ts index bcf780c..096ace1 100644 --- a/src/layers/clamped.ts +++ b/src/layers/clamped.ts @@ -134,11 +134,11 @@ export default class ClampedLayerer { if (this.p.clamped[i].name == name) { const minZoom = this.p.clamped[i].minZoom const maxZoom = this.p.clamped[i].maxZoom + this.p.clamped.splice(i, 1) if (this.p.p.zoom >= minZoom && this.p.p.zoom <= maxZoom) { this.p.p._.tiledWorld.killDrawingTiles() this.p.p._.tiledWorld.updateAllRasters() } - this.p.clamped.splice(i, 1) return true } } @@ -451,7 +451,7 @@ export default class ClampedLayerer { // Compute radius in meters const lnglatRadiusAway = this.p.p.projection.tileXYZ2LatLng( - x + style.radius / canvas.width, + x + (style.radius + ctx.lineWidth) / canvas.width, y, this.p.p.zoom ) @@ -467,6 +467,76 @@ export default class ClampedLayerer { // @ts-ignore const canvasY = parseInt((y - xyz.y) * canvas.height) + // Bearing is a triangle indicating direction + if (c.style?.bearing) { + const unit = c.style.bearing.angleUnit || 'deg' + const bearingProp = + c.style.bearing.angleProp || false + + let yaw = 0 + if (bearingProp !== false) { + yaw = parseFloat( + Utils.getIn(f.properties, bearingProp, 0) + ) + if (unit === 'deg') { + yaw = yaw * (Math.PI / 180) + } + } + yaw += Math.PI + + const startingPoint = Utils.rotatePoint( + { + x: canvasX, + y: + canvasY + + style.radius + + ctx.lineWidth - + 2, + }, + [canvasX, canvasY], + yaw - 45 * (Math.PI / 180) + ) + const indicator = [ + Utils.rotatePoint( + { + x: canvasX, + y: canvasY + style.radius * 2, + }, + [canvasX, canvasY], + yaw + ), + Utils.rotatePoint( + { + x: canvasX, + y: + canvasY + + style.radius + + ctx.lineWidth - + 2, + }, + [canvasX, canvasY], + yaw + 45 * (Math.PI / 180) + ), + startingPoint, + ] + + ctx.fillStyle = c.style.bearing.color || 'red' + ctx.lineWidth = (1 / scaleFactor) * 1 + + ctx.beginPath() + ctx.moveTo(startingPoint.x, startingPoint.y) + indicator.forEach((ind) => { + ctx.lineTo(ind.x, ind.y) + }) + ctx.closePath() + ctx.fill() + ctx.stroke() + + ctx.fillStyle = style.fillColor + ctx.lineWidth = + style.weight * ((1 / scaleFactor) * 1) + } + ctx.beginPath() ctx.arc( canvasX, diff --git a/src/layers/index.ts b/src/layers/index.ts index b62978d..ccc9b19 100644 --- a/src/layers/index.ts +++ b/src/layers/index.ts @@ -4,6 +4,7 @@ import Tile3dLayerer from './tile3d' import TileLayerer from './tile' import ClampedLayerer from './clamped' import VectorLayerer from './vector' +import ModelLayerer from './model' interface Private { layerers: { @@ -11,6 +12,7 @@ interface Private { tile: TileLayerer clamped: ClampedLayerer vector: VectorLayerer + model: ModelLayerer } } @@ -23,6 +25,7 @@ export default class Layers { tile: any clamped: any vector: any + model: any all: any constructor(parent: any) { @@ -40,6 +43,7 @@ export default class Layers { tile: new TileLayerer(this), clamped: new ClampedLayerer(this), vector: new VectorLayerer(this), + model: new ModelLayerer(this), }, } this._reset() @@ -50,6 +54,7 @@ export default class Layers { this.tile = [] this.clamped = [] this.vector = [] + this.model = [] // For convenience // The order here is also used by the layers control @@ -58,6 +63,7 @@ export default class Layers { tile: this.tile, clamped: this.clamped, vector: this.vector, + model: this.model, } } @@ -75,6 +81,8 @@ export default class Layers { if (layerObj.on == 1) layerObj.on = true else if (layerObj.on == 0) layerObj.on = false + layerObj._type = type + if (this._.layerers[type]) this._.layerers[type].add(layerObj, callback) else console.warn(`Cannot add unknown layer type ${type}.`) } @@ -128,6 +136,39 @@ export default class Layers { return true } + setLayerFilterEffect = ( + name: string, + filter: string, + value: number + ): boolean => { + const allowableFilterEffects = [ + 'brightness', + 'contrast', + 'saturation', + 'blendCode', + ] + if (!allowableFilterEffects.includes(filter)) { + console.warn( + `Filter ${filter} must be one of: ${allowableFilterEffects.toString()}.` + ) + return false + } + + const didFilter = this._.layerers.tile.setFilterEffect( + name, + filter, + // @ts-ignore + parseFloat(value) + ) + if (!didFilter) { + console.warn( + `Could not find tile layer named '${name}' to set the filter of.` + ) + return false + } + return true + } + // Helper findHighestMaxZoom = (): number => { let highest = 0 @@ -175,6 +216,10 @@ export default class Layers { return null } + hasLayer = (layerName: string): boolean => { + return this.getLayerByName(layerName) != null + } + // Computes a feature's style given it layer styling configuration // Does fancy things like letting you set style from properties and by properties getFeatureStyle = (layer: any, feature: any, isStrokeless?: boolean) => { @@ -252,11 +297,29 @@ export default class Layers { // Final format if (style.fillColor === 'none') style.fillColor = 'rgba(0,0,0,0)' + const type = feature.geometry?.type + ? feature.geometry.type.toLowerCase() + : '' + // Active && Highlights if (feature._active) { - style.fillColor = this.p.options.activeColor || 'red' + if ( + this.p.options.canBecomeActive !== false && + layer.canBecomeActive !== false && + (layer.style[type] == null || + (layer.style[type] && + layer.style[type].canBecomeActive !== false)) + ) + style.fillColor = this.p.options.activeColor || 'red' } else if (feature._highlighted) { - style.fillColor = this.p.options.highlightColor || 'yellow' + if ( + this.p.options.canBecomeHighlighted !== false && + layer.canBecomeHighlighted !== false && + (layer.style[type] == null || + (layer.style[type] && + layer.style[type].canBecomeHighlighted !== false)) + ) + style.fillColor = this.p.options.highlightColor || 'yellow' } // For lines and what not diff --git a/src/layers/model.ts b/src/layers/model.ts index e69de29..e1c99cf 100644 --- a/src/layers/model.ts +++ b/src/layers/model.ts @@ -0,0 +1,353 @@ +import { Object3D, Vector3, Quaternion } from 'three' +import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js' +import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js' +import { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader.js' +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js' +import Utils from '../utils' + +const objLoader = new OBJLoader() +const mtlLoader = new MTLLoader() +const colladaLoader = new ColladaLoader() +const gltfLoader = new GLTFLoader() + +export default class ModelLayerer { + // parent + p: any + modelCache: any + + constructor(parent: any) { + this.p = parent + this.modelCache = {} + } + + add = (layerObj: any, callback?: Function): void => { + if (!this.p.p._.wasInitialized) return + + let alreadyExists = false + if ( + layerObj.hasOwnProperty('name') && + layerObj.hasOwnProperty('on') && + layerObj.hasOwnProperty('path') + ) { + for (let i = 0; i < this.p.model.length; i++) { + if (this.p.model[i].hasOwnProperty('name')) { + if (this.p.model[i].name == layerObj.name) { + this.p.model[i] = layerObj + alreadyExists = true + break + } + } + } + if (!alreadyExists) { + this.generateModel(layerObj, (model) => { + if (model) { + model = this.localizeModel(layerObj, model) + this.p.p.planet.add(model) + layerObj.model = model + this.p.model.push(layerObj) + this.p.model.sort((a, b) => b.order - a.order) + this.setOpacity(layerObj.name, layerObj.opacity) + } + if (typeof callback === 'function') callback() + }) + } else if (typeof callback === 'function') callback() + } else { + console.warn( + `Attempted to add an invalid model layer: ${layerObj.name}. Required props: name, on, path` + ) + } + } + + toggle = (name: string, on?: boolean): boolean => { + if (!this.p.p._.wasInitialized) return false + + this.p.model.forEach((layer) => { + if (name === layer.name) { + layer.on = on != null ? on : !layer.on + layer.model.visible = layer.on + + return true + } + }) + return false + } + + setOpacity = (name: string, opacity: number): boolean => { + if (!this.p.p._.wasInitialized) return false + + if (opacity == null) opacity = 1 + + for (let i = 0; i < this.p.model.length; i++) { + const layer = this.p.model[i] + if (name === layer.name) { + layer.opacity = Math.max(Math.min(opacity, 1), 0) + Utils.setAllMaterialOpacity(layer.model, layer.opacity) + return true + } + } + return false + } + + remove = (name: string): boolean => { + if (!this.p.p._.wasInitialized) return false + for (let i = 0; i < this.p.model.length; i++) { + if (this.p.model[i].name === name) { + this.p.p.planet.remove(this.p.model[i].model) + this.p.model.splice(i, 1) + return true + } + } + return false + } + + private generateModel = (layerObj: any, callback: Function) => { + const modelType = Utils.getExtension(layerObj.path).toLowerCase() + + if (this.modelCache[layerObj.path]) { + callback(this.modelCache[layerObj.path].clone()) + return + } + + const callback2 = (model) => { + if (model && layerObj.cache !== false) { + this.modelCache[layerObj.path] = model.clone() + } + callback(model) + } + + switch (modelType) { + case 'obj': + this.objToModel(layerObj, callback2) + break + case 'dae': + this.daeToModel(layerObj, callback2) + break + case 'glb': + case 'gltf': + this.gltfToModel(layerObj, callback2) + break + default: + console.warn( + `WARNING - Unsupported model file type: ${modelType} in layer ${layerObj.name}. Must be one of: obj, dae, glb` + ) + callback(false) + } + } + + private objToModel = async (layerObj, callback: Function) => { + if (layerObj.mtlPath) { + mtlLoader.load(layerObj.mtlPath, function (materials) { + const objMtlLoader = new OBJLoader() + objMtlLoader.setMaterials(materials) + materials.preload() + objMtlLoader.load( + layerObj.path, + function (mesh) { + //Done + callback(mesh) + }, + function (xhr) {}, + function (error) { + //Error + console.warn('Failed to load .obj at: ' + layerObj.path) + callback(false) + } + ) + }) + } else { + objLoader.load( + layerObj.path, + function (mesh) { + //Done + callback(mesh) + }, + function (xhr) {}, + function (error) { + //Error + console.warn('Failed to load .obj at: ' + layerObj.path) + callback(false) + } + ) + } + } + + private daeToModel = (layerObj, callback: Function, options?: any) => { + options = options || {} + + colladaLoader.load( + layerObj.path, + function (mesh) { + //Done + callback(mesh.scene) + }, + function (xhr) {}, + function (error) { + //Error + console.warn('Failed to load .dae at: ' + layerObj.path) + callback(false) + } + ) + } + + private gltfToModel = async (layerObj, callback: Function) => { + gltfLoader.load( + layerObj.path, + function (mesh) { + //Done + callback(mesh.scene) + }, + function (xhr) { + //Progress + /* + if (xhr.total > 0) + console.log( + `${layerObj.path}: (xhr.loaded / xhr.total) * 100 + '% loaded!` + ) + */ + }, + function (error) { + //Error + console.warn('Failed to load gltf at: ' + layerObj.path) + callback(false) + } + ) + } + + // Sets model position, scale, rotation, &c. + private localizeModel = (layerObj, model) => { + const parentMesh = new Object3D() + let position + let rotation + let scale + if (layerObj.isArrayed) { + let models = [] + for (let i = 0; i < layerObj.position.length; i++) { + const modelC = model.clone() + const lng = + layerObj.position[i].longitude || + layerObj.position[i].lng || + 0 + const lat = + layerObj.position[i].latitude || + layerObj.position[i].lat || + 0 + const elev = + (layerObj.position[i].elevation || + layerObj.position[i].elev || + 0) * this.p.p.options.exaggeration + const pos = this.p.p.projection.lonLatToVector3(lng, lat, elev) + modelC.position.set(pos.x, pos.y, pos.z) + + const quaternion = new Quaternion() + quaternion.setFromUnitVectors( + new Vector3(0, 1, 0), + new Vector3(pos.x, pos.y, pos.z).normalize() + ) + modelC.applyQuaternion(quaternion) + modelC.rotateY(-lng * (Math.PI / 180)) + + if (layerObj.rotation) { + const rotation = + layerObj.rotation.length != null + ? layerObj.rotation.length > i + ? layerObj.rotation[i] + : layerObj.rotation[ + layerObj.rotation.length - 1 + ] + : layerObj.rotation + + let order = rotation.order || 'YXZ' + if (order.length != 3) { + console.warn( + `Lithosphere: Warning - Model Layer "${layerObj.name}" has an invalid rotation.order. Defaulting back to 'YXZ'` + ) + order = 'YXZ' + } + modelC.rotation.order = order + order.split('').forEach((axis) => { + switch (axis) { + case 'X': + modelC.rotateX(rotation.x || 0) + break + case 'Y': + modelC.rotateY(-rotation.y || 0) + break + case 'Z': + modelC.rotateZ(rotation.z || 0) + break + default: + console.warn( + `Lithosphere: Warning - Model Layer "${layerObj.name}" has an invalid rotation.order axis: ${axis}. Must be one of X, Y, Z` + ) + break + } + }) + } + if (layerObj.scale != null) { + const s = layerObj.scale[i] || layerObj.scale || 1 + modelC.scale.set(s || 1, s || 1, s || 1) + } + + parentMesh.add(modelC) + } + } else { + const lng = + layerObj.position.longitude || layerObj.position.lng || 0 + const lat = layerObj.position.latitude || layerObj.position.lat || 0 + const elev = + (layerObj.position.elevation || layerObj.position.elev || 0) * + this.p.p.options.exaggeration + const pos = this.p.p.projection.lonLatToVector3(lng, lat, elev) + model.position.set(pos.x, pos.y, pos.z) + + const quaternion = new Quaternion() + quaternion.setFromUnitVectors( + new Vector3(0, 1, 0), + new Vector3(pos.x, pos.y, pos.z).normalize() + ) + model.applyQuaternion(quaternion) + model.rotateY(-lng * (Math.PI / 180)) + + if (layerObj.rotation) { + let order = layerObj.rotation.order || 'YXZ' + if (order.length != 3) { + console.warn( + `Lithosphere: Warning - Model Layer "${layerObj.name}" has an invalid rotation.order. Defaulting back to 'YXZ'` + ) + order = 'YXZ' + } + model.rotation.order = order + order.split('').forEach((axis) => { + switch (axis) { + case 'X': + model.rotateX(layerObj.rotation.x || 0) + break + case 'Y': + model.rotateY(-layerObj.rotation.y || 0) + break + case 'Z': + model.rotateZ(layerObj.rotation.z || 0) + break + default: + console.warn( + `Lithosphere: Warning - Model Layer "${layerObj.name}" has an invalid rotation.order axis: ${axis}. Must be one of X, Y, Z` + ) + break + } + }) + } + if (layerObj.scale != null) { + const s = layerObj.scale + model.scale.set(s || 1, s || 1, s || 1) + } + + parentMesh.add(model) + } + + if (layerObj.on == false) { + parentMesh.visible = false + } + + return parentMesh + } +} diff --git a/src/layers/tile.ts b/src/layers/tile.ts index 9eeed6b..3b8ebff 100644 --- a/src/layers/tile.ts +++ b/src/layers/tile.ts @@ -80,6 +80,25 @@ export default class TileLayerer { return false } + setFilterEffect = ( + name: string, + filter: string, + value: number + ): boolean => { + if (!this.p.p._.wasInitialized) return false + + for (let i = 0; i < this.p.tile.length; i++) { + if (this.p.tile[i].hasOwnProperty('name')) { + this.p.tile[i].filters = this.p.tile[i].filters || {} + if (this.p.tile[i].name == name) { + this.p.tile[i].filters[filter] = value + return true + } + } + } + return false + } + remove = (name: string): boolean => { if (!this.p.p._.wasInitialized) return false diff --git a/src/layers/tile3d.ts b/src/layers/tile3d.ts index 8d66c45..8c0d0a2 100644 --- a/src/layers/tile3d.ts +++ b/src/layers/tile3d.ts @@ -1,5 +1,5 @@ import { TilesRenderer } from '3d-tiles-renderer' -import { Vector3, Object3D, MeshBasicMaterial } from 'three' +import { Vector3, Object3D, Quaternion, MeshBasicMaterial } from 'three' import Utils from '../utils' @@ -34,7 +34,6 @@ export default class Tile3dLayerer { } if (!alreadyExists) { const tilesRenderer = this.generateTile3ds(layerObj) - const meshes = tilesRenderer.group const tile3dLayer = new Object3D() // @ts-ignore tile3dLayer.material = new MeshBasicMaterial({ @@ -42,10 +41,10 @@ export default class Tile3dLayerer { opacity: 0.5, color: 0xaaaaaa, }) - tile3dLayer.add(meshes) this.p.p.planet.add(tile3dLayer) - this.localizeTile3ds(layerObj, tilesRenderer) - layerObj.meshes = meshes + const model = this.localizeTile3ds(layerObj, tilesRenderer) + tile3dLayer.add(model) + layerObj.meshes = model layerObj.renderer = tilesRenderer layerObj.tile3dLayer = tile3dLayer this.p.tile3d.push(layerObj) @@ -115,6 +114,66 @@ export default class Tile3dLayerer { } private localizeTile3ds = (layerObj: any, tilesRenderer: any) => { + const parentMesh = new Object3D() + + const lng = layerObj.position.longitude || layerObj.position.lng || 0 + const lat = layerObj.position.latitude || layerObj.position.lat || 0 + const elev = + (layerObj.position.elevation || layerObj.position.elev || 0) * + this.p.p.options.exaggeration + const pos = this.p.p.projection.lonLatToVector3(lng, lat, elev) + tilesRenderer.group.position.set(pos.x, pos.y, pos.z) + + const quaternion = new Quaternion() + quaternion.setFromUnitVectors( + new Vector3(0, 1, 0), + new Vector3(pos.x, pos.y, pos.z).normalize() + ) + tilesRenderer.group.applyQuaternion(quaternion) + tilesRenderer.group.rotateY(-lng * (Math.PI / 180)) + + if (layerObj.rotation) { + let order = layerObj.rotation.order || 'YXZ' + if (order.length != 3) { + console.warn( + `Lithosphere: Warning - Model Layer "${layerObj.name}" has an invalid rotation.order. Defaulting back to 'YXZ'` + ) + order = 'YXZ' + } + tilesRenderer.group.rotation.order = order + order.split('').forEach((axis) => { + switch (axis) { + case 'X': + tilesRenderer.group.rotateX(layerObj.rotation.x || 0) + break + case 'Y': + tilesRenderer.group.rotateY(layerObj.rotation.y || 0) + break + case 'Z': + tilesRenderer.group.rotateZ(layerObj.rotation.z || 0) + break + default: + console.warn( + `Lithosphere: Warning - Model Layer "${layerObj.name}" has an invalid rotation.order axis: ${axis}. Must be one of X, Y, Z` + ) + break + } + }) + } + if (layerObj.scale != null) { + const s = layerObj.scale + tilesRenderer.group.scale.set(s || 1, s || 1, s || 1) + } + + if (layerObj.on == false) { + tilesRenderer.group.visible = false + } + + parentMesh.add(tilesRenderer.group) + return parentMesh + + /* + /// // position const v = this.p.p.projection.lonLatToVector3( layerObj.position.longitude || layerObj.position.lng || 0, @@ -175,5 +234,6 @@ export default class Tile3dLayerer { break } } + */ } } diff --git a/src/lithosphere.ts b/src/lithosphere.ts index 4172b02..e9ba303 100644 --- a/src/lithosphere.ts +++ b/src/lithosphere.ts @@ -34,6 +34,7 @@ interface Private { container: HTMLElement sceneContainer: HTMLElement wasInitialized: boolean + rendererWrapper: any renderer: any cameras: any cameraPositionTarget: number[] @@ -73,6 +74,9 @@ export default class LithoSphere { removeLayer: Function toggleLayer: Function setLayerOpacity: Function + setLayerFilterEffect: Function + getLayerByName: Function + hasLayer: Function addControl: Function removeControl: Function scene: Scene @@ -104,6 +108,7 @@ export default class LithoSphere { container: document.getElementById(containerId), sceneContainer: sceneContainer, wasInitialized: false, + rendererWrapper: null, renderer: null, cameras: null, cameraPositionTarget: null, @@ -113,7 +118,7 @@ export default class LithoSphere { minNativeZoom: 0, loader: new TextureLoader(), raycaster: new Raycaster(), - updateEveryNthRender: 2, + updateEveryNthRender: 1, counters: { update: 0, frame: 0, @@ -168,7 +173,8 @@ export default class LithoSphere { _init(): boolean { // Create the renderer - this._.renderer = new Renderer(this._.sceneContainer).renderer + this._.rendererWrapper = new Renderer(this._.sceneContainer) + this._.renderer = this._.rendererWrapper.renderer // Make sure it was made and set to initialized if (this._.renderer) { @@ -198,6 +204,9 @@ export default class LithoSphere { this.removeLayer = this.layers.removeLayer this.toggleLayer = this.layers.toggleLayer this.setLayerOpacity = this.layers.setLayerOpacity + this.setLayerFilterEffect = this.layers.setLayerFilterEffect + this.getLayerByName = this.layers.getLayerByName + this.hasLayer = this.layers.hasLayer // Initialize Tiled World this._.tiledWorld = new TiledWorld(this) @@ -335,7 +344,7 @@ export default class LithoSphere { this._.counters.update = (this._.counters.update + 1) % this._.updateEveryNthRender if (this._.counters.update === 0) this._update() - else if (!this._.cameras.isFirstPerson) + if (!this._.cameras.isFirstPerson) this._.cameras.orbit.controls.update() this.layers.tile3d.forEach((tile3d) => { @@ -435,6 +444,8 @@ export default class LithoSphere { { pageX: 0, pageY: 0 }, { x: 0.0001, y: 0.0001 } ) + // Just in case canvas width and height messes up in some setups + this._.rendererWrapper.updateSize() setTimeout(() => { // Repositions center diff --git a/src/utils/index.ts b/src/utils/index.ts index 88e3f90..d7b8138 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -289,6 +289,32 @@ const Utils = { isArray(object: any): boolean { return Object.prototype.toString.call(object) === '[object Array]' }, + // Sets a model's direct children's opacities + setChildrenMaterialOpacity(model, opacity: number, recurse?: Function) { + model.children.forEach((mesh) => { + if (mesh.material) { + mesh.material.transparent = true + mesh.material.opacity = opacity + } + if ( + typeof recurse === 'function' && + mesh.children && + mesh.children.length > 0 + ) { + recurse(mesh) + } + }) + }, + // Traverses through all children and children's children, &c. and changes their material opacities + setAllMaterialOpacity(model, opacity): void { + if (model.material) { + model.material.transparent = true + model.material.opacity = opacity + } + Utils.setChildrenMaterialOpacity(model, opacity, (mesh) => { + Utils.setAllMaterialOpacity(mesh, opacity) + }) + }, } export default Utils