diff --git a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/panoramas-mock-data.js b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/panoramas-mock-data.js index ca239c84..e29e47d8 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/panoramas-mock-data.js +++ b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/panoramas-mock-data.js @@ -40,5 +40,51 @@ export const panoramas = reactive({ rotationY: 0, multiply: 3, // #20221223 2 to 3 }, + + // #20230129, v5 shop1 - 大卖场->商超 shop3 - 便利店 + // shop1 - env1 shelf -> v3.5 + // shop1 - env1 empty + // shop1 - env2 freezer + // shop1 - env2 empty + + // shop3 - env1 shelf + { + id: 'UoKkcO', + url: `${api.storePrefix}/v5/panorama/shop3/env1-shelf-4k.jpg`, + urlSmall: `${api.storePrefix}/v5/panorama/shop3/env1-shelf-4k.jpg`, + urlThumb: `${api.storePrefix}/v5/panorama/shop3/env1-shelf-thumb.jpg`, + rotationY: 0, + multiply: 3, + enterZoom: .75, + }, + // { + // id: 'x3e7Ev', + // url: `${api.storePrefix}/v5/panorama/shop3/env1-empty-4k.jpg`, + // urlSmall: `${api.storePrefix}/v5/panorama/shop3/env1-empty-4k.jpg`, + // urlThumb: `${api.storePrefix}/v5/panorama/shop3/env1-empty-thumb.jpg`, + // rotationY: 0, + // multiply: 3, + // enterZoom: .75, + // }, + { + id: 'd7BLLe', + url: `${api.storePrefix}/v5/panorama/shop3/env2-freezer-4k.jpg`, + urlSmall: `${api.storePrefix}/v5/panorama/shop3/env2-freezer-4k.jpg`, + urlThumb: `${api.storePrefix}/v5/panorama/shop3/env2-freezer-thumb.jpg`, + rotationY: 0, + multiply: 3, + enterZoom: .75, + }, + // { + // id: 'VGLCzs', + // url: `${api.storePrefix}/v5/panorama/shop3/env2-empty-4k.jpg`, + // urlSmall: `${api.storePrefix}/v5/panorama/shop3/env2-empty-4k.jpg`, + // urlThumb: `${api.storePrefix}/v5/panorama/shop3/env2-empty-thumb.png`, + // rotationY: 0, + // multiply: 3, + // enterZoom: .75, + // }, + + ], }) \ No newline at end of file diff --git a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/rotSprites-mock-data.js b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/rotSprites-mock-data.js index 84f723c1..cce973c2 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/rotSprites-mock-data.js +++ b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/rotSprites-mock-data.js @@ -1,33 +1,35 @@ import { reactive } from 'vue' import { api } from '../../../shelves-vue/api/baseApi' +export const rotSpritesList = [ + { + id: 'fRwV2h', + name: "c-ada6l", + url: `${api.storePrefix}/rotSprite/fRwV2h/c-ada61/pano_$2.webp`, + urlSmall: `${api.storePrefix}/rotSprite/fRwV2h/c-ada61/pano_$2.webp`, + urlThumb: `${api.storePrefix}/rotSprite/fRwV2h/c-ada61/pano_00.webp`, + rsFrames: 36, + rsClockwise: true, + rsFirstRotY: -30, + rsWidth: 5.8, // 5m*1200/1034 + rsHeight: 3.8, // 800/1200 + rsCenterY: .26, // 214/800 + }, + { + id: 'LR2fN8', + name: "c-bca", + url: `${api.storePrefix}/rotSprite/LR2fN8/c-bca/pano_$2.webp`, + urlSmall: `${api.storePrefix}/rotSprite/LR2fN8/c-bca/pano_$2.webp`, + urlThumb: `${api.storePrefix}/rotSprite/LR2fN8/c-bca/pano_00.webp`, + rsFrames: 36, + rsClockwise: true, + rsFirstRotY: -30, + rsWidth: 4.78, // 4.6m*1200/1155 + rsHeight: 3.19, // 800/1200 + rsCenterY: .27, // 218/800 + }, +] + export const rotSprites = reactive({ - list: [ - { - id: 'fRwV2h', - name: "c-ada6l", - url: `${api.storePrefix}/rotSprite/fRwV2h/c-ada61/pano_$2.webp`, - urlSmall: `${api.storePrefix}/rotSprite/fRwV2h/c-ada61/pano_$2.webp`, - urlThumb: `${api.storePrefix}/rotSprie/fRwV2h/c-ada61/pano_00.webp`, - rsFrames: 36, - rsClockwise: true, - rsFirstRotY: -30, - rsWidth: 5.8, // 5m*1200/1034 - rsHeight: 3.8, // 800/1200 - rsCenterY: .26, // 214/800 - }, - { - id: 'LR2fN8', - name: "c-cba", - url: `${api.storePrefix}/rotSprite/LR2fN8/c-cba/pano_$2.webp`, - urlSmall: `${api.storePrefix}/rotSprite/LR2fN8/c-cba/pano_$2.webp`, - urlThumb: `${api.storePrefix}/rotSprie/LR2fN8/c-cba/pano_00.webp`, - rsFrames: 36, - rsClockwise: true, - rsFirstRotY: -30, - rsWidth: 4.78, // 4.6m*1200/1155 - rsHeight: 3.19, // 800/1200 - rsCenterY: .27, // 218/800 - }, - ] + list: rotSpritesList }) \ No newline at end of file diff --git a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/shelves-mock-data.js b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/shelves-mock-data.js index 99e92d46..7769e18e 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/shelves-mock-data.js +++ b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/shelves-mock-data.js @@ -13,7 +13,9 @@ export const shelves = reactive({ // cols: 3, url: `${api.storePrefix}/shelf/cpIvDZ/shelf-1.glb`, urlThumb: `${api.storePrefix}/shelf/cpIvDZ/shelf-1.png`, - cells: shelf1_cells + // cells: shelf1_cells, // #20230117 + cells: [], + originCells: shelf1_cells, }, { id: 'Ik40of', @@ -21,7 +23,9 @@ export const shelves = reactive({ // cols: 3, url: `${api.storePrefix}/shelf/Sl28gs/shelf-2.glb`, urlThumb: `${api.storePrefix}/shelf/Sl28gs/shelf-2.png`, - cells: shelf2_cells + // cells: shelf2_cells, // #20230117 + cells: [], + originCells: shelf2_cells, }, // #20220912, v3.5 @@ -29,7 +33,9 @@ export const shelves = reactive({ id: 'ULDcMg', url: `${api.storePrefix}/v3.5/shelf/shelf-ghost-1.glb`, urlThumb: `${api.storePrefix}/v3.5/shelf/shelf-ghost-1.png`, - cells: shelf3_cells, + // cells: shelf3_cells, // #20230117 + cells: [], + originCells: shelf3_cells, hideWhenSurvey: true, }, diff --git a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/wares-mock-data.js b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/wares-mock-data.js index ffa5e086..aee6fc0b 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/wares-mock-data.js +++ b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/mock-data/wares-mock-data.js @@ -53,6 +53,12 @@ export const wares_v3_5_ = [ // #20220716, 增加 type // type := 0, 由 commodity + texture 构成 // type := 1, 由内嵌的commodity构成, 模型可以自己带有texture, 简化整个流程 +// #20230129, +// type := 21, rotSprite +import { rotSpritesList } from './rotSprites-mock-data' +rotSpritesList.forEach(itm=>{ + itm.type = 21 +}) let list = [ { @@ -161,5 +167,8 @@ let list = [ // #20220912, v3.5 for v3.4 list = list.concat(wares_v3_5_) +// #20230129, wares + rotSprites +list = list.concat(rotSpritesList) + export const wares = reactive({ list }) diff --git a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/shelves-test-data.js b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/shelves-test-data.js index 8f8bf3fa..ecfb6620 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue-demo/api/shelves-test-data.js +++ b/src/views/Creative/3d/crossyo/shelves-vue-demo/api/shelves-test-data.js @@ -3,6 +3,8 @@ // export const DATA_VERSION = 3.5 import shopPanoData1 from './mock-data/data/shop-pano-data-1.json' +// import shopPanoData1 from './mock-data/data/shop-pano-data-230112bug.json' // и͹λ޷Ʒ + import shopHallData1 from './mock-data/data/shop-hall-data-1.json' // surveyId:5z3ouolx diff --git a/src/views/Creative/3d/crossyo/shelves-vue-demo/index.vue b/src/views/Creative/3d/crossyo/shelves-vue-demo/index.vue index e0391cc2..c8e4212c 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue-demo/index.vue +++ b/src/views/Creative/3d/crossyo/shelves-vue-demo/index.vue @@ -25,7 +25,7 @@ body { /* font-family: "Microsoft YaHei"; */ /* font-family: monospace; */ - font-family: "Microsoft YaHei"; + font-family: "PingFang SC", "Microsoft Yahei"; } /* Works on Firefox */ @@ -397,6 +397,65 @@ body { background: none; } +.ant-tree { + font-size: 13px; + font-weight: 600; + letter-spacing: 2px; + color: #434343; + /* direction: rtl; + text-align: left; */ +} + +.ant-tree>li:last-child { + padding-bottom: 0; +} + +.ant-tree>li:first-child { + padding-top: 0; +} + +.ant-tree-child-tree>li:first-child { + padding-top: 16px; +} + +.ant-tree-child-tree .ant-tree-title { + padding-left: 10px; +} + +.ant-tree li { + padding: 8px 0; +} + +.ant-tree li .ant-tree-node-content-wrapper { + font-size: 13px; + font-weight: 600; + letter-spacing: 2px; + color: #434343; + /* padding: 0; */ +} + +.ant-tree li ul { + margin: 0; + padding: 0; +} + +.ant-tree li .ant-tree-node-content-wrapper.ant-tree-node-selected { + background-color: #DFF4D0; +} + +.ant-tree li span.ant-tree-switcher { + float: right; +} + +.ant-tree li span.ant-tree-switcher span { + font-size: 14px !important; + color: #434343; +} + +.ant-tree li span.ant-tree-iconEle img { + width: 100%; + height: 100%; +} .ant-divider { color: #F5F5F5; margin: 0; diff --git a/src/views/Creative/3d/crossyo/shelves-vue-demo/view/ShopEditorDemo.vue b/src/views/Creative/3d/crossyo/shelves-vue-demo/view/ShopEditorDemo.vue index d7ca9487..8f954646 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue-demo/view/ShopEditorDemo.vue +++ b/src/views/Creative/3d/crossyo/shelves-vue-demo/view/ShopEditorDemo.vue @@ -65,6 +65,8 @@ @remove="removeShelf" /> +
-
@@ -104,7 +105,7 @@ import TabPropPanorama from "../../shelves-vue/components/editor/TabPropPanorama import TabPropHall from "../../shelves-vue/components/editor/TabPropHall.vue" import TabPropShelf from "../../shelves-vue/components/editor/TabPropShelf.vue" import TabPropCellWare from '../../shelves-vue/components/editor/TabPropCellWare.vue' -import TabPropSchema from '../../shelves-vue/components/editor/TabPropSchema.vue' +import TabListSchema from '../../shelves-vue/components/editor/TabListSchema.vue' // import PanoramaUploader from '../../shelves-vue/view/PanoramaUploader.vue' // import ShelfUploader from '../../shelves-vue/view/ShelfUploader.vue' @@ -349,7 +350,21 @@ export default { wareAddSuccess(data) { this.clickThumbWare(data) }, + // + clickSchemaItem(d) { + if (d) { + if (d.hasOwnProperty('cell')) { + this.selectedCell = d.cell + this.activePropName = 'ware' + } else if (d.env0) { + this.activePropName = this.isHall ? 'hall' : 'panorama' + } + + } else { + this.activePropName = null + } + }, }, }; diff --git a/src/views/Creative/3d/crossyo/shelves-vue/asset/icon2/cube.svg b/src/views/Creative/3d/crossyo/shelves-vue/asset/icon2/cube.svg index 8c380122..68b7d672 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue/asset/icon2/cube.svg +++ b/src/views/Creative/3d/crossyo/shelves-vue/asset/icon2/cube.svg @@ -1,17 +1,17 @@ - - + + viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve"> + - - + + diff --git a/src/views/Creative/3d/crossyo/shelves-vue/components/ScenePreviewer.vue b/src/views/Creative/3d/crossyo/shelves-vue/components/ScenePreviewer.vue index 1f8395e7..837a75db 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue/components/ScenePreviewer.vue +++ b/src/views/Creative/3d/crossyo/shelves-vue/components/ScenePreviewer.vue @@ -110,7 +110,7 @@ div.container-previewer-1-:focus { outline: none; } -div.container-previewer-1->>>canvas:focus { +div.container-previewer-1-:deep()canvas:focus { outline: none; } \ No newline at end of file diff --git a/src/views/Creative/3d/crossyo/shelves-vue/components/SceneSeparateTexturePreviewer.vue b/src/views/Creative/3d/crossyo/shelves-vue/components/SceneSeparateTexturePreviewer.vue index 1896b018..cab2dfe9 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue/components/SceneSeparateTexturePreviewer.vue +++ b/src/views/Creative/3d/crossyo/shelves-vue/components/SceneSeparateTexturePreviewer.vue @@ -104,7 +104,7 @@ div.container-previewer-1-:focus { outline: none; } -div.container-previewer-1->>>canvas:focus { +div.container-previewer-1-:deep()canvas:focus { outline: none; } \ No newline at end of file diff --git a/src/views/Creative/3d/crossyo/shelves-vue/components/SceneShopSurveyViewer.vue b/src/views/Creative/3d/crossyo/shelves-vue/components/SceneShopSurveyViewer.vue index 6f99f8a6..f3214026 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue/components/SceneShopSurveyViewer.vue +++ b/src/views/Creative/3d/crossyo/shelves-vue/components/SceneShopSurveyViewer.vue @@ -167,7 +167,7 @@ div.container-viewer-1-:focus { outline: none; } -div.container-viewer-1->>>canvas:focus { +div.container-viewer-1-:deep()canvas:focus { outline: none; } \ No newline at end of file diff --git a/src/views/Creative/3d/crossyo/shelves-vue/components/editor/SceneShopEditor.vue b/src/views/Creative/3d/crossyo/shelves-vue/components/editor/SceneShopEditor.vue index cbff0c86..457f07c2 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue/components/editor/SceneShopEditor.vue +++ b/src/views/Creative/3d/crossyo/shelves-vue/components/editor/SceneShopEditor.vue @@ -304,7 +304,7 @@ div.container-editor-1-:focus { outline: none; } -div.container-editor-1->>>canvas:focus { +div.container-editor-1-:deep()canvas:focus { outline: none; } diff --git a/src/views/Creative/3d/crossyo/shelves-vue/components/editor/TabListSchema.vue b/src/views/Creative/3d/crossyo/shelves-vue/components/editor/TabListSchema.vue new file mode 100644 index 00000000..962d2ac4 --- /dev/null +++ b/src/views/Creative/3d/crossyo/shelves-vue/components/editor/TabListSchema.vue @@ -0,0 +1,121 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/Creative/3d/crossyo/shelves-vue/components/editor/TabPropPanorama.vue b/src/views/Creative/3d/crossyo/shelves-vue/components/editor/TabPropPanorama.vue index e2396d2b..d628db4f 100644 --- a/src/views/Creative/3d/crossyo/shelves-vue/components/editor/TabPropPanorama.vue +++ b/src/views/Creative/3d/crossyo/shelves-vue/components/editor/TabPropPanorama.vue @@ -10,10 +10,10 @@
视觉距离 -
- +
光源样式
diff --git a/src/views/Creative/components/Crossyo3DFrame.vue b/src/views/Creative/components/Crossyo3DFrame.vue index cd24feb3..7a499c1e 100644 --- a/src/views/Creative/components/Crossyo3DFrame.vue +++ b/src/views/Creative/components/Crossyo3DFrame.vue @@ -13,6 +13,7 @@ .crossyo > :slotted(.ui){ /* Works on Firefox */ * { + font-family: "PingFang SC", "Microsoft Yahei"; scrollbar-width: thin; scrollbar-color: #ECECEC rgba(0, 0, 0, 0); } diff --git a/src/views/Creative/lib/shelves.module.js b/src/views/Creative/lib/shelves.module.js index e8e420f7..c929a7c0 100644 --- a/src/views/Creative/lib/shelves.module.js +++ b/src/views/Creative/lib/shelves.module.js @@ -432,7 +432,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"BaseShelve\": () => (/* binding */ BaseShelve),\n/* harmony export */ \"CELL_HIERARCHY\": () => (/* binding */ CELL_HIERARCHY),\n/* harmony export */ \"HIERARCHY_TYPE\": () => (/* binding */ HIERARCHY_TYPE),\n/* harmony export */ \"try_append_shelf_originCells\": () => (/* binding */ try_append_shelf_originCells)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! three */ \"./node_modules/_three@0.139.2@three/build/three.module.js\");\n/* harmony import */ var _common_CommoditiesCache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/CommoditiesCache */ \"./src/crossyo/shelves/common/CommoditiesCache.js\");\n/* harmony import */ var _common_TexturesCache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../common/TexturesCache */ \"./src/crossyo/shelves/common/TexturesCache.js\");\n/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util */ \"./src/crossyo/shelves/common/util.js\");\n/* harmony import */ var _SceneTags__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SceneTags */ \"./src/crossyo/shelves/common/SceneTags.js\");\n/* harmony import */ var kutsi_red_valley_o3d_TextSprite__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! kutsi-red-valley/o3d/TextSprite */ \"./src-kutsi-red-valley/crossyo/kutsi/o3d/TextSprite.js\");\n/* harmony import */ var kutsi_red_valley_o3d_TextPlaneSprite__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! kutsi-red-valley/o3d/TextPlaneSprite */ \"./src-kutsi-red-valley/crossyo/kutsi/o3d/TextPlaneSprite.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst HIERARCHY_TYPE = {\r\n STANDALONE: 1,\r\n INHERITED: 2,\r\n}\r\n\r\nconst CELL_HIERARCHY = HIERARCHY_TYPE.INHERITED\r\n\r\nclass BaseShelve {\r\n\r\n constructor(viewer) {\r\n\r\n this.viewer_ = viewer\r\n this.commodities_cache_ = new _common_CommoditiesCache__WEBPACK_IMPORTED_MODULE_0__.CommoditiesCache(viewer)\r\n this.textures_cache_ = new _common_TexturesCache__WEBPACK_IMPORTED_MODULE_1__.TexturesCache(viewer)\r\n }\r\n\r\n get_texture_url_(texture) {\r\n if (texture) {\r\n return _common_util__WEBPACK_IMPORTED_MODULE_2__.isMobile ? texture.urlSmall : texture.url\r\n } else {\r\n return null\r\n }\r\n }\r\n\r\n get_commodity_url_(commodity) {\r\n if (!_common_util__WEBPACK_IMPORTED_MODULE_2__.isMobile) {\r\n return commodity.url\r\n } else { // mobile\r\n return commodity.urlSmall || commodity.url\r\n }\r\n }\r\n\r\n // 1) 初始加载时\r\n // 2)更新shelf时,例如多列\r\n update_cells_container_(o3d, shelf) {\r\n\r\n console.log('## update_cells_container_', o3d, shelf /* JSON.stringify(shelf) */ )\r\n\r\n // remove clear first!\r\n\r\n //\r\n if (shelf.cells && shelf.cells.length > 0) {\r\n shelf.cells.forEach(cell => {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d = new three__WEBPACK_IMPORTED_MODULE_6__.Object3D()\r\n c_o3d.name = 'cell__'\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.addTag)(c_o3d, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_CELL)\r\n // ext.$c_o3d__ = c_o3d\r\n ext.get_c_o3d__ = () => {\r\n return c_o3d\r\n }\r\n\r\n let box = cell.box\r\n c_o3d.position.set(box.position.x, box.position.y, box.position.z)\r\n c_o3d.rotation.set(box.rotation.x, box.rotation.y, box.rotation.z)\r\n // this.viewer_.mesh_shelf__.add(c_o3d)\r\n o3d.add(c_o3d)\r\n\r\n // console.log('## add cell container', c_o3d)\r\n\r\n })\r\n }\r\n\r\n }\r\n\r\n // for 跟随编辑cell位置后的移动\r\n update_cell_container_e_(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d__ = ext.get_c_o3d__ ? ext.get_c_o3d__() : null\r\n if (c_o3d__) {\r\n\r\n let box = cell.box\r\n c_o3d__.position.set(box.position.x, box.position.y, box.position.z)\r\n c_o3d__.rotation.set(box.rotation.x, box.rotation.y, box.rotation.z)\r\n\r\n }\r\n }\r\n\r\n remove_all_in_shelf_(o3d_shelf) {\r\n\r\n // console.log('remove_all_in_shelf_', mesh_shelf)\r\n (0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.childrenTagToArray)(o3d_shelf, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_CELL).forEach(c=> c.removeFromParent())\r\n\r\n }\r\n\r\n remove_cell_ware_(c_o3d) {\r\n (0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.traverseTagToArray)(c_o3d, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_WARE).forEach(c => c.removeFromParent())\r\n }\r\n\r\n removeWareFromCell(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d__ = ext.get_c_o3d__ ? ext.get_c_o3d__() : null\r\n if (c_o3d__) {\r\n\r\n if (!ext.origin_o3d_url__\r\n && !ext.origin_tex_url__\r\n ) {\r\n console.log('SAME!!')\r\n return\r\n } else {\r\n console.log('REMOVE PREV!!' /*, commodity.url*/, ext.origin_o3d_url__)\r\n // remove previous!\r\n // ext.$c_o3d__.removeFromParent()\r\n // ext.$c_o3d__ = null\r\n\r\n // c_o3d__.removeFromParent()\r\n this.remove_cell_ware_(c_o3d__)\r\n\r\n ext.origin_o3d_url__ = null\r\n ext.$origin_o3d__ = null\r\n ext.origin_tex_url__ = null\r\n ext.$origin_tex__ = null\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n addWareToCell(ware, cell) {\r\n\r\n // #20221229, TEMP, 此处不一定合理\r\n (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.append_default_cell_data_)(cell)\r\n\r\n return new Promise((resolve, reject) => {\r\n\r\n let commodity = ware.commodity\r\n let texture = ware.texture // maybe null!\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d__ = ext.get_c_o3d__ ? ext.get_c_o3d__() : null\r\n // console.log('addWareToCell#c_o3d__', c_o3d__)\r\n if (c_o3d__) {\r\n\r\n if (this.get_commodity_url_(commodity) == ext.origin_o3d_url__\r\n && this.get_texture_url_(texture) == ext.origin_tex_url__\r\n ) {\r\n console.log('SAME!!')\r\n return\r\n } else {\r\n console.log('REMOVE PREV!!', this.get_commodity_url_(commodity), ext.origin_o3d_url__)\r\n // remove previous!\r\n // ext.$c_o3d__.removeFromParent()\r\n // ext.$c_o3d__ = null\r\n\r\n // only remove ware!\r\n // c_o3d__.removeFromParent()\r\n this.remove_cell_ware_(c_o3d__)\r\n\r\n ext.origin_o3d_url__ = null\r\n ext.$origin_o3d__ = null\r\n ext.origin_tex_url__ = null\r\n ext.$origin_tex__ = null\r\n }\r\n\r\n }\r\n\r\n this.commodities_cache_.find(this.get_commodity_url_(commodity)).then(o3d_nt => {\r\n this.textures_cache_.find(texture).then(tex => {\r\n\r\n ext.$origin_tex__ = tex\r\n ext.origin_tex_url__ = this.get_texture_url_(texture)\r\n\r\n let o3d = o3d_nt.clone()\r\n\r\n o3d.name = o3d_nt.name + '-mat'\r\n if (o3d.material) {\r\n o3d.material = o3d.material.clone()\r\n if (tex) {\r\n o3d.material.map = tex\r\n }\r\n } else { // #20220729, mesh in children\r\n o3d.traverse(c => {\r\n if (c.isMesh) {\r\n c.material = c.material.clone() // case 自己上传的独特商品\r\n if (tex) {\r\n console.warn('#20220729, un confirmed path, 291G9J81LO1!')\r\n c.material.map = tex\r\n }\r\n }\r\n })\r\n }\r\n\r\n // ext.$origin_o3d__ = o3d\r\n ext.get_origin_o3d__ = () => {\r\n return o3d\r\n }\r\n ext.origin_o3d_url__ = this.get_commodity_url_(commodity)\r\n\r\n // {\r\n // let c_o3d = new Object3D()\r\n // c_o3d.name = 'cell__'\r\n // // ext.$c_o3d__ = c_o3d\r\n // ext.get_c_o3d__ = () => {\r\n // return c_o3d\r\n // }\r\n\r\n // let box = cell.box\r\n // c_o3d.position.set(box.position.x, box.position.y, box.position.z)\r\n // c_o3d.rotation.set(box.rotation.x, box.rotation.y, box.rotation.z)\r\n // this.viewer_.mesh_shelf__.add(c_o3d)\r\n // }\r\n\r\n this.update_cell_pileNumber_(cell)\r\n\r\n resolve()\r\n }).catch(e => {\r\n reject(e)\r\n })\r\n\r\n }).catch(e => {\r\n reject(e)\r\n })\r\n\r\n })\r\n\r\n }\r\n\r\n // with pile rotation y\r\n update_cell_pileNumber_(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n if (ext.get_c_o3d__) {\r\n\r\n let c_o3d__ = ext.get_c_o3d__()\r\n if (c_o3d__) {\r\n\r\n let old_number = c_o3d__.children.length\r\n let new_number = cell.pileNumber\r\n\r\n console.log('update_pile_number', old_number, new_number)\r\n\r\n const add_tag_ = o3d => {\r\n o3d.traverse(c => {\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.addTag)(c, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_WARE)\r\n })\r\n }\r\n\r\n if (old_number != new_number) {\r\n\r\n // c_o3d__.clear()\r\n this.remove_cell_ware_(c_o3d__)\r\n\r\n let exto = ext.get_origin_o3d__()\r\n // console.log('#exto', exto, c_o3d__)\r\n\r\n let size = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.box3_except_shadow)(exto).getSize(new three__WEBPACK_IMPORTED_MODULE_6__.Vector3())\r\n let sw = size.x\r\n\r\n // if (cell.pileNumber == 6) { // temp for v3.5\r\n // let w = sw * (3 - 1)\r\n // for (let i = 0; i < new_number; i++) {\r\n // let co = exto.clone()\r\n // co.name = exto.name + '-' + i\r\n // if (i < 3) {\r\n // co.position.x = i * sw - w / 2\r\n // co.position.z = sw / 2\r\n // } else {\r\n // co.position.x = (i - 3) * sw - w / 2\r\n // co.position.z = - sw / 2\r\n // }\r\n // c_o3d__.add(co)\r\n // co.rotation.y = cell.pileRotationY * Math.PI / 180\r\n // }\r\n // } else {\r\n // let w = sw * (new_number - 1)\r\n // for (let i = 0; i < new_number; i++) {\r\n // let co = exto.clone()\r\n // co.name = exto.name + '-' + i\r\n // co.position.x = i * sw - w / 2\r\n // c_o3d__.add(co)\r\n // co.rotation.y = cell.pileRotationY * Math.PI / 180\r\n // }\r\n // }\r\n\r\n {// v5 改为总数 0, 2, 4, .. 必然两排方式\r\n\r\n // cell.maxPileNumber__ = 6\r\n // console.log(cell.box)\r\n let cw = cell.box.size.x\r\n cell.maxPileNumber__ = Math.floor(cw / sw) * 2\r\n\r\n let even_number = Math.floor(new_number / 2) * 2\r\n let half_number = even_number / 2\r\n let w = sw * (half_number - 1)\r\n for (let i = 0; i < half_number; i++) {\r\n\r\n let co = exto.clone()\r\n co.name = exto.name + '-' + i * 2\r\n\r\n co.position.x = i * sw - w / 2\r\n co.position.z = sw / 2\r\n c_o3d__.add(co)\r\n co.rotation.y = cell.pileRotationY * Math.PI / 180\r\n add_tag_(co)\r\n\r\n // console.log('#2', exto, co)\r\n\r\n let co2 = exto.clone()\r\n co2.name = exto.name + '-' + (i * 2 + 1)\r\n\r\n co2.position.x = i * sw - w / 2\r\n co2.position.z = - sw / 2\r\n c_o3d__.add(co2)\r\n co2.rotation.y = cell.pileRotationY * Math.PI / 180\r\n add_tag_(co2)\r\n\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n\r\n } else {\r\n console.warn('sk324kFdfkP34k;ls3k!')\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n update_cell_pileRotationY_(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n\r\n if (ext.get_c_o3d__) {\r\n\r\n let c_o3d__ = ext.get_c_o3d__()\r\n if (c_o3d__) {\r\n\r\n // console.log('update_cell_pileRotationY_', c_o3d__, cell.pileRotationY)\r\n c_o3d__.children.forEach(c => {\r\n c.rotation.y = cell.pileRotationY * Math.PI / 180\r\n })\r\n\r\n } else {\r\n console.warn('UIH4329HJPmk023lKQb!')\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n // #20230112, 不同于 SurveyShelve::addLogoPriceToCell\r\n // 由于强制show状态,主要用于编辑器!\r\n update_logo_to_cell_(cell) {\r\n\r\n // console.log('update_logo_to_cell_', cell)\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n if (ext.get_c_o3d__) {\r\n let c_o3d__ = ext.get_c_o3d__()\r\n\r\n // remove logo in container!\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.childrenTagToArray)(c_o3d__, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_LOGO).forEach(c => {\r\n let tex = c.material.map\r\n c.removeFromParent()\r\n // console.log(tex)\r\n tex.dispose()\r\n })\r\n\r\n // 目前编辑\r\n let showLogo = cell.surveyLogo ? true : false\r\n // if (cell.hasOwnProperty('showLogo')) {\r\n // showLogo = cell.showLogo\r\n // }\r\n cell.showLogo = showLogo\r\n if (showLogo) {// logo\r\n let txtLogo = new kutsi_red_valley_o3d_TextSprite__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\r\n depthWrite: true,\r\n depthTest: true,\r\n }, {\r\n text: cell.surveyLogo,\r\n noPerspScale: .028, // .0185 * 1.5,\r\n })\r\n\r\n let logo = null\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // logo = cell.logo\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n logo = cell.box.child.logo\r\n // }\r\n\r\n let logopos = logo.position\r\n if (logopos) {\r\n txtLogo.position.copy(new three__WEBPACK_IMPORTED_MODULE_6__.Vector3(logopos.x, logopos.y, logopos.z))\r\n // } else { // 兼容之前老的logo数据没有position的问题\r\n // let boxpos = cell.box.position\r\n // txtLogo.position.copy(new Vector3(0, .15, 0).add(new Vector3(boxpos.x, boxpos.y, boxpos.z)))\r\n }\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // mesh_shelf.add(txtLogo)\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n\r\n c_o3d__.add(txtLogo)\r\n // { // debug\r\n // let axes = new AxesHelper(.2)\r\n // axes.position.set(logopos.x, logopos.y, logopos.z)\r\n // cell_o3d.add(axes)\r\n // }\r\n\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.addTag)(txtLogo, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_LOGO)\r\n }\r\n\r\n }\r\n }\r\n\r\n // price sign\r\n update_sign_to_cell_(cell) {\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n if (ext.get_c_o3d__) {\r\n let c_o3d__ = ext.get_c_o3d__()\r\n\r\n let showSign = cell.surveyPrice ? true : false\r\n // if (cell.hasOwnProperty('showSign')) {\r\n // showSign = cell.showSign\r\n // }\r\n cell.showSign = showSign\r\n if (showSign) {// sign - price\r\n\r\n let sign = null\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // sign = cell.sign\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n sign = cell.box.child.sign\r\n // }\r\n\r\n // let txtPrice = new TextSprite({\r\n let txtPrice = new kutsi_red_valley_o3d_TextPlaneSprite__WEBPACK_IMPORTED_MODULE_5__.TextPlaneSprite({\r\n depthWrite: true,\r\n depthTest: true,\r\n // 214,202,178 \r\n color: 0xd6cab2, // bg\r\n }, {\r\n textColor: 0x000000,\r\n text: (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.text_price_)(cell.surveyPrice),\r\n center_y: .5,\r\n // noPerspScale: .025,\r\n noPerspScale: .05,\r\n // perpType: PerspType.Persp,\r\n })\r\n\r\n // TODO ..\r\n\r\n let spos = sign.position\r\n txtPrice.position.set(spos.x, spos.y, spos.z)\r\n let srot = sign.rotation\r\n txtPrice.rotation.set(srot.x, srot.y, srot.z)\r\n\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // mesh_shelf.add(txtPrice)\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n // if (c_o3d__) {\r\n c_o3d__.add(txtPrice)\r\n // { // debug\r\n // let axes = new AxesHelper(.2)\r\n // axes.position.set(spos.x, spos.y, spos.z)\r\n // cell_o3d.add(axes)\r\n // }\r\n // }\r\n // }\r\n\r\n }\r\n\r\n }\r\n }\r\n\r\n dispose() {\r\n this.commodities_cache_.dispose()\r\n this.textures_cache_.dispose()\r\n }\r\n\r\n}\r\n\r\n\r\n// TEMP for v1 to v3, 解些老的数据,并且生成新的cells数据,copy to store/shelves 列表中\r\nconst parse_v3_cells_from_v1_shelf_model_ = o3d => {\r\n\r\n console.log('## parse_v3_cells_from_v1_shelf_model_', o3d)\r\n\r\n let boxes = []\r\n let signs = []\r\n o3d.traverse(c => {\r\n if (/^box-\\d-\\d/.test(c.name)) {\r\n // console.log(c)\r\n boxes.push(c)\r\n } else if (/^sign-\\d-\\d/.test(c.name)) {\r\n // console.log(c)\r\n signs.push(c)\r\n }\r\n })\r\n if (boxes.length != signs.length) {\r\n console.warn('boxes len != signs len')\r\n return\r\n }\r\n boxes.sort((a, b) => {\r\n return a.name.localeCompare(b.name)\r\n })\r\n signs.sort((a, b) => {\r\n return a.name.localeCompare(b.name)\r\n })\r\n\r\n // console.log(boxes, signs)\r\n\r\n let to_box_scale_ = (t, box) => {\r\n // console.log('box', box, box.geometry.boundingBox, box.geometry.boundingBox.getSize(new Vector3()))\r\n t.size = box.geometry.boundingBox.getSize(new three__WEBPACK_IMPORTED_MODULE_6__.Vector3())\r\n // console.log(t)\r\n return t\r\n }\r\n\r\n let cells = []\r\n for (let i = 0; i < boxes.length; i++) {\r\n let box = boxes[i]\r\n let sign = signs[i]\r\n\r\n // let bbx1 = box.geometry.boundingBox\r\n // bbx1.applyMatrix4(box.matrix)\r\n\r\n let cell = {\r\n name: box.name.substr(4),\r\n // 底面中心\r\n box: to_box_scale_((0,_common_util__WEBPACK_IMPORTED_MODULE_2__.to_transform)(box), box),\r\n }\r\n\r\n if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // 中心\r\n cell.sign = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.to_transform)(sign)\r\n cell.sign.position.z += .01\r\n cell.logo = { // #20220611\r\n position: {\r\n x: box.position.x,\r\n y: box.position.y + .15,\r\n z: box.position.z\r\n }\r\n }\r\n } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n\r\n let t_sign = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.to_transform)(sign)\r\n t_sign.position.x -= cell.box.position.x\r\n t_sign.position.y -= cell.box.position.y\r\n t_sign.position.z -= cell.box.position.z\r\n t_sign.position.z += .01\r\n\r\n t_sign.rotation.x = t_sign.rotation.y = t_sign.rotation.z = 0\r\n\r\n cell.box.child = {\r\n sign: t_sign,\r\n logo: { // #20220611\r\n position: {\r\n x: box.position.x - cell.box.position.x,\r\n y: box.position.y + .15 - cell.box.position.y,\r\n z: box.position.z - cell.box.position.z,\r\n },\r\n },\r\n }\r\n\r\n }\r\n\r\n (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.append_default_cell_data_)(cell)\r\n\r\n cells.push(cell)\r\n }\r\n\r\n return cells\r\n}\r\n\r\n// #20230117, 主要调用移至上传流程,此处对于上传流程的修补\r\nconst try_append_shelf_originCells = (o3d, shelf0) => {\r\n // TEMP for v1 to v3, 解些老的数据,并且生成新的cells数据,copy to store/shelves 列表中\r\n // if (!shelf0.cells || shelf0.cells.length == 0) \r\n if (!shelf0.originCells) { // 可以尝试用modelCells覆盖一下\r\n // v5 比较 cells 中是否有数据,如果没有,则运行 parse v3 cell 并且打印到日志中\r\n\r\n // this.shopData_.shelf.cells = \r\n let cells = parse_v3_cells_from_v1_shelf_model_(o3d)\r\n if (cells && cells.length > 0) {\r\n shelf0.originCells = cells\r\n\r\n let s_cells = JSON.stringify(cells)\r\n console.log('发现模型中含有cells数据覆盖至originCells\\n', s_cells)\r\n\r\n }\r\n }\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://shelves/./src/crossyo/shelves/common/BaseShelve.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"BaseShelve\": () => (/* binding */ BaseShelve),\n/* harmony export */ \"CELL_HIERARCHY\": () => (/* binding */ CELL_HIERARCHY),\n/* harmony export */ \"HIERARCHY_TYPE\": () => (/* binding */ HIERARCHY_TYPE),\n/* harmony export */ \"try_append_shelf_originCells\": () => (/* binding */ try_append_shelf_originCells)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! three */ \"./node_modules/_three@0.139.2@three/build/three.module.js\");\n/* harmony import */ var _common_CommoditiesCache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../common/CommoditiesCache */ \"./src/crossyo/shelves/common/CommoditiesCache.js\");\n/* harmony import */ var _common_TexturesCache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../common/TexturesCache */ \"./src/crossyo/shelves/common/TexturesCache.js\");\n/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util */ \"./src/crossyo/shelves/common/util.js\");\n/* harmony import */ var _SceneTags__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SceneTags */ \"./src/crossyo/shelves/common/SceneTags.js\");\n/* harmony import */ var kutsi_red_valley_o3d_TextSprite__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! kutsi-red-valley/o3d/TextSprite */ \"./src-kutsi-red-valley/crossyo/kutsi/o3d/TextSprite.js\");\n/* harmony import */ var kutsi_red_valley_o3d_TextPlaneSprite__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! kutsi-red-valley/o3d/TextPlaneSprite */ \"./src-kutsi-red-valley/crossyo/kutsi/o3d/TextPlaneSprite.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst HIERARCHY_TYPE = {\r\n STANDALONE: 1,\r\n INHERITED: 2,\r\n}\r\n\r\nconst CELL_HIERARCHY = HIERARCHY_TYPE.INHERITED\r\n\r\nclass BaseShelve {\r\n\r\n constructor(viewer) {\r\n\r\n this.viewer_ = viewer\r\n this.commodities_cache_ = new _common_CommoditiesCache__WEBPACK_IMPORTED_MODULE_0__.CommoditiesCache(viewer)\r\n this.textures_cache_ = new _common_TexturesCache__WEBPACK_IMPORTED_MODULE_1__.TexturesCache(viewer)\r\n }\r\n\r\n get_texture_url_(texture) {\r\n if (texture) {\r\n return _common_util__WEBPACK_IMPORTED_MODULE_2__.isMobile ? texture.urlSmall : texture.url\r\n } else {\r\n return null\r\n }\r\n }\r\n\r\n get_commodity_url_(commodity) {\r\n if (!_common_util__WEBPACK_IMPORTED_MODULE_2__.isMobile) {\r\n return commodity.url\r\n } else { // mobile\r\n return commodity.urlSmall || commodity.url\r\n }\r\n }\r\n\r\n // 1) 初始加载时\r\n // 2)更新shelf时,例如多列\r\n update_cells_container_(o3d, shelf) {\r\n\r\n console.log('## update_cells_container_', o3d, shelf /* JSON.stringify(shelf) */ )\r\n\r\n // remove clear first!\r\n\r\n //\r\n if (shelf.cells && shelf.cells.length > 0) {\r\n shelf.cells.forEach(cell => {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d = new three__WEBPACK_IMPORTED_MODULE_6__.Object3D()\r\n c_o3d.name = 'cell__'\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.addTag)(c_o3d, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_CELL)\r\n // ext.$c_o3d__ = c_o3d\r\n ext.get_c_o3d__ = () => {\r\n return c_o3d\r\n }\r\n\r\n let box = cell.box\r\n c_o3d.position.set(box.position.x, box.position.y, box.position.z)\r\n c_o3d.rotation.set(box.rotation.x, box.rotation.y, box.rotation.z)\r\n // this.viewer_.mesh_shelf__.add(c_o3d)\r\n o3d.add(c_o3d)\r\n\r\n // console.log('## add cell container', c_o3d)\r\n\r\n })\r\n }\r\n\r\n }\r\n\r\n // for 跟随编辑cell位置后的移动\r\n update_cell_container_e_(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d__ = ext.get_c_o3d__ ? ext.get_c_o3d__() : null\r\n if (c_o3d__) {\r\n\r\n let box = cell.box\r\n c_o3d__.position.set(box.position.x, box.position.y, box.position.z)\r\n c_o3d__.rotation.set(box.rotation.x, box.rotation.y, box.rotation.z)\r\n\r\n }\r\n }\r\n\r\n remove_all_in_shelf_(o3d_shelf) {\r\n\r\n // console.log('remove_all_in_shelf_', mesh_shelf)\r\n (0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.childrenTagToArray)(o3d_shelf, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_CELL).forEach(c=> c.removeFromParent())\r\n\r\n }\r\n\r\n remove_cell_ware_(c_o3d) {\r\n (0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.traverseTagToArray)(c_o3d, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_WARE).forEach(c => c.removeFromParent())\r\n }\r\n\r\n removeWareFromCell(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d__ = ext.get_c_o3d__ ? ext.get_c_o3d__() : null\r\n if (c_o3d__) {\r\n\r\n if (!ext.origin_o3d_url__\r\n && !ext.origin_tex_url__\r\n ) {\r\n console.log('SAME!!')\r\n return\r\n } else {\r\n console.log('REMOVE PREV!!' /*, commodity.url*/, ext.origin_o3d_url__)\r\n // remove previous!\r\n // ext.$c_o3d__.removeFromParent()\r\n // ext.$c_o3d__ = null\r\n\r\n // c_o3d__.removeFromParent()\r\n this.remove_cell_ware_(c_o3d__)\r\n\r\n ext.origin_o3d_url__ = null\r\n ext.$origin_o3d__ = null\r\n ext.origin_tex_url__ = null\r\n ext.$origin_tex__ = null\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n addWareToCell(ware, cell) {\r\n\r\n // #20221229, TEMP, 此处不一定合理\r\n (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.append_default_cell_data_)(cell)\r\n// console.log('## add ware to cell ware type', ware.type)\r\n\t\tif (ware.type == 0 || ware.type == 1) {\r\n\t\t\treturn this.addWareToCell_type0_1(ware, cell)\r\n\t\t} else if (ware.type == 21) { // rotSprite\r\n\t\t\treturn this.addWareToCell_type21(ware, cell) \r\n\t\t} else {\r\n\t\t\treturn new Promise(resolve => {\r\n\t\t\t\tresolve()\r\n\t\t\t})\r\n\t\t}\r\n\t}\r\n\r\n\tremove_prev_ware_(ware, ext, c_o3d__) {\r\n\r\n\t\tlet commodity = ware.commodity\r\n\t\t// let texture = ware.texture\r\n\r\n\t\tconsole.log('REMOVE PREV!!', this.get_commodity_url_(commodity), ext.origin_o3d_url__)\r\n\t\t// remove previous!\r\n\t\t// ext.$c_o3d__.removeFromParent()\r\n\t\t// ext.$c_o3d__ = null\r\n\r\n\t\t// only remove ware!\r\n\t\t// c_o3d__.removeFromParent()\r\n\t\tthis.remove_cell_ware_(c_o3d__)\r\n\r\n\t\text.origin_type__ = -1\r\n\t\text.origin_o3d_url__ = null\r\n\t\text.$origin_o3d__ = null\r\n\t\text.origin_tex_url__ = null\r\n\t\text.$origin_tex__ = null\r\n\r\n\t}\r\n\r\n\taddWareToCell_type0_1(ware, cell) {\r\n return new Promise((resolve, reject) => {\r\n\r\n let commodity = ware.commodity\r\n let texture = ware.texture // maybe null!\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n let c_o3d__ = ext.get_c_o3d__ ? ext.get_c_o3d__() : null\r\n // console.log('addWareToCell#c_o3d__', c_o3d__)\r\n if (c_o3d__) {\r\n if (\r\n\t\t\t\t\tware.type == ext.origin_type__\r\n\t\t\t\t\t&& this.get_commodity_url_(commodity) == ext.origin_o3d_url__\r\n && this.get_texture_url_(texture) == ext.origin_tex_url__\r\n ) {\r\n console.log('SAME!!')\r\n return\r\n } else {\r\n\r\n\t\t\t\t\tthis.remove_prev_ware_(ware, ext, c_o3d__)\r\n\r\n }\r\n\r\n }\r\n\r\n this.commodities_cache_.find(this.get_commodity_url_(commodity)).then(o3d_nt => {\r\n this.textures_cache_.find(texture).then(tex => {\r\n\r\n ext.$origin_tex__ = tex\r\n ext.origin_tex_url__ = this.get_texture_url_(texture)\r\n\r\n let o3d = o3d_nt.clone()\r\n\r\n o3d.name = o3d_nt.name + '-mat'\r\n if (o3d.material) {\r\n o3d.material = o3d.material.clone()\r\n if (tex) {\r\n o3d.material.map = tex\r\n }\r\n } else { // #20220729, mesh in children\r\n o3d.traverse(c => {\r\n if (c.isMesh) {\r\n c.material = c.material.clone() // case 自己上传的独特商品\r\n if (tex) {\r\n console.warn('#20220729, un confirmed path, 291G9J81LO1!')\r\n c.material.map = tex\r\n }\r\n }\r\n })\r\n }\r\n\r\n // ext.$origin_o3d__ = o3d\r\n ext.get_origin_o3d__ = () => {\r\n return o3d\r\n }\r\n\t\t\t\t\text.origin_type__ = ware.type\r\n ext.origin_o3d_url__ = this.get_commodity_url_(commodity)\r\n\r\n // {\r\n // let c_o3d = new Object3D()\r\n // c_o3d.name = 'cell__'\r\n // // ext.$c_o3d__ = c_o3d\r\n // ext.get_c_o3d__ = () => {\r\n // return c_o3d\r\n // }\r\n\r\n // let box = cell.box\r\n // c_o3d.position.set(box.position.x, box.position.y, box.position.z)\r\n // c_o3d.rotation.set(box.rotation.x, box.rotation.y, box.rotation.z)\r\n // this.viewer_.mesh_shelf__.add(c_o3d)\r\n // }\r\n\r\n this.update_cell_pileNumber_(cell)\r\n\r\n resolve()\r\n }).catch(e => {\r\n reject(e)\r\n })\r\n\r\n }).catch(e => {\r\n reject(e)\r\n })\r\n\r\n })\r\n\r\n }\r\n\r\n\r\n\taddWareToCell_type21(ware, cell) {\r\n\t\treturn new Promise((resolve, reject) => {\r\n\t\t\tresolve()\r\n\t\t})\r\n\t}\r\n\r\n // with pile rotation y\r\n update_cell_pileNumber_(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n if (ext.get_c_o3d__) {\r\n\r\n let c_o3d__ = ext.get_c_o3d__()\r\n if (c_o3d__) {\r\n\r\n let old_number = c_o3d__.children.length\r\n let new_number = cell.pileNumber\r\n\r\n console.log('update_pile_number', old_number, new_number)\r\n\r\n const add_tag_ = o3d => {\r\n o3d.traverse(c => {\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.addTag)(c, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_WARE)\r\n })\r\n }\r\n\r\n if (old_number != new_number) {\r\n\r\n // c_o3d__.clear()\r\n this.remove_cell_ware_(c_o3d__)\r\n\r\n let exto = ext.get_origin_o3d__()\r\n // console.log('#exto', exto, c_o3d__)\r\n\r\n let size = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.box3_except_shadow)(exto).getSize(new three__WEBPACK_IMPORTED_MODULE_6__.Vector3())\r\n let sw = size.x\r\n\r\n // if (cell.pileNumber == 6) { // temp for v3.5\r\n // let w = sw * (3 - 1)\r\n // for (let i = 0; i < new_number; i++) {\r\n // let co = exto.clone()\r\n // co.name = exto.name + '-' + i\r\n // if (i < 3) {\r\n // co.position.x = i * sw - w / 2\r\n // co.position.z = sw / 2\r\n // } else {\r\n // co.position.x = (i - 3) * sw - w / 2\r\n // co.position.z = - sw / 2\r\n // }\r\n // c_o3d__.add(co)\r\n // co.rotation.y = cell.pileRotationY * Math.PI / 180\r\n // }\r\n // } else {\r\n // let w = sw * (new_number - 1)\r\n // for (let i = 0; i < new_number; i++) {\r\n // let co = exto.clone()\r\n // co.name = exto.name + '-' + i\r\n // co.position.x = i * sw - w / 2\r\n // c_o3d__.add(co)\r\n // co.rotation.y = cell.pileRotationY * Math.PI / 180\r\n // }\r\n // }\r\n\r\n {// v5 改为总数 0, 2, 4, .. 必然两排方式\r\n\r\n // cell.maxPileNumber__ = 6\r\n // console.log(cell.box)\r\n let cw = cell.box.size.x\r\n cell.maxPileNumber__ = Math.floor(cw / sw) * 2\r\n\r\n let even_number = Math.floor(new_number / 2) * 2\r\n let half_number = even_number / 2\r\n let w = sw * (half_number - 1)\r\n for (let i = 0; i < half_number; i++) {\r\n\r\n let co = exto.clone()\r\n co.name = exto.name + '-' + i * 2\r\n\r\n co.position.x = i * sw - w / 2\r\n co.position.z = sw / 2\r\n c_o3d__.add(co)\r\n co.rotation.y = cell.pileRotationY * Math.PI / 180\r\n add_tag_(co)\r\n\r\n // console.log('#2', exto, co)\r\n\r\n let co2 = exto.clone()\r\n co2.name = exto.name + '-' + (i * 2 + 1)\r\n\r\n co2.position.x = i * sw - w / 2\r\n co2.position.z = - sw / 2\r\n c_o3d__.add(co2)\r\n co2.rotation.y = cell.pileRotationY * Math.PI / 180\r\n add_tag_(co2)\r\n\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n\r\n } else {\r\n console.warn('sk324kFdfkP34k;ls3k!')\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n update_cell_pileRotationY_(cell) {\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n\r\n if (ext.get_c_o3d__) {\r\n\r\n let c_o3d__ = ext.get_c_o3d__()\r\n if (c_o3d__) {\r\n\r\n // console.log('update_cell_pileRotationY_', c_o3d__, cell.pileRotationY)\r\n c_o3d__.children.forEach(c => {\r\n c.rotation.y = cell.pileRotationY * Math.PI / 180\r\n })\r\n\r\n } else {\r\n console.warn('UIH4329HJPmk023lKQb!')\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n // #20230112, 不同于 SurveyShelve::addLogoPriceToCell\r\n // 由于强制show状态,主要用于编辑器!\r\n update_logo_to_cell_(cell) {\r\n\r\n // console.log('update_logo_to_cell_', cell)\r\n\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n if (ext.get_c_o3d__) {\r\n let c_o3d__ = ext.get_c_o3d__()\r\n\r\n // remove logo in container!\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.childrenTagToArray)(c_o3d__, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_LOGO).forEach(c => {\r\n let tex = c.material.map\r\n c.removeFromParent()\r\n // console.log(tex)\r\n tex.dispose()\r\n })\r\n\r\n // 目前编辑\r\n let showLogo = cell.surveyLogo ? true : false\r\n // if (cell.hasOwnProperty('showLogo')) {\r\n // showLogo = cell.showLogo\r\n // }\r\n cell.showLogo = showLogo\r\n if (showLogo) {// logo\r\n let txtLogo = new kutsi_red_valley_o3d_TextSprite__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\r\n depthWrite: true,\r\n depthTest: true,\r\n }, {\r\n text: cell.surveyLogo,\r\n noPerspScale: .028, // .0185 * 1.5,\r\n })\r\n\r\n let logo = null\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // logo = cell.logo\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n logo = cell.box.child.logo\r\n // }\r\n\r\n let logopos = logo.position\r\n if (logopos) {\r\n txtLogo.position.copy(new three__WEBPACK_IMPORTED_MODULE_6__.Vector3(logopos.x, logopos.y, logopos.z))\r\n // } else { // 兼容之前老的logo数据没有position的问题\r\n // let boxpos = cell.box.position\r\n // txtLogo.position.copy(new Vector3(0, .15, 0).add(new Vector3(boxpos.x, boxpos.y, boxpos.z)))\r\n }\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // mesh_shelf.add(txtLogo)\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n\r\n c_o3d__.add(txtLogo)\r\n // { // debug\r\n // let axes = new AxesHelper(.2)\r\n // axes.position.set(logopos.x, logopos.y, logopos.z)\r\n // cell_o3d.add(axes)\r\n // }\r\n\r\n ;(0,_SceneTags__WEBPACK_IMPORTED_MODULE_3__.addTag)(txtLogo, _SceneTags__WEBPACK_IMPORTED_MODULE_3__.TAG_LOGO)\r\n }\r\n\r\n }\r\n }\r\n\r\n // price sign\r\n update_sign_to_cell_(cell) {\r\n let ext = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.use_ext)(cell)\r\n if (ext.get_c_o3d__) {\r\n let c_o3d__ = ext.get_c_o3d__()\r\n\r\n let showSign = cell.surveyPrice ? true : false\r\n // if (cell.hasOwnProperty('showSign')) {\r\n // showSign = cell.showSign\r\n // }\r\n cell.showSign = showSign\r\n if (showSign) {// sign - price\r\n\r\n let sign = null\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // sign = cell.sign\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n sign = cell.box.child.sign\r\n // }\r\n\r\n // let txtPrice = new TextSprite({\r\n let txtPrice = new kutsi_red_valley_o3d_TextPlaneSprite__WEBPACK_IMPORTED_MODULE_5__.TextPlaneSprite({\r\n depthWrite: true,\r\n depthTest: true,\r\n // 214,202,178 \r\n color: 0xd6cab2, // bg\r\n }, {\r\n textColor: 0x000000,\r\n text: (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.text_price_)(cell.surveyPrice),\r\n center_y: .5,\r\n // noPerspScale: .025,\r\n noPerspScale: .05,\r\n // perpType: PerspType.Persp,\r\n })\r\n\r\n // TODO ..\r\n\r\n let spos = sign.position\r\n txtPrice.position.set(spos.x, spos.y, spos.z)\r\n let srot = sign.rotation\r\n txtPrice.rotation.set(srot.x, srot.y, srot.z)\r\n\r\n // if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // mesh_shelf.add(txtPrice)\r\n // } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n // if (c_o3d__) {\r\n c_o3d__.add(txtPrice)\r\n // { // debug\r\n // let axes = new AxesHelper(.2)\r\n // axes.position.set(spos.x, spos.y, spos.z)\r\n // cell_o3d.add(axes)\r\n // }\r\n // }\r\n // }\r\n\r\n }\r\n\r\n }\r\n }\r\n\r\n dispose() {\r\n this.commodities_cache_.dispose()\r\n this.textures_cache_.dispose()\r\n }\r\n\r\n}\r\n\r\n\r\n// TEMP for v1 to v3, 解些老的数据,并且生成新的cells数据,copy to store/shelves 列表中\r\nconst parse_v3_cells_from_v1_shelf_model_ = o3d => {\r\n\r\n console.log('## parse_v3_cells_from_v1_shelf_model_', o3d)\r\n\r\n let boxes = []\r\n let signs = []\r\n o3d.traverse(c => {\r\n if (/^box-\\d-\\d/.test(c.name)) {\r\n // console.log(c)\r\n boxes.push(c)\r\n } else if (/^sign-\\d-\\d/.test(c.name)) {\r\n // console.log(c)\r\n signs.push(c)\r\n }\r\n })\r\n if (boxes.length != signs.length) {\r\n console.warn('boxes len != signs len')\r\n return\r\n }\r\n boxes.sort((a, b) => {\r\n return a.name.localeCompare(b.name)\r\n })\r\n signs.sort((a, b) => {\r\n return a.name.localeCompare(b.name)\r\n })\r\n\r\n // console.log(boxes, signs)\r\n\r\n let to_box_scale_ = (t, box) => {\r\n // console.log('box', box, box.geometry.boundingBox, box.geometry.boundingBox.getSize(new Vector3()))\r\n t.size = box.geometry.boundingBox.getSize(new three__WEBPACK_IMPORTED_MODULE_6__.Vector3())\r\n // console.log(t)\r\n return t\r\n }\r\n\r\n let cells = []\r\n for (let i = 0; i < boxes.length; i++) {\r\n let box = boxes[i]\r\n let sign = signs[i]\r\n\r\n // let bbx1 = box.geometry.boundingBox\r\n // bbx1.applyMatrix4(box.matrix)\r\n\r\n let cell = {\r\n name: box.name.substr(4),\r\n // 底面中心\r\n box: to_box_scale_((0,_common_util__WEBPACK_IMPORTED_MODULE_2__.to_transform)(box), box),\r\n }\r\n\r\n if (CELL_HIERARCHY == HIERARCHY_TYPE.STANDALONE) {\r\n // 中心\r\n cell.sign = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.to_transform)(sign)\r\n cell.sign.position.z += .01\r\n cell.logo = { // #20220611\r\n position: {\r\n x: box.position.x,\r\n y: box.position.y + .15,\r\n z: box.position.z\r\n }\r\n }\r\n } else if (CELL_HIERARCHY == HIERARCHY_TYPE.INHERITED) {\r\n\r\n let t_sign = (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.to_transform)(sign)\r\n t_sign.position.x -= cell.box.position.x\r\n t_sign.position.y -= cell.box.position.y\r\n t_sign.position.z -= cell.box.position.z\r\n t_sign.position.z += .01\r\n\r\n t_sign.rotation.x = t_sign.rotation.y = t_sign.rotation.z = 0\r\n\r\n cell.box.child = {\r\n sign: t_sign,\r\n logo: { // #20220611\r\n position: {\r\n x: box.position.x - cell.box.position.x,\r\n y: box.position.y + .15 - cell.box.position.y,\r\n z: box.position.z - cell.box.position.z,\r\n },\r\n },\r\n }\r\n\r\n }\r\n\r\n (0,_common_util__WEBPACK_IMPORTED_MODULE_2__.append_default_cell_data_)(cell)\r\n\r\n cells.push(cell)\r\n }\r\n\r\n return cells\r\n}\r\n\r\n// #20230117, 主要调用移至上传流程,此处对于上传流程的修补\r\nconst try_append_shelf_originCells = (o3d, shelf0) => {\r\n // TEMP for v1 to v3, 解些老的数据,并且生成新的cells数据,copy to store/shelves 列表中\r\n // if (!shelf0.cells || shelf0.cells.length == 0) \r\n if (!shelf0.originCells) { // 可以尝试用modelCells覆盖一下\r\n // v5 比较 cells 中是否有数据,如果没有,则运行 parse v3 cell 并且打印到日志中\r\n\r\n // this.shopData_.shelf.cells = \r\n let cells = parse_v3_cells_from_v1_shelf_model_(o3d)\r\n if (cells && cells.length > 0) {\r\n shelf0.originCells = cells\r\n\r\n let s_cells = JSON.stringify(cells)\r\n console.log('发现模型中含有cells数据覆盖至originCells\\n', s_cells)\r\n\r\n }\r\n }\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://shelves/./src/crossyo/shelves/common/BaseShelve.js?"); /***/ }), @@ -454,7 +454,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"LightSourceManager\": () => (/* binding */ LightSourceManager)\n/* harmony export */ });\n/* harmony import */ var three_examples_jsm_loaders_gltfloader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three/examples/jsm/loaders/gltfloader */ \"./node_modules/_three@0.139.2@three/examples/jsm/loaders/gltfloader.js\");\n\r\n\r\n\r\nclass LightSourceManager {\r\n\r\n constructor(viewer) {\r\n this.viewer_ = viewer\r\n\r\n this.prefixAsset_ = this.viewer_.opts_.prefixAsset\r\n\r\n // this.lightSource1_ = 'default' // default \r\n\r\n // this.sample_model_ = null\r\n this.default_tex_ = null\r\n }\r\n\r\n get scene_() {\r\n return this.viewer_.scene_\r\n }\r\n\r\n get shopData_() {\r\n return this.viewer_.shopData_\r\n }\r\n\r\n // get load_sample_model_() {\r\n // return {\r\n // func: 'setupCustomization', param: {\r\n // onDoing: next => {\r\n // let loader = new GLTFLoader()\r\n // loader.load(`${this.prefixAsset_}/model/light-source-sample-1.glb`, gltf => {\r\n // // console.log(gltf)\r\n // this.sample_model_ = gltf.scene.children[0]\r\n // // console.log('this.sample_model_', this.sample_model_)\r\n // next()\r\n // })\r\n // }\r\n // }\r\n // }\r\n // }\r\n\r\n // get sampleModel() {\r\n // return this.sample_model_\r\n // }\r\n\r\n // init load, or panorama/hall changed!\r\n // when_init_load_() {\r\n // }\r\n\r\n setup_panorama_default_env_tex_(tex) {\r\n this.default_tex_ = tex\r\n // console.log('## setup panorama default env tex', tex)\r\n }\r\n\r\n update_light_source1_() {\r\n \r\n let lightSource1 = 'default'\r\n if (!this.viewer_.is_hall__) {\r\n if (this.shopData_.panorama) {\r\n lightSource1 = this.shopData_.panorama.lightSource1 || 'default'\r\n }\r\n } else {\r\n if (this.shopData_.hall) {\r\n lightSource1 = this.shopData_.hall.lightSource1 || 'default'\r\n }\r\n }\r\n\r\n if (lightSource1 == 'default') {\r\n this.scene_.environment = this.default_tex_\r\n } else if (lightSource1 == 'point') {\r\n\r\n // TODO dispose or cache tex!\r\n\r\n this.viewer_.build_specs__([{\r\n func: 'setupEnvEquirect', param: {\r\n url: `${this.prefixAsset_}/env/env-point-1-w.exr`,\r\n onAfter: tex => {\r\n this.scene_.environment = tex\r\n }\r\n }\r\n }])\r\n } else if (lightSource1 == 'area') {\r\n this.viewer_.build_specs__([{\r\n func: 'setupEnvEquirect', param: {\r\n url: `${this.prefixAsset_}/env/env-area-1-w.exr`,\r\n onAfter: tex => {\r\n this.scene_.environment = tex\r\n }\r\n }\r\n }])\r\n }\r\n\r\n }\r\n\r\n}\r\n\n\n//# sourceURL=webpack://shelves/./src/crossyo/shelves/common/LightSourceManager.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"LightSourceManager\": () => (/* binding */ LightSourceManager)\n/* harmony export */ });\n/* harmony import */ var three_examples_jsm_loaders_GLTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three/examples/jsm/loaders/GLTFLoader */ \"./node_modules/_three@0.139.2@three/examples/jsm/loaders/GLTFLoader.js\");\n\r\n\r\n\r\nclass LightSourceManager {\r\n\r\n constructor(viewer) {\r\n this.viewer_ = viewer\r\n\r\n this.prefixAsset_ = this.viewer_.opts_.prefixAsset\r\n\r\n // this.lightSource1_ = 'default' // default \r\n\r\n // this.sample_model_ = null\r\n this.default_tex_ = null\r\n }\r\n\r\n get scene_() {\r\n return this.viewer_.scene_\r\n }\r\n\r\n get shopData_() {\r\n return this.viewer_.shopData_\r\n }\r\n\r\n // get load_sample_model_() {\r\n // return {\r\n // func: 'setupCustomization', param: {\r\n // onDoing: next => {\r\n // let loader = new GLTFLoader()\r\n // loader.load(`${this.prefixAsset_}/model/light-source-sample-1.glb`, gltf => {\r\n // // console.log(gltf)\r\n // this.sample_model_ = gltf.scene.children[0]\r\n // // console.log('this.sample_model_', this.sample_model_)\r\n // next()\r\n // })\r\n // }\r\n // }\r\n // }\r\n // }\r\n\r\n // get sampleModel() {\r\n // return this.sample_model_\r\n // }\r\n\r\n // init load, or panorama/hall changed!\r\n // when_init_load_() {\r\n // }\r\n\r\n setup_panorama_default_env_tex_(tex) {\r\n this.default_tex_ = tex\r\n // console.log('## setup panorama default env tex', tex)\r\n }\r\n\r\n update_light_source1_() {\r\n \r\n let lightSource1 = 'default'\r\n if (!this.viewer_.is_hall__) {\r\n if (this.shopData_.panorama) {\r\n lightSource1 = this.shopData_.panorama.lightSource1 || 'default'\r\n }\r\n } else {\r\n if (this.shopData_.hall) {\r\n lightSource1 = this.shopData_.hall.lightSource1 || 'default'\r\n }\r\n }\r\n\r\n if (lightSource1 == 'default') {\r\n this.scene_.environment = this.default_tex_\r\n } else if (lightSource1 == 'point') {\r\n\r\n // TODO dispose or cache tex!\r\n\r\n this.viewer_.build_specs__([{\r\n func: 'setupEnvEquirect', param: {\r\n url: `${this.prefixAsset_}/env/env-point-1-w.exr`,\r\n onAfter: tex => {\r\n this.scene_.environment = tex\r\n }\r\n }\r\n }])\r\n } else if (lightSource1 == 'area') {\r\n this.viewer_.build_specs__([{\r\n func: 'setupEnvEquirect', param: {\r\n url: `${this.prefixAsset_}/env/env-area-1-w.exr`,\r\n onAfter: tex => {\r\n this.scene_.environment = tex\r\n }\r\n }\r\n }])\r\n }\r\n\r\n }\r\n\r\n}\r\n\n\n//# sourceURL=webpack://shelves/./src/crossyo/shelves/common/LightSourceManager.js?"); /***/ }), @@ -718,7 +718,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ShelvesViewer_\": () => (/* binding */ ShelvesViewer_)\n/* harmony export */ });\n/* harmony import */ var _ViewModeBaseViewer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ViewModeBaseViewer */ \"./src/crossyo/shelves/viewer/ViewModeBaseViewer.js\");\n/* harmony import */ var kutsi_util_BuilderEx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! kutsi/util/BuilderEx */ \"./src-kutsi/crossyo/kutsi/util/BuilderEx.js\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! three */ \"./node_modules/_three@0.139.2@three/build/three.module.js\");\n/* harmony import */ var kutsi_shelves_controls_ElasticFreeLookControls__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! kutsi-shelves/controls/ElasticFreeLookControls */ \"./src-kutsi-shelves/crossyo/kutsi/controls/ElasticFreeLookControls.js\");\n/* harmony import */ var kutsi_util_SceneUtil__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! kutsi/util/SceneUtil */ \"./src-kutsi/crossyo/kutsi/util/SceneUtil.js\");\n/* harmony import */ var kutsi_util_SceneTuningUtil__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! kutsi/util/SceneTuningUtil */ \"./src-kutsi/crossyo/kutsi/util/SceneTuningUtil.js\");\n/* harmony import */ var _assets_white_256_png__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../assets/white-256.png */ \"./src/crossyo/shelves/assets/white-256.png\");\n/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../common/util */ \"./src/crossyo/shelves/common/util.js\");\n/* harmony import */ var _si_SiObjects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../si/SiObjects */ \"./src/crossyo/shelves/si/SiObjects.js\");\n/* harmony import */ var kutsi_util_frame_ViewTransformDetector__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! kutsi/util/frame/ViewTransformDetector */ \"./src-kutsi/crossyo/kutsi/util/frame/ViewTransformDetector.js\");\n/* harmony import */ var _common_ShelfO3dExt5__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../common/ShelfO3dExt5 */ \"./src/crossyo/shelves/common/ShelfO3dExt5.js\");\n/* harmony import */ var _common_SceneTags__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../common/SceneTags */ \"./src/crossyo/shelves/common/SceneTags.js\");\n\r\n\r\n\r\n\r\n\r\n// import { DropTableGeometry } from 'kutsi/geometry/DropTableGeometry'\r\n\r\n\r\n\r\n\r\n\r\n// import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'\r\n// import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls'\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst try_mixin_two_fov_ = cam => {\r\n\tif (!cam.hasOwnProperty('aspectFov')) {\r\n\r\n\t\tcam.aspectFov_ = cam.fov\r\n\t\tcam.zoomFov_ = 1\r\n\t\tObject.defineProperty(cam, 'aspectFov', {\r\n\t\t\tset(v) {\r\n\t\t\t\tthis.aspectFov_ = v\r\n\t\t\t\tthis.fov = this.aspectFov_ * this.zoomFov_\r\n\t\t\t\t// console.log('update after aspectFov', this.fov)\r\n\t\t\t},\r\n\t\t\tget() {\r\n\t\t\t\treturn this.aspectFov_\r\n\t\t\t}\r\n\t\t})\r\n\t\tObject.defineProperty(cam, 'zoomFov', {\r\n\t\t\tset(v) {\r\n\t\t\t\tthis.zoomFov_ = v\r\n\t\t\t\tthis.fov = this.aspectFov_ * this.zoomFov_\r\n\t\t\t\t// console.log('update after zoomFov ', this.zoomFov_, ' to real fov', this.fov)\r\n\r\n\t\t\t\t// 1 ~ .5(长焦2x)\r\n\r\n\t\t\t\tthis.updateProjectionMatrix()\r\n\t\t\t},\r\n\t\t\tget() {\r\n\t\t\t\treturn this.zoomFov_\r\n\t\t\t}\r\n\t\t})\r\n\r\n\t}\r\n}\r\n\r\nconst SPHERE_RADIUS = 13.65\r\nconst SPHERE_DEBUG = false // normal\r\n// const SPHERE_DEBUG = true // orbit show depth!\r\n\r\nclass ShelvesViewer_ extends _ViewModeBaseViewer__WEBPACK_IMPORTED_MODULE_0__.ViewModeBaseViewer {\r\n\r\n\tconstructor(opts) {\r\n\r\n\t\tsuper(Object.assign({\r\n\t\t\ttrend: {\r\n\t\t\t\thdr: true,\r\n\t\t\t},\r\n\t\t\tpicker: {\r\n\t\t\t\tuseHitsArray: true,\r\n\t\t\t},\r\n\t\t\t// manually_start_animate: true, // for loading\r\n\t\t\t// clzControls: MapControls,\r\n\t\t\tfov0: 55,\r\n\r\n\t\t\tclzBuilder: kutsi_util_BuilderEx__WEBPACK_IMPORTED_MODULE_1__.BuilderEx,\r\n\r\n\t\t\t// v2\r\n\t\t\t// assets: {\r\n\t\t\t// \tenv1: assets_env1,\r\n\t\t\t// }\r\n\r\n\t\t}, opts))\r\n\r\n\t\t// {//window aspect ratio!\r\n\t\t// \t// if (window.innerWidth / window.innerHeight < 1) {\r\n\t\t// \t// \tthis.opts_.fov0 = 75\r\n\t\t// \t// }\r\n\t\t// }\r\n\r\n\t\t// console.log('this.opts_', this.opts_)\r\n\r\n\t\tthis.shopData_ = this.opts_.shopData\r\n\r\n\t\tthis.isViewer__ = true\r\n\r\n\t\tthis.objects__ = new _si_SiObjects__WEBPACK_IMPORTED_MODULE_7__.SiObjects(this)\r\n\r\n\t\t// default 1 / 1000\r\n\t\tthis.observe_vtd_ = new kutsi_util_frame_ViewTransformDetector__WEBPACK_IMPORTED_MODULE_8__.ViewTransformDetector(1 / 100, false)\r\n\r\n\t}\r\n\r\n\tresize_() {\r\n\t\tsuper.resize_()\r\n\t\t// this.size_\r\n\r\n\t\ttry_mixin_two_fov_(this.camera_)\r\n\r\n\t\t// .5 -> 75\r\n\t\t// 2 -> 50\r\n\t\tlet aspect = this.size_.w / this.size_.h\r\n\t\tlet aspectFov = three__WEBPACK_IMPORTED_MODULE_11__.MathUtils.lerp(75, 50, three__WEBPACK_IMPORTED_MODULE_11__.MathUtils.smoothstep(aspect, .5, 2))\r\n\t\t// console.log('\\t', aspect, aspectFov)\r\n\r\n\t\tthis.camera_.aspectFov = aspectFov\r\n\t\t// this.camera_.aspectFov = 75 // for snapshot!\r\n\t\tthis.camera_.updateProjectionMatrix()\r\n\r\n\t}\r\n\r\n\tstartup() {\r\n\t\tsuper.startup()\r\n\t\t// this.controls_.enablePan = true\r\n\t\tthis.scene_.background = new three__WEBPACK_IMPORTED_MODULE_11__.Color(0xefefef)\r\n\t}\r\n\r\n\tbeginLoadSpecs() {\r\n\r\n\t\tlet arr = super.beginLoadSpecs()\r\n\r\n\t\tif (!this.is_hall__) {\r\n\r\n\t\t\t// #20230103\r\n\t\t\tlet panorama = this.shopData_.panorama\r\n\t\t\tif (panorama && panorama.enterZoom) {\r\n\t\t\t\tthis.camera_.zoomFov = 1 / panorama.enterZoom\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.geo_env_sphere__ = new three__WEBPACK_IMPORTED_MODULE_11__.SphereBufferGeometry(SPHERE_RADIUS, 256, 256)\r\n\t\t// this.geo_env_sphere__ = new SphereBufferGeometry(SPHERE_RADIUS, 512, 512)\r\n\t\tthis.mesh_env_sphere__ = null\r\n\r\n\t\tthis.cart_plane_ = new three__WEBPACK_IMPORTED_MODULE_11__.Plane(new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(-1, 0, 0), 2)\r\n\t\tthis.mesh_shelf__ = null\r\n\r\n\t\t// {// debug\r\n\t\t// \tthis.dump_keydown_after__ = () => {\r\n\t\t// \t\tconsole.log('shelf', this.mesh_shelf__)\r\n\t\t// \t}\r\n\t\t// }\r\n\r\n\t\tarr.push({\r\n\t\t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t\turl: _assets_white_256_png__WEBPACK_IMPORTED_MODULE_5__,\r\n\t\t\t\tonAfter: tex => {\r\n\t\t\t\t\tthis.w256_ = tex\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t})\r\n\r\n\t\t// this.DEFAULT_TARGET__ = new Vector3(0.1, -0.01, 0.00)\r\n\t\t// this.DEFAULT_TARGET__ = new Vector3(2.37, -0.41, 0.00)\r\n\t\tthis.DEFAULT_TARGET__ = new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(2.37, -0.31, 0.00)\r\n\r\n\t\tthis.specs_item_cust_controls_(arr)\r\n\r\n\t\tthis.specs_shop_data_base_(arr)\r\n\r\n\t\tlet shelf0 = (0,_common_util__WEBPACK_IMPORTED_MODULE_6__.get_shelf_0_)(this.shopData_)\r\n\t\tif (shelf0) {\r\n\r\n\t\t\tlet shelf_url = shelf0.url\r\n\t\t\tarr.push({\r\n\t\t\t\tfunc: 'setupModelGltf', param: {\r\n\t\t\t\t\tpath: shelf_url.substr(0, shelf_url.lastIndexOf('/')),\r\n\t\t\t\t\tname: shelf_url.substr(shelf_url.lastIndexOf('/')),\r\n\t\t\t\t\t// predefinedModel: (() => {\r\n\t\t\t\t\t// \tlet def = {\r\n\t\t\t\t\t// \t\tobjects_isolate_material: true,\r\n\t\t\t\t\t// \t\tmaps: {\r\n\t\t\t\t\t// \t\t\t'm1': { url: 'model/ao-2to1k-s4096/shelves_Bake1_CyclesBake_AO.png' }\r\n\t\t\t\t\t// \t\t},\r\n\t\t\t\t\t// \t\tobjects: {\r\n\t\t\t\t\t// \t\t\t'shelves': {\r\n\t\t\t\t\t// \t\t\t\tlightMap: 'm1'\r\n\t\t\t\t\t// \t\t\t}\r\n\t\t\t\t\t// \t\t}\r\n\t\t\t\t\t// \t}\r\n\t\t\t\t\t// \treturn def\r\n\t\t\t\t\t// })(),\r\n\t\t\t\t\tonAfter: o3d => {\r\n\r\n\t\t\t\t\t\to3d.traverse(c => {\r\n\t\t\t\t\t\t\tif (c.isMesh) {\r\n\t\t\t\t\t\t\t\tif (c.material.aoMap) {\r\n\t\t\t\t\t\t\t\t\tc.material.lightMap = c.material.aoMap\r\n\t\t\t\t\t\t\t\t\t// c.material.aoMap = null\r\n\t\t\t\t\t\t\t\t\tc.material.lightMapIntensity = .5\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tc.material.side = three__WEBPACK_IMPORTED_MODULE_11__.FrontSide\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (/^box-\\d-\\d/.test(c.name)) {\r\n\t\t\t\t\t\t\t\tc.visible = false\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t})\r\n\r\n\t\t\t\t\t\tif (shelf0.position && shelf0.rotation) {\r\n\r\n\t\t\t\t\t\t\to3d.position.set(shelf0.position.x, shelf0.position.y, shelf0.position.z)\r\n\t\t\t\t\t\t\to3d.rotation.set(shelf0.rotation.x, shelf0.rotation.y, shelf0.rotation.z)\r\n\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\to3d.rotation.set(0, - Math.PI / 2, 0)\r\n\t\t\t\t\t\t\to3d.position.set(2.7, -1, 0)\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tthis.scene_.add(o3d)\r\n\r\n\t\t\t\t\t\t// ? 不用尝试解些模型内嵌的cells信息\r\n\r\n\t\t\t\t\t\tnew _common_ShelfO3dExt5__WEBPACK_IMPORTED_MODULE_9__.ShelfO3dExt5(this).setup(o3d, shelf0, { forceUpdate: false })\r\n\t\t\t\t\t\tthis.mesh_shelf__ = o3d\r\n\r\n\t\t\t\t\t\t// .$model__ = o3d\r\n\t\t\t\t\t\tshelf0.get_model__ = () => {\r\n\t\t\t\t\t\t\treturn o3d\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// dump_o3d(o3d)\r\n\t\t\t\t\t\t// can-2, box-2, pillow-2\r\n\r\n\t\t\t\t\t\t// create_sample_balls(balls => {\r\n\t\t\t\t\t\t// \tballs.position.set(2, -.25, 0)\r\n\t\t\t\t\t\t// \tthis.scene_.add(balls)\r\n\t\t\t\t\t\t// })\r\n\r\n\t\t\t\t\t\t// create_env_ball(ball => {\r\n\t\t\t\t\t\t// \tball.position.set(2, -.25, 0)\r\n\t\t\t\t\t\t// \tthis.scene_.add(ball)\r\n\t\t\t\t\t\t// })\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\r\n\t\t} else {\r\n\t\t\t// TODO 新建\r\n\t\t}\r\n\r\n\t\t// if (this.shopData_ && this.shopData_.commodities) {\r\n\r\n\t\t// \tthis.shopData_.commodities.forEach(mod => {\r\n\t\t// \t\tlet mod_url = mod.url\r\n\t\t// \t\tarr.push({\r\n\t\t// \t\t\tfunc: 'setupModelGltf', param: {\r\n\t\t// \t\t\t\tpath: mod_url.substr(0, mod_url.lastIndexOf('/')),\r\n\t\t// \t\t\t\tname: mod_url.substr(mod_url.lastIndexOf('/')),\r\n\t\t// \t\t\t\tonAfter: o3d => {\r\n\t\t// \t\t\t\t\to3d.traverse(c => {\r\n\t\t// \t\t\t\t\t\tif (c.isMesh) {\r\n\t\t// \t\t\t\t\t\t\tc.material.envMapIntensity = this.shopData_.panorama.multiply\r\n\t\t// \t\t\t\t\t\t\tc.material.side = FrontSide\r\n\t\t// \t\t\t\t\t\t}\r\n\t\t// \t\t\t\t\t})\r\n\t\t// \t\t\t\t\tif (!o3d.isMesh && o3d.children.length == 1) {\r\n\t\t// \t\t\t\t\t\t// 单个mesh, 需要导出时apply transform\r\n\t\t// \t\t\t\t\t\tmod.get_model__ = () => {\r\n\t\t// \t\t\t\t\t\t\treturn o3d.children[0]\r\n\t\t// \t\t\t\t\t\t}\r\n\t\t// \t\t\t\t\t} else {\r\n\t\t// \t\t\t\t\t\tmod.get_model__ = () => {\r\n\t\t// \t\t\t\t\t\t\treturn o3d\r\n\t\t// \t\t\t\t\t\t}\r\n\t\t// \t\t\t\t\t}\r\n\t\t// \t\t\t\t},\r\n\t\t// \t\t\t},\r\n\t\t// \t\t})\r\n\t\t// \t})\r\n\r\n\t\t// } else {\r\n\t\t// \t// TODO 新建\r\n\t\t// }\r\n\r\n\t\tif (this.shopData_ && this.shopData_.objects) {\r\n\t\t\tthis.objects__.attach_specs_for_load_(this.shopData_.objects, arr)\r\n\t\t}\r\n\r\n\t\tif (this.use_grid__) {\r\n\r\n\t\t\tlet grid = new three__WEBPACK_IMPORTED_MODULE_11__.GridHelper(4, 8)\r\n\t\t\t// grid.position.set(0, -5, 0)\r\n\t\t\tgrid.position.set(0, -1, 0)\r\n\t\t\tthis.scene_.add(grid)\r\n\r\n\t\t\t// let box = new Mesh(\r\n\t\t\t// \tnew BoxBufferGeometry(1.5, 1.5, .5),\r\n\t\t\t// \tnew MeshStandardMaterial({\r\n\t\t\t// \t\twireframe: true,\r\n\t\t\t// \t})\r\n\t\t\t// )\r\n\t\t\t// box.rotation.set(0, Math.PI / 2, 0)\r\n\t\t\t// box.position.set(2.25, -.25, 0)\r\n\t\t\t// this.scene_.add(box)\r\n\r\n\t\t}\r\n\r\n\t\t// cart plane !\r\n\r\n\r\n\t\treturn arr\r\n\t}\r\n\r\n\t// @can be override\r\n\tspecs_item_cust_controls_(arr) {\r\n\r\n\t\tarr.push({\r\n\t\t\tfunc: 'setupCustomization', param: {\r\n\t\t\t\tonDoing: next => {\r\n\r\n\t\t\t\t\t// this.scene_.fog = new Fog(this.theme_.fogColor, 400, 800)\r\n\r\n\t\t\t\t\t// this.controls_.minPolarAngle = 0\r\n\t\t\t\t\t// this.controls_.maxPolarAngle = Math.PI * .67\r\n\t\t\t\t\t// this.controls_.maxDistance = 400\r\n\r\n\t\t\t\t\t// this.scene_.add(new AxesHelper(10))\r\n\r\n\t\t\t\t\tlet target = this.DEFAULT_TARGET__\r\n\r\n\t\t\t\t\tif (SPHERE_DEBUG) { // debug\r\n\t\t\t\t\t\tthis.updateViewerLookat({\r\n\t\t\t\t\t\t\tposition: new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(-1, 0.1, 0.00),\r\n\t\t\t\t\t\t\ttarget: new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(0.00, 0.00, 0.00),\r\n\t\t\t\t\t\t\tforceUpdateNearFar: true,\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t\tthis.controls_.enablePan = true\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis.changeControls(\r\n\t\t\t\t\t\t\t// new FreeLookControls\r\n\t\t\t\t\t\t\tnew kutsi_shelves_controls_ElasticFreeLookControls__WEBPACK_IMPORTED_MODULE_2__[\"default\"]\r\n\t\t\t\t\t\t\t\t(this.camera_, this.renderer_.domElement, {\r\n\t\t\t\t\t\t\t\t\tlookDirection: -1,\r\n\t\t\t\t\t\t\t\t\telasticDirection: target,\r\n\t\t\t\t\t\t\t\t\tzoomResetFunction: e => {\r\n\t\t\t\t\t\t\t\t\t\treturn e.object.zoomFov\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\tzoomFunction: e => {\r\n\t\t\t\t\t\t\t\t\t\te.object.zoomFov = e.zoom2\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\tzoomMin: .5,\r\n\t\t\t\t\t\t\t\t\tzoomMax: 1,\r\n\t\t\t\t\t\t\t\t}))\r\n\r\n\t\t\t\t\t\tthis.updateViewerLookat({\r\n\t\t\t\t\t\t\t// position: new Vector3(-0.1, 0.01, 0.00),\r\n\t\t\t\t\t\t\t// target: new Vector3(0.00, 0.00, 0.00),\r\n\t\t\t\t\t\t\tposition: new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(0.00, 0.00, 0.00),\r\n\t\t\t\t\t\t\ttarget,\r\n\t\t\t\t\t\t\tforceUpdateNearFar: true,\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tnext()\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t})\r\n\r\n\r\n\t}\r\n\r\n\tspecs_shop_data_base_(arr) {\r\n\r\n\t\tif (this.shopData_ && this.shopData_.panorama) {\r\n\r\n\t\t\t// if (this.shopData_.panorama.urlEnv) {\r\n\t\t\t// \tarr.push({\r\n\t\t\t// \t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t// \t\t\turl: `${this.shopData_.panorama.url}`,\r\n\t\t\t// \t\t\tonAfter: tex => {\r\n\t\t\t// \t\t\t\tthis.scene_.background = tex\r\n\t\t\t// \t\t\t\t// this.scene_.environment = tex\r\n\t\t\t// \t\t\t}\r\n\t\t\t// \t\t}\r\n\t\t\t// \t})\r\n\t\t\t// \tarr.push({\r\n\t\t\t// \t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t// \t\t\turl: `${this.shopData_.panorama.urlEnv}`,\r\n\t\t\t// \t\t\tonAfter: tex => {\r\n\t\t\t// \t\t\t\t// this.scene_.background = tex\r\n\t\t\t// \t\t\t\tthis.scene_.environment = tex\r\n\t\t\t// \t\t\t}\r\n\t\t\t// \t\t}\r\n\t\t\t// \t})\r\n\r\n\t\t\t// } else {\r\n\r\n\t\t\tlet panorama_shelf_exr = this.shopData_.panorama.urlShelfExr\r\n\t\t\tarr.push({\r\n\t\t\t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t\t\turl: `${this.get_panorama_url_(this.shopData_.panorama)}`,\r\n\t\t\t\t\tonAfter: tex => {\r\n\t\t\t\t\t\t// this.scene_.background = tex\r\n\t\t\t\t\t\t// for rotationY\r\n\r\n\t\t\t\t\t\tlet sp = new three__WEBPACK_IMPORTED_MODULE_11__.Mesh(\r\n\t\t\t\t\t\t\t// new SphereBufferGeometry(20, 256, 256),\r\n\t\t\t\t\t\t\tthis.geo_env_sphere__,\r\n\t\t\t\t\t\t\tnew three__WEBPACK_IMPORTED_MODULE_11__.MeshStandardMaterial({\r\n\t\t\t\t\t\t\t\tmap: tex,\r\n\t\t\t\t\t\t\t\tside: three__WEBPACK_IMPORTED_MODULE_11__.BackSide,\r\n\t\t\t\t\t\t\t\t// wireframe: true,\r\n\t\t\t\t\t\t\t\tfog: false,\r\n\t\t\t\t\t\t\t\t// displacementScale: -env_.radius * .992,\r\n\t\t\t\t\t\t\t\t// displacementMap: new TextureLoader().load(`${this.prefixAsset_}/env/equirect/${env_.code}-zdepth-1k.png`),\r\n\t\t\t\t\t\t\t\tdisplacementScale: - SPHERE_RADIUS,\r\n\t\t\t\t\t\t\t\tdisplacementMap: new three__WEBPACK_IMPORTED_MODULE_11__.TextureLoader().load(`${this.shopData_.panorama.urlDepth}`),\r\n\t\t\t\t\t\t\t\tenvMap: this.w256_,\r\n\t\t\t\t\t\t\t\t// envMapIntensity: 2,\r\n\t\t\t\t\t\t\t})\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t\tsp.scale.set(1, 1, -1)\r\n\t\t\t\t\t\t// sp.name = 'sys-env-sphere-'\r\n\t\t\t\t\t\t;(0,_common_SceneTags__WEBPACK_IMPORTED_MODULE_10__.addTag)(sp, _common_SceneTags__WEBPACK_IMPORTED_MODULE_10__.TAG_SYS_ENV)\r\n\t\t\t\t\t\tthis.scene_.add(sp)\r\n\r\n\t\t\t\t\t\tthis.mesh_env_sphere__ = sp\r\n\t\t\t\t\t\tthis.mesh_env_sphere__.rotation.y = this.shopData_.panorama.rotationY * Math.PI / 180\r\n\r\n\t\t\t\t\t\tif (!panorama_shelf_exr) {\r\n\t\t\t\t\t\t\tthis.scene_.environment = tex\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tthis.light_source_manager_.setup_panorama_default_env_tex_(tex)\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t\tif (panorama_shelf_exr) {\r\n\t\t\t\tarr.push({\r\n\t\t\t\t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t\t\t\turl: `${panorama_shelf_exr}`,\r\n\t\t\t\t\t\tonAfter: tex => {\r\n\t\t\t\t\t\t\tthis.scene_.environment = tex\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// }\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// TODO 新增时\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tget_panorama_url_(panorama) {\r\n\t\tif (this.isViewer__) {\r\n\t\t\treturn _common_util__WEBPACK_IMPORTED_MODULE_6__.isMobile ? panorama.urlSmall : panorama.url\r\n\t\t} else {\r\n\t\t\treturn panorama.urlSmall // 編輯器頻繁dispose,減少開銷\r\n\t\t}\r\n\t}\r\n\r\n\tbefore_render_(time, delta) {\r\n\t\tsuper.before_render_(time, delta)\r\n\r\n\t\tlet result = this.observe_vtd_.updateResult(this)\r\n\t\tif (result) {\r\n\t\t\t// console.log(data) \r\n\t\t\tthis.emit('roughViewChanged', result)\r\n\t\t}\r\n\r\n\t\t// if (this.mesh_env_sphere__) { // just for render test!\r\n\t\t// \tthis.mesh_env_sphere__.rotation.y += delta\r\n\t\t// }\r\n\t}\r\n\r\n\tdispose() {\r\n\t\tif (this.objects__) {\r\n\t\t\tthis.objects__.dispose()\r\n\t\t}\r\n\t\tsuper.dispose()\r\n\t\tconsole.log('viewer dispose!')\r\n\t}\r\n\r\n}\r\n\r\n\n\n//# sourceURL=webpack://shelves/./src/crossyo/shelves/viewer/ShelvesViewer_.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ShelvesViewer_\": () => (/* binding */ ShelvesViewer_)\n/* harmony export */ });\n/* harmony import */ var _ViewModeBaseViewer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ViewModeBaseViewer */ \"./src/crossyo/shelves/viewer/ViewModeBaseViewer.js\");\n/* harmony import */ var kutsi_util_BuilderEx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! kutsi/util/BuilderEx */ \"./src-kutsi/crossyo/kutsi/util/BuilderEx.js\");\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! three */ \"./node_modules/_three@0.139.2@three/build/three.module.js\");\n/* harmony import */ var kutsi_shelves_controls_ElasticFreeLookControls__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! kutsi-shelves/controls/ElasticFreeLookControls */ \"./src-kutsi-shelves/crossyo/kutsi/controls/ElasticFreeLookControls.js\");\n/* harmony import */ var kutsi_util_SceneUtil__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! kutsi/util/SceneUtil */ \"./src-kutsi/crossyo/kutsi/util/SceneUtil.js\");\n/* harmony import */ var kutsi_util_SceneTuningUtil__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! kutsi/util/SceneTuningUtil */ \"./src-kutsi/crossyo/kutsi/util/SceneTuningUtil.js\");\n/* harmony import */ var _assets_white_256_png__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../assets/white-256.png */ \"./src/crossyo/shelves/assets/white-256.png\");\n/* harmony import */ var _common_util__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../common/util */ \"./src/crossyo/shelves/common/util.js\");\n/* harmony import */ var _si_SiObjects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../si/SiObjects */ \"./src/crossyo/shelves/si/SiObjects.js\");\n/* harmony import */ var kutsi_util_frame_ViewTransformDetector__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! kutsi/util/frame/ViewTransformDetector */ \"./src-kutsi/crossyo/kutsi/util/frame/ViewTransformDetector.js\");\n/* harmony import */ var _common_ShelfO3dExt5__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../common/ShelfO3dExt5 */ \"./src/crossyo/shelves/common/ShelfO3dExt5.js\");\n/* harmony import */ var _common_SceneTags__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../common/SceneTags */ \"./src/crossyo/shelves/common/SceneTags.js\");\n\r\n\r\n\r\n\r\n\r\n// import { DropTableGeometry } from 'kutsi/geometry/DropTableGeometry'\r\n\r\n\r\n\r\n\r\n\r\n// import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'\r\n// import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls'\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst try_mixin_two_fov_ = cam => {\r\n\tif (!cam.hasOwnProperty('aspectFov')) {\r\n\r\n\t\tcam.aspectFov_ = cam.fov\r\n\t\tcam.zoomFov_ = 1\r\n\t\tObject.defineProperty(cam, 'aspectFov', {\r\n\t\t\tset(v) {\r\n\t\t\t\tthis.aspectFov_ = v\r\n\t\t\t\tthis.fov = this.aspectFov_ * this.zoomFov_\r\n\t\t\t\t// console.log('update after aspectFov', this.fov)\r\n\t\t\t},\r\n\t\t\tget() {\r\n\t\t\t\treturn this.aspectFov_\r\n\t\t\t}\r\n\t\t})\r\n\t\tObject.defineProperty(cam, 'zoomFov', {\r\n\t\t\tset(v) {\r\n\t\t\t\tthis.zoomFov_ = v\r\n\t\t\t\tthis.fov = this.aspectFov_ * this.zoomFov_\r\n\t\t\t\t// console.log('update after zoomFov ', this.zoomFov_, ' to real fov', this.fov)\r\n\r\n\t\t\t\t// 1 ~ .5(长焦2x)\r\n\r\n\t\t\t\tthis.updateProjectionMatrix()\r\n\t\t\t},\r\n\t\t\tget() {\r\n\t\t\t\treturn this.zoomFov_\r\n\t\t\t}\r\n\t\t})\r\n\r\n\t}\r\n}\r\n\r\nconst SPHERE_RADIUS = 13.65\r\nconst SPHERE_DEBUG = false // normal\r\n// const SPHERE_DEBUG = true // orbit show depth!\r\n\r\nclass ShelvesViewer_ extends _ViewModeBaseViewer__WEBPACK_IMPORTED_MODULE_0__.ViewModeBaseViewer {\r\n\r\n\tconstructor(opts) {\r\n\r\n\t\tsuper(Object.assign({\r\n\t\t\ttrend: {\r\n\t\t\t\thdr: true,\r\n\t\t\t},\r\n\t\t\tpicker: {\r\n\t\t\t\tuseHitsArray: true,\r\n\t\t\t},\r\n\t\t\t// manually_start_animate: true, // for loading\r\n\t\t\t// clzControls: MapControls,\r\n\t\t\tfov0: 55,\r\n\r\n\t\t\tclzBuilder: kutsi_util_BuilderEx__WEBPACK_IMPORTED_MODULE_1__.BuilderEx,\r\n\r\n\t\t\t// v2\r\n\t\t\t// assets: {\r\n\t\t\t// \tenv1: assets_env1,\r\n\t\t\t// }\r\n\r\n\t\t}, opts))\r\n\r\n\t\t// {//window aspect ratio!\r\n\t\t// \t// if (window.innerWidth / window.innerHeight < 1) {\r\n\t\t// \t// \tthis.opts_.fov0 = 75\r\n\t\t// \t// }\r\n\t\t// }\r\n\r\n\t\t// console.log('this.opts_', this.opts_)\r\n\r\n\t\tthis.shopData_ = this.opts_.shopData\r\n\r\n\t\tthis.isViewer__ = true\r\n\r\n\t\tthis.objects__ = new _si_SiObjects__WEBPACK_IMPORTED_MODULE_7__.SiObjects(this)\r\n\r\n\t\t// default 1 / 1000\r\n\t\tthis.observe_vtd_ = new kutsi_util_frame_ViewTransformDetector__WEBPACK_IMPORTED_MODULE_8__.ViewTransformDetector(1 / 100, false)\r\n\r\n\t}\r\n\r\n\tresize_() {\r\n\t\tsuper.resize_()\r\n\t\t// this.size_\r\n\r\n\t\ttry_mixin_two_fov_(this.camera_)\r\n\r\n\t\t// .5 -> 75\r\n\t\t// 2 -> 50\r\n\t\tlet aspect = this.size_.w / this.size_.h\r\n\t\tlet aspectFov = three__WEBPACK_IMPORTED_MODULE_11__.MathUtils.lerp(75, 50, three__WEBPACK_IMPORTED_MODULE_11__.MathUtils.smoothstep(aspect, .5, 2))\r\n\t\t// console.log('\\t', aspect, aspectFov)\r\n\r\n\t\tthis.camera_.aspectFov = aspectFov\r\n\t\t// this.camera_.aspectFov = 75 // for snapshot!\r\n\t\tthis.camera_.updateProjectionMatrix()\r\n\r\n\t}\r\n\r\n\tstartup() {\r\n\t\tsuper.startup()\r\n\t\t// this.controls_.enablePan = true\r\n\t\tthis.scene_.background = new three__WEBPACK_IMPORTED_MODULE_11__.Color(0xefefef)\r\n\t}\r\n\r\n\tbeginLoadSpecs() {\r\n\r\n\t\tlet arr = super.beginLoadSpecs()\r\n\r\n\t\tif (!this.is_hall__) {\r\n\r\n\t\t\t// #20230103\r\n\t\t\tlet panorama = this.shopData_.panorama\r\n\t\t\tif (panorama && panorama.enterZoom) {\r\n\t\t\t\tthis.camera_.zoomFov = 1 / panorama.enterZoom\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.geo_env_sphere__ = new three__WEBPACK_IMPORTED_MODULE_11__.SphereBufferGeometry(SPHERE_RADIUS, 256, 256)\r\n\t\t// this.geo_env_sphere__ = new SphereBufferGeometry(SPHERE_RADIUS, 512, 512)\r\n\t\tthis.mesh_env_sphere__ = null\r\n\r\n\t\tthis.cart_plane_ = new three__WEBPACK_IMPORTED_MODULE_11__.Plane(new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(-1, 0, 0), 2)\r\n\t\tthis.mesh_shelf__ = null\r\n\r\n\t\t// {// debug\r\n\t\t// \tthis.dump_keydown_after__ = () => {\r\n\t\t// \t\tconsole.log('shelf', this.mesh_shelf__)\r\n\t\t// \t}\r\n\t\t// }\r\n\r\n\t\tarr.push({\r\n\t\t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t\turl: _assets_white_256_png__WEBPACK_IMPORTED_MODULE_5__,\r\n\t\t\t\tonAfter: tex => {\r\n\t\t\t\t\tthis.w256_ = tex\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t})\r\n\r\n\t\t// this.DEFAULT_TARGET__ = new Vector3(0.1, -0.01, 0.00)\r\n\t\t// this.DEFAULT_TARGET__ = new Vector3(2.37, -0.41, 0.00)\r\n\t\tthis.DEFAULT_TARGET__ = new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(2.37, -0.31, 0.00)\r\n\r\n\t\tthis.specs_item_cust_controls_(arr)\r\n\r\n\t\tthis.specs_shop_data_base_(arr)\r\n\r\n\t\tlet shelf0 = (0,_common_util__WEBPACK_IMPORTED_MODULE_6__.get_shelf_0_)(this.shopData_)\r\n\t\tif (shelf0) {\r\n\r\n\t\t\tlet shelf_url = shelf0.url\r\n\t\t\tarr.push({\r\n\t\t\t\tfunc: 'setupModelGltf', param: {\r\n\t\t\t\t\tpath: shelf_url.substr(0, shelf_url.lastIndexOf('/')),\r\n\t\t\t\t\tname: shelf_url.substr(shelf_url.lastIndexOf('/')),\r\n\t\t\t\t\t// predefinedModel: (() => {\r\n\t\t\t\t\t// \tlet def = {\r\n\t\t\t\t\t// \t\tobjects_isolate_material: true,\r\n\t\t\t\t\t// \t\tmaps: {\r\n\t\t\t\t\t// \t\t\t'm1': { url: 'model/ao-2to1k-s4096/shelves_Bake1_CyclesBake_AO.png' }\r\n\t\t\t\t\t// \t\t},\r\n\t\t\t\t\t// \t\tobjects: {\r\n\t\t\t\t\t// \t\t\t'shelves': {\r\n\t\t\t\t\t// \t\t\t\tlightMap: 'm1'\r\n\t\t\t\t\t// \t\t\t}\r\n\t\t\t\t\t// \t\t}\r\n\t\t\t\t\t// \t}\r\n\t\t\t\t\t// \treturn def\r\n\t\t\t\t\t// })(),\r\n\t\t\t\t\tonAfter: o3d => {\r\n\r\n\t\t\t\t\t\to3d.traverse(c => {\r\n\t\t\t\t\t\t\tif (c.isMesh) {\r\n\t\t\t\t\t\t\t\tif (c.material.aoMap) {\r\n\t\t\t\t\t\t\t\t\tc.material.lightMap = c.material.aoMap\r\n\t\t\t\t\t\t\t\t\t// c.material.aoMap = null\r\n\t\t\t\t\t\t\t\t\tc.material.lightMapIntensity = .5\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tc.material.side = three__WEBPACK_IMPORTED_MODULE_11__.FrontSide\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (/^box-\\d-\\d/.test(c.name)) {\r\n\t\t\t\t\t\t\t\tc.visible = false\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t})\r\n\r\n\t\t\t\t\t\tif (shelf0.position && shelf0.rotation) {\r\n\r\n\t\t\t\t\t\t\to3d.position.set(shelf0.position.x, shelf0.position.y, shelf0.position.z)\r\n\t\t\t\t\t\t\to3d.rotation.set(shelf0.rotation.x, shelf0.rotation.y, shelf0.rotation.z)\r\n\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\to3d.rotation.set(0, - Math.PI / 2, 0)\r\n\t\t\t\t\t\t\to3d.position.set(2.7, -1, 0)\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tthis.scene_.add(o3d)\r\n\r\n\t\t\t\t\t\t// ? 不用尝试解些模型内嵌的cells信息\r\n\r\n\t\t\t\t\t\tnew _common_ShelfO3dExt5__WEBPACK_IMPORTED_MODULE_9__.ShelfO3dExt5(this).setup(o3d, shelf0, { forceUpdate: false })\r\n\t\t\t\t\t\tthis.mesh_shelf__ = o3d\r\n\r\n\t\t\t\t\t\t// .$model__ = o3d\r\n\t\t\t\t\t\tshelf0.get_model__ = () => {\r\n\t\t\t\t\t\t\treturn o3d\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// dump_o3d(o3d)\r\n\t\t\t\t\t\t// can-2, box-2, pillow-2\r\n\r\n\t\t\t\t\t\t// create_sample_balls(balls => {\r\n\t\t\t\t\t\t// \tballs.position.set(2, -.25, 0)\r\n\t\t\t\t\t\t// \tthis.scene_.add(balls)\r\n\t\t\t\t\t\t// })\r\n\r\n\t\t\t\t\t\t// create_env_ball(ball => {\r\n\t\t\t\t\t\t// \tball.position.set(2, -.25, 0)\r\n\t\t\t\t\t\t// \tthis.scene_.add(ball)\r\n\t\t\t\t\t\t// })\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\r\n\t\t} else {\r\n\t\t\t// TODO 新建\r\n\t\t}\r\n\r\n\t\t// if (this.shopData_ && this.shopData_.commodities) {\r\n\r\n\t\t// \tthis.shopData_.commodities.forEach(mod => {\r\n\t\t// \t\tlet mod_url = mod.url\r\n\t\t// \t\tarr.push({\r\n\t\t// \t\t\tfunc: 'setupModelGltf', param: {\r\n\t\t// \t\t\t\tpath: mod_url.substr(0, mod_url.lastIndexOf('/')),\r\n\t\t// \t\t\t\tname: mod_url.substr(mod_url.lastIndexOf('/')),\r\n\t\t// \t\t\t\tonAfter: o3d => {\r\n\t\t// \t\t\t\t\to3d.traverse(c => {\r\n\t\t// \t\t\t\t\t\tif (c.isMesh) {\r\n\t\t// \t\t\t\t\t\t\tc.material.envMapIntensity = this.shopData_.panorama.multiply\r\n\t\t// \t\t\t\t\t\t\tc.material.side = FrontSide\r\n\t\t// \t\t\t\t\t\t}\r\n\t\t// \t\t\t\t\t})\r\n\t\t// \t\t\t\t\tif (!o3d.isMesh && o3d.children.length == 1) {\r\n\t\t// \t\t\t\t\t\t// 单个mesh, 需要导出时apply transform\r\n\t\t// \t\t\t\t\t\tmod.get_model__ = () => {\r\n\t\t// \t\t\t\t\t\t\treturn o3d.children[0]\r\n\t\t// \t\t\t\t\t\t}\r\n\t\t// \t\t\t\t\t} else {\r\n\t\t// \t\t\t\t\t\tmod.get_model__ = () => {\r\n\t\t// \t\t\t\t\t\t\treturn o3d\r\n\t\t// \t\t\t\t\t\t}\r\n\t\t// \t\t\t\t\t}\r\n\t\t// \t\t\t\t},\r\n\t\t// \t\t\t},\r\n\t\t// \t\t})\r\n\t\t// \t})\r\n\r\n\t\t// } else {\r\n\t\t// \t// TODO 新建\r\n\t\t// }\r\n\r\n\t\tif (this.shopData_ && this.shopData_.objects) {\r\n\t\t\tthis.objects__.attach_specs_for_load_(this.shopData_.objects, arr)\r\n\t\t}\r\n\r\n\t\tif (this.use_grid__) {\r\n\r\n\t\t\tlet grid = new three__WEBPACK_IMPORTED_MODULE_11__.GridHelper(4, 8)\r\n\t\t\t// grid.position.set(0, -5, 0)\r\n\t\t\tgrid.position.set(0, -1, 0)\r\n\t\t\tthis.scene_.add(grid)\r\n\r\n\t\t\t// let box = new Mesh(\r\n\t\t\t// \tnew BoxBufferGeometry(1.5, 1.5, .5),\r\n\t\t\t// \tnew MeshStandardMaterial({\r\n\t\t\t// \t\twireframe: true,\r\n\t\t\t// \t})\r\n\t\t\t// )\r\n\t\t\t// box.rotation.set(0, Math.PI / 2, 0)\r\n\t\t\t// box.position.set(2.25, -.25, 0)\r\n\t\t\t// this.scene_.add(box)\r\n\r\n\t\t}\r\n\r\n\t\t// cart plane !\r\n\r\n\r\n\t\treturn arr\r\n\t}\r\n\r\n\t// @can be override\r\n\tspecs_item_cust_controls_(arr) {\r\n\r\n\t\tarr.push({\r\n\t\t\tfunc: 'setupCustomization', param: {\r\n\t\t\t\tonDoing: next => {\r\n\r\n\t\t\t\t\t// this.scene_.fog = new Fog(this.theme_.fogColor, 400, 800)\r\n\r\n\t\t\t\t\t// this.controls_.minPolarAngle = 0\r\n\t\t\t\t\t// this.controls_.maxPolarAngle = Math.PI * .67\r\n\t\t\t\t\t// this.controls_.maxDistance = 400\r\n\r\n\t\t\t\t\t// this.scene_.add(new AxesHelper(10))\r\n\r\n\t\t\t\t\tlet target = this.DEFAULT_TARGET__\r\n\r\n\t\t\t\t\tif (SPHERE_DEBUG) { // debug\r\n\t\t\t\t\t\tthis.updateViewerLookat({\r\n\t\t\t\t\t\t\tposition: new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(-1, 0.1, 0.00),\r\n\t\t\t\t\t\t\ttarget: new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(0.00, 0.00, 0.00),\r\n\t\t\t\t\t\t\tforceUpdateNearFar: true,\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t\tthis.controls_.enablePan = true\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis.changeControls(\r\n\t\t\t\t\t\t\t// new FreeLookControls\r\n\t\t\t\t\t\t\tnew kutsi_shelves_controls_ElasticFreeLookControls__WEBPACK_IMPORTED_MODULE_2__[\"default\"]\r\n\t\t\t\t\t\t\t\t(this.camera_, this.renderer_.domElement, {\r\n\t\t\t\t\t\t\t\t\tlookDirection: -1,\r\n\t\t\t\t\t\t\t\t\telasticDirection: target,\r\n\t\t\t\t\t\t\t\t\tzoomResetFunction: e => {\r\n\t\t\t\t\t\t\t\t\t\treturn e.object.zoomFov\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\tzoomFunction: e => {\r\n\t\t\t\t\t\t\t\t\t\te.object.zoomFov = e.zoom2\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\tzoomMin: 1 / 2,\r\n\t\t\t\t\t\t\t\t\tzoomMax: 1 / .75, // .75 源自于 enterZoom的最小值\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t}))\r\n\r\n\t\t\t\t\t\tthis.updateViewerLookat({\r\n\t\t\t\t\t\t\t// position: new Vector3(-0.1, 0.01, 0.00),\r\n\t\t\t\t\t\t\t// target: new Vector3(0.00, 0.00, 0.00),\r\n\t\t\t\t\t\t\tposition: new three__WEBPACK_IMPORTED_MODULE_11__.Vector3(0.00, 0.00, 0.00),\r\n\t\t\t\t\t\t\ttarget,\r\n\t\t\t\t\t\t\tforceUpdateNearFar: true,\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tnext()\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t})\r\n\r\n\r\n\t}\r\n\r\n\tspecs_shop_data_base_(arr) {\r\n\r\n\t\tif (this.shopData_ && this.shopData_.panorama) {\r\n\r\n\t\t\t// if (this.shopData_.panorama.urlEnv) {\r\n\t\t\t// \tarr.push({\r\n\t\t\t// \t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t// \t\t\turl: `${this.shopData_.panorama.url}`,\r\n\t\t\t// \t\t\tonAfter: tex => {\r\n\t\t\t// \t\t\t\tthis.scene_.background = tex\r\n\t\t\t// \t\t\t\t// this.scene_.environment = tex\r\n\t\t\t// \t\t\t}\r\n\t\t\t// \t\t}\r\n\t\t\t// \t})\r\n\t\t\t// \tarr.push({\r\n\t\t\t// \t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t// \t\t\turl: `${this.shopData_.panorama.urlEnv}`,\r\n\t\t\t// \t\t\tonAfter: tex => {\r\n\t\t\t// \t\t\t\t// this.scene_.background = tex\r\n\t\t\t// \t\t\t\tthis.scene_.environment = tex\r\n\t\t\t// \t\t\t}\r\n\t\t\t// \t\t}\r\n\t\t\t// \t})\r\n\r\n\t\t\t// } else {\r\n\r\n\t\t\tlet panorama_shelf_exr = this.shopData_.panorama.urlShelfExr\r\n\t\t\tarr.push({\r\n\t\t\t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t\t\turl: `${this.get_panorama_url_(this.shopData_.panorama)}`,\r\n\t\t\t\t\tonAfter: tex => {\r\n\t\t\t\t\t\t// this.scene_.background = tex\r\n\t\t\t\t\t\t// for rotationY\r\n\r\n\t\t\t\t\t\tlet sp = new three__WEBPACK_IMPORTED_MODULE_11__.Mesh(\r\n\t\t\t\t\t\t\t// new SphereBufferGeometry(20, 256, 256),\r\n\t\t\t\t\t\t\tthis.geo_env_sphere__,\r\n\t\t\t\t\t\t\tnew three__WEBPACK_IMPORTED_MODULE_11__.MeshStandardMaterial({\r\n\t\t\t\t\t\t\t\tmap: tex,\r\n\t\t\t\t\t\t\t\tside: three__WEBPACK_IMPORTED_MODULE_11__.BackSide,\r\n\t\t\t\t\t\t\t\t// wireframe: true,\r\n\t\t\t\t\t\t\t\tfog: false,\r\n\t\t\t\t\t\t\t\t// displacementScale: -env_.radius * .992,\r\n\t\t\t\t\t\t\t\t// displacementMap: new TextureLoader().load(`${this.prefixAsset_}/env/equirect/${env_.code}-zdepth-1k.png`),\r\n\t\t\t\t\t\t\t\tdisplacementScale: - SPHERE_RADIUS,\r\n\t\t\t\t\t\t\t\tdisplacementMap: new three__WEBPACK_IMPORTED_MODULE_11__.TextureLoader().load(`${this.shopData_.panorama.urlDepth}`),\r\n\t\t\t\t\t\t\t\tenvMap: this.w256_,\r\n\t\t\t\t\t\t\t\t// envMapIntensity: 2,\r\n\t\t\t\t\t\t\t})\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t\tsp.scale.set(1, 1, -1)\r\n\t\t\t\t\t\t// sp.name = 'sys-env-sphere-'\r\n\t\t\t\t\t\t;(0,_common_SceneTags__WEBPACK_IMPORTED_MODULE_10__.addTag)(sp, _common_SceneTags__WEBPACK_IMPORTED_MODULE_10__.TAG_SYS_ENV)\r\n\t\t\t\t\t\tthis.scene_.add(sp)\r\n\r\n\t\t\t\t\t\tthis.mesh_env_sphere__ = sp\r\n\t\t\t\t\t\tthis.mesh_env_sphere__.rotation.y = this.shopData_.panorama.rotationY * Math.PI / 180\r\n\r\n\t\t\t\t\t\tif (!panorama_shelf_exr) {\r\n\t\t\t\t\t\t\tthis.scene_.environment = tex\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tthis.light_source_manager_.setup_panorama_default_env_tex_(tex)\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t\tif (panorama_shelf_exr) {\r\n\t\t\t\tarr.push({\r\n\t\t\t\t\tfunc: 'setupEnvEquirect', param: {\r\n\t\t\t\t\t\turl: `${panorama_shelf_exr}`,\r\n\t\t\t\t\t\tonAfter: tex => {\r\n\t\t\t\t\t\t\tthis.scene_.environment = tex\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// }\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// TODO 新增时\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tget_panorama_url_(panorama) {\r\n\t\tif (this.isViewer__) {\r\n\t\t\treturn _common_util__WEBPACK_IMPORTED_MODULE_6__.isMobile ? panorama.urlSmall : panorama.url\r\n\t\t} else {\r\n\t\t\treturn panorama.urlSmall // 編輯器頻繁dispose,減少開銷\r\n\t\t}\r\n\t}\r\n\r\n\tbefore_render_(time, delta) {\r\n\t\tsuper.before_render_(time, delta)\r\n\r\n\t\tlet result = this.observe_vtd_.updateResult(this)\r\n\t\tif (result) {\r\n\t\t\t// console.log(data) \r\n\t\t\tthis.emit('roughViewChanged', result)\r\n\t\t}\r\n\r\n\t\t// if (this.mesh_env_sphere__) { // just for render test!\r\n\t\t// \tthis.mesh_env_sphere__.rotation.y += delta\r\n\t\t// }\r\n\t}\r\n\r\n\tdispose() {\r\n\t\tif (this.objects__) {\r\n\t\t\tthis.objects__.dispose()\r\n\t\t}\r\n\t\tsuper.dispose()\r\n\t\tconsole.log('viewer dispose!')\r\n\t}\r\n\r\n}\r\n\r\n\n\n//# sourceURL=webpack://shelves/./src/crossyo/shelves/viewer/ShelvesViewer_.js?"); /***/ }), @@ -865,17 +865,6 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ }), -/***/ "./node_modules/_three@0.139.2@three/examples/jsm/loaders/gltfloader.js": -/*!******************************************************************************!*\ - !*** ./node_modules/_three@0.139.2@three/examples/jsm/loaders/gltfloader.js ***! - \******************************************************************************/ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"GLTFLoader\": () => (/* binding */ GLTFLoader)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! three */ \"./node_modules/_three@0.139.2@three/build/three.module.js\");\n\n\nclass GLTFLoader extends three__WEBPACK_IMPORTED_MODULE_0__.Loader {\n\n\tconstructor( manager ) {\n\n\t\tsuper( manager );\n\n\t\tthis.dracoLoader = null;\n\t\tthis.ktx2Loader = null;\n\t\tthis.meshoptDecoder = null;\n\n\t\tthis.pluginCallbacks = [];\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsClearcoatExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureBasisUExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFTextureWebPExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsSheenExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsTransmissionExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsVolumeExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsIorExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMaterialsSpecularExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFLightsExtension( parser );\n\n\t\t} );\n\n\t\tthis.register( function ( parser ) {\n\n\t\t\treturn new GLTFMeshoptCompression( parser );\n\n\t\t} );\n\n\t}\n\n\tload( url, onLoad, onProgress, onError ) {\n\n\t\tconst scope = this;\n\n\t\tlet resourcePath;\n\n\t\tif ( this.resourcePath !== '' ) {\n\n\t\t\tresourcePath = this.resourcePath;\n\n\t\t} else if ( this.path !== '' ) {\n\n\t\t\tresourcePath = this.path;\n\n\t\t} else {\n\n\t\t\tresourcePath = three__WEBPACK_IMPORTED_MODULE_0__.LoaderUtils.extractUrlBase( url );\n\n\t\t}\n\n\t\t// Tells the LoadingManager to track an extra item, which resolves after\n\t\t// the model is fully loaded. This means the count of items loaded will\n\t\t// be incorrect, but ensures manager.onLoad() does not fire early.\n\t\tthis.manager.itemStart( url );\n\n\t\tconst _onError = function ( e ) {\n\n\t\t\tif ( onError ) {\n\n\t\t\t\tonError( e );\n\n\t\t\t} else {\n\n\t\t\t\tconsole.error( e );\n\n\t\t\t}\n\n\t\t\tscope.manager.itemError( url );\n\t\t\tscope.manager.itemEnd( url );\n\n\t\t};\n\n\t\tconst loader = new three__WEBPACK_IMPORTED_MODULE_0__.FileLoader( this.manager );\n\n\t\tloader.setPath( this.path );\n\t\tloader.setResponseType( 'arraybuffer' );\n\t\tloader.setRequestHeader( this.requestHeader );\n\t\tloader.setWithCredentials( this.withCredentials );\n\n\t\tloader.load( url, function ( data ) {\n\n\t\t\ttry {\n\n\t\t\t\tscope.parse( data, resourcePath, function ( gltf ) {\n\n\t\t\t\t\tonLoad( gltf );\n\n\t\t\t\t\tscope.manager.itemEnd( url );\n\n\t\t\t\t}, _onError );\n\n\t\t\t} catch ( e ) {\n\n\t\t\t\t_onError( e );\n\n\t\t\t}\n\n\t\t}, onProgress, _onError );\n\n\t}\n\n\tsetDRACOLoader( dracoLoader ) {\n\n\t\tthis.dracoLoader = dracoLoader;\n\t\treturn this;\n\n\t}\n\n\tsetDDSLoader() {\n\n\t\tthrow new Error(\n\n\t\t\t'THREE.GLTFLoader: \"MSFT_texture_dds\" no longer supported. Please update to \"KHR_texture_basisu\".'\n\n\t\t);\n\n\t}\n\n\tsetKTX2Loader( ktx2Loader ) {\n\n\t\tthis.ktx2Loader = ktx2Loader;\n\t\treturn this;\n\n\t}\n\n\tsetMeshoptDecoder( meshoptDecoder ) {\n\n\t\tthis.meshoptDecoder = meshoptDecoder;\n\t\treturn this;\n\n\t}\n\n\tregister( callback ) {\n\n\t\tif ( this.pluginCallbacks.indexOf( callback ) === - 1 ) {\n\n\t\t\tthis.pluginCallbacks.push( callback );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\tunregister( callback ) {\n\n\t\tif ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) {\n\n\t\t\tthis.pluginCallbacks.splice( this.pluginCallbacks.indexOf( callback ), 1 );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n\tparse( data, path, onLoad, onError ) {\n\n\t\tlet content;\n\t\tconst extensions = {};\n\t\tconst plugins = {};\n\n\t\tif ( typeof data === 'string' ) {\n\n\t\t\tcontent = data;\n\n\t\t} else {\n\n\t\t\tconst magic = three__WEBPACK_IMPORTED_MODULE_0__.LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );\n\n\t\t\tif ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\t\ttry {\n\n\t\t\t\t\textensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );\n\n\t\t\t\t} catch ( error ) {\n\n\t\t\t\t\tif ( onError ) onError( error );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tcontent = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;\n\n\t\t\t} else {\n\n\t\t\t\tcontent = three__WEBPACK_IMPORTED_MODULE_0__.LoaderUtils.decodeText( new Uint8Array( data ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\tconst json = JSON.parse( content );\n\n\t\tif ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {\n\n\t\t\tif ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );\n\t\t\treturn;\n\n\t\t}\n\n\t\tconst parser = new GLTFParser( json, {\n\n\t\t\tpath: path || this.resourcePath || '',\n\t\t\tcrossOrigin: this.crossOrigin,\n\t\t\trequestHeader: this.requestHeader,\n\t\t\tmanager: this.manager,\n\t\t\tktx2Loader: this.ktx2Loader,\n\t\t\tmeshoptDecoder: this.meshoptDecoder\n\n\t\t} );\n\n\t\tparser.fileLoader.setRequestHeader( this.requestHeader );\n\n\t\tfor ( let i = 0; i < this.pluginCallbacks.length; i ++ ) {\n\n\t\t\tconst plugin = this.pluginCallbacks[ i ]( parser );\n\t\t\tplugins[ plugin.name ] = plugin;\n\n\t\t\t// Workaround to avoid determining as unknown extension\n\t\t\t// in addUnknownExtensionsToUserData().\n\t\t\t// Remove this workaround if we move all the existing\n\t\t\t// extension handlers to plugin system\n\t\t\textensions[ plugin.name ] = true;\n\n\t\t}\n\n\t\tif ( json.extensionsUsed ) {\n\n\t\t\tfor ( let i = 0; i < json.extensionsUsed.length; ++ i ) {\n\n\t\t\t\tconst extensionName = json.extensionsUsed[ i ];\n\t\t\t\tconst extensionsRequired = json.extensionsRequired || [];\n\n\t\t\t\tswitch ( extensionName ) {\n\n\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_UNLIT:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsUnlitExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_TEXTURE_TRANSFORM:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFTextureTransformExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase EXTENSIONS.KHR_MESH_QUANTIZATION:\n\t\t\t\t\t\textensions[ extensionName ] = new GLTFMeshQuantizationExtension();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tif ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) {\n\n\t\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Unknown extension \"' + extensionName + '\".' );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tparser.setExtensions( extensions );\n\t\tparser.setPlugins( plugins );\n\t\tparser.parse( onLoad, onError );\n\n\t}\n\n\tparseAsync( data, path ) {\n\n\t\tconst scope = this;\n\n\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\tscope.parse( data, path, resolve, reject );\n\n\t\t} );\n\n\t}\n\n}\n\n/* GLTFREGISTRY */\n\nfunction GLTFRegistry() {\n\n\tlet objects = {};\n\n\treturn\t{\n\n\t\tget: function ( key ) {\n\n\t\t\treturn objects[ key ];\n\n\t\t},\n\n\t\tadd: function ( key, object ) {\n\n\t\t\tobjects[ key ] = object;\n\n\t\t},\n\n\t\tremove: function ( key ) {\n\n\t\t\tdelete objects[ key ];\n\n\t\t},\n\n\t\tremoveAll: function () {\n\n\t\t\tobjects = {};\n\n\t\t}\n\n\t};\n\n}\n\n/*********************************/\n/********** EXTENSIONS ***********/\n/*********************************/\n\nconst EXTENSIONS = {\n\tKHR_BINARY_GLTF: 'KHR_binary_glTF',\n\tKHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',\n\tKHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',\n\tKHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',\n\tKHR_MATERIALS_IOR: 'KHR_materials_ior',\n\tKHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',\n\tKHR_MATERIALS_SHEEN: 'KHR_materials_sheen',\n\tKHR_MATERIALS_SPECULAR: 'KHR_materials_specular',\n\tKHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',\n\tKHR_MATERIALS_UNLIT: 'KHR_materials_unlit',\n\tKHR_MATERIALS_VOLUME: 'KHR_materials_volume',\n\tKHR_TEXTURE_BASISU: 'KHR_texture_basisu',\n\tKHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',\n\tKHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',\n\tEXT_TEXTURE_WEBP: 'EXT_texture_webp',\n\tEXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression'\n};\n\n/**\n * Punctual Lights Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual\n */\nclass GLTFLightsExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;\n\n\t\t// Object3D instance caches\n\t\tthis.cache = { refs: {}, uses: {} };\n\n\t}\n\n\t_markDefs() {\n\n\t\tconst parser = this.parser;\n\t\tconst nodeDefs = this.parser.json.nodes || [];\n\n\t\tfor ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {\n\n\t\t\tconst nodeDef = nodeDefs[ nodeIndex ];\n\n\t\t\tif ( nodeDef.extensions\n\t\t\t\t\t&& nodeDef.extensions[ this.name ]\n\t\t\t\t\t&& nodeDef.extensions[ this.name ].light !== undefined ) {\n\n\t\t\t\tparser._addNodeRef( this.cache, nodeDef.extensions[ this.name ].light );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t_loadLight( lightIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst cacheKey = 'light:' + lightIndex;\n\t\tlet dependency = parser.cache.get( cacheKey );\n\n\t\tif ( dependency ) return dependency;\n\n\t\tconst json = parser.json;\n\t\tconst extensions = ( json.extensions && json.extensions[ this.name ] ) || {};\n\t\tconst lightDefs = extensions.lights || [];\n\t\tconst lightDef = lightDefs[ lightIndex ];\n\t\tlet lightNode;\n\n\t\tconst color = new three__WEBPACK_IMPORTED_MODULE_0__.Color( 0xffffff );\n\n\t\tif ( lightDef.color !== undefined ) color.fromArray( lightDef.color );\n\n\t\tconst range = lightDef.range !== undefined ? lightDef.range : 0;\n\n\t\tswitch ( lightDef.type ) {\n\n\t\t\tcase 'directional':\n\t\t\t\tlightNode = new three__WEBPACK_IMPORTED_MODULE_0__.DirectionalLight( color );\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tcase 'point':\n\t\t\t\tlightNode = new three__WEBPACK_IMPORTED_MODULE_0__.PointLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\tbreak;\n\n\t\t\tcase 'spot':\n\t\t\t\tlightNode = new three__WEBPACK_IMPORTED_MODULE_0__.SpotLight( color );\n\t\t\t\tlightNode.distance = range;\n\t\t\t\t// Handle spotlight properties.\n\t\t\t\tlightDef.spot = lightDef.spot || {};\n\t\t\t\tlightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;\n\t\t\t\tlightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;\n\t\t\t\tlightNode.angle = lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\n\t\t\t\tlightNode.add( lightNode.target );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Unexpected light type: ' + lightDef.type );\n\n\t\t}\n\n\t\t// Some lights (e.g. spot) default to a position other than the origin. Reset the position\n\t\t// here, because node-level parsing will only override position if explicitly specified.\n\t\tlightNode.position.set( 0, 0, 0 );\n\n\t\tlightNode.decay = 2;\n\n\t\tif ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;\n\n\t\tlightNode.name = parser.createUniqueName( lightDef.name || ( 'light_' + lightIndex ) );\n\n\t\tdependency = Promise.resolve( lightNode );\n\n\t\tparser.cache.add( cacheKey, dependency );\n\n\t\treturn dependency;\n\n\t}\n\n\tcreateNodeAttachment( nodeIndex ) {\n\n\t\tconst self = this;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\t\tconst lightDef = ( nodeDef.extensions && nodeDef.extensions[ this.name ] ) || {};\n\t\tconst lightIndex = lightDef.light;\n\n\t\tif ( lightIndex === undefined ) return null;\n\n\t\treturn this._loadLight( lightIndex ).then( function ( light ) {\n\n\t\t\treturn parser._getNodeRef( self.cache, lightIndex, light );\n\n\t\t} );\n\n\t}\n\n}\n\n/**\n * Unlit Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit\n */\nclass GLTFMaterialsUnlitExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_UNLIT;\n\n\t}\n\n\tgetMaterialType() {\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshBasicMaterial;\n\n\t}\n\n\textendParams( materialParams, materialDef, parser ) {\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.color = new three__WEBPACK_IMPORTED_MODULE_0__.Color( 1.0, 1.0, 1.0 );\n\t\tmaterialParams.opacity = 1.0;\n\n\t\tconst metallicRoughness = materialDef.pbrMetallicRoughness;\n\n\t\tif ( metallicRoughness ) {\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tconst array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.fromArray( array );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, three__WEBPACK_IMPORTED_MODULE_0__.sRGBEncoding ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Clearcoat Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat\n */\nclass GLTFMaterialsClearcoatExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshPhysicalMaterial;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {\n\n\t\t\treturn Promise.resolve();\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tconst extension = materialDef.extensions[ this.name ];\n\n\t\tif ( extension.clearcoatFactor !== undefined ) {\n\n\t\t\tmaterialParams.clearcoat = extension.clearcoatFactor;\n\n\t\t}\n\n\t\tif ( extension.clearcoatTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) );\n\n\t\t}\n\n\t\tif ( extension.clearcoatRoughnessFactor !== undefined ) {\n\n\t\t\tmaterialParams.clearcoatRoughness = extension.clearcoatRoughnessFactor;\n\n\t\t}\n\n\t\tif ( extension.clearcoatRoughnessTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) );\n\n\t\t}\n\n\t\tif ( extension.clearcoatNormalTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) );\n\n\t\t\tif ( extension.clearcoatNormalTexture.scale !== undefined ) {\n\n\t\t\t\tconst scale = extension.clearcoatNormalTexture.scale;\n\n\t\t\t\tmaterialParams.clearcoatNormalScale = new three__WEBPACK_IMPORTED_MODULE_0__.Vector2( scale, scale );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Sheen Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_sheen\n */\nclass GLTFMaterialsSheenExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_SHEEN;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshPhysicalMaterial;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {\n\n\t\t\treturn Promise.resolve();\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tmaterialParams.sheenColor = new three__WEBPACK_IMPORTED_MODULE_0__.Color( 0, 0, 0 );\n\t\tmaterialParams.sheenRoughness = 0;\n\t\tmaterialParams.sheen = 1;\n\n\t\tconst extension = materialDef.extensions[ this.name ];\n\n\t\tif ( extension.sheenColorFactor !== undefined ) {\n\n\t\t\tmaterialParams.sheenColor.fromArray( extension.sheenColorFactor );\n\n\t\t}\n\n\t\tif ( extension.sheenRoughnessFactor !== undefined ) {\n\n\t\t\tmaterialParams.sheenRoughness = extension.sheenRoughnessFactor;\n\n\t\t}\n\n\t\tif ( extension.sheenColorTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, three__WEBPACK_IMPORTED_MODULE_0__.sRGBEncoding ) );\n\n\t\t}\n\n\t\tif ( extension.sheenRoughnessTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Transmission Materials Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission\n * Draft: https://github.com/KhronosGroup/glTF/pull/1698\n */\nclass GLTFMaterialsTransmissionExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshPhysicalMaterial;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {\n\n\t\t\treturn Promise.resolve();\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tconst extension = materialDef.extensions[ this.name ];\n\n\t\tif ( extension.transmissionFactor !== undefined ) {\n\n\t\t\tmaterialParams.transmission = extension.transmissionFactor;\n\n\t\t}\n\n\t\tif ( extension.transmissionTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials Volume Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume\n */\nclass GLTFMaterialsVolumeExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_VOLUME;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshPhysicalMaterial;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {\n\n\t\t\treturn Promise.resolve();\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tconst extension = materialDef.extensions[ this.name ];\n\n\t\tmaterialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;\n\n\t\tif ( extension.thicknessTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );\n\n\t\t}\n\n\t\tmaterialParams.attenuationDistance = extension.attenuationDistance || 0;\n\n\t\tconst colorArray = extension.attenuationColor || [ 1, 1, 1 ];\n\t\tmaterialParams.attenuationColor = new three__WEBPACK_IMPORTED_MODULE_0__.Color( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ] );\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * Materials ior Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_ior\n */\nclass GLTFMaterialsIorExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_IOR;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshPhysicalMaterial;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {\n\n\t\t\treturn Promise.resolve();\n\n\t\t}\n\n\t\tconst extension = materialDef.extensions[ this.name ];\n\n\t\tmaterialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;\n\n\t\treturn Promise.resolve();\n\n\t}\n\n}\n\n/**\n * Materials specular Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_specular\n */\nclass GLTFMaterialsSpecularExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_SPECULAR;\n\n\t}\n\n\tgetMaterialType( materialIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshPhysicalMaterial;\n\n\t}\n\n\textendMaterialParams( materialIndex, materialParams ) {\n\n\t\tconst parser = this.parser;\n\t\tconst materialDef = parser.json.materials[ materialIndex ];\n\n\t\tif ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {\n\n\t\t\treturn Promise.resolve();\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tconst extension = materialDef.extensions[ this.name ];\n\n\t\tmaterialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0;\n\n\t\tif ( extension.specularTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );\n\n\t\t}\n\n\t\tconst colorArray = extension.specularColorFactor || [ 1, 1, 1 ];\n\t\tmaterialParams.specularColor = new three__WEBPACK_IMPORTED_MODULE_0__.Color( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ] );\n\n\t\tif ( extension.specularColorTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, three__WEBPACK_IMPORTED_MODULE_0__.sRGBEncoding ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n}\n\n/**\n * BasisU Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu\n */\nclass GLTFTextureBasisUExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_BASISU;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ this.name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ this.name ];\n\t\tconst loader = parser.options.ktx2Loader;\n\n\t\tif ( ! loader ) {\n\n\t\t\tif ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {\n\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures' );\n\n\t\t\t} else {\n\n\t\t\t\t// Assumes that the extension is optional and that a fallback texture is present\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t}\n\n}\n\n/**\n * WebP Texture Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_webp\n */\nclass GLTFTextureWebPExtension {\n\n\tconstructor( parser ) {\n\n\t\tthis.parser = parser;\n\t\tthis.name = EXTENSIONS.EXT_TEXTURE_WEBP;\n\t\tthis.isSupported = null;\n\n\t}\n\n\tloadTexture( textureIndex ) {\n\n\t\tconst name = this.name;\n\t\tconst parser = this.parser;\n\t\tconst json = parser.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\n\t\tif ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tconst extension = textureDef.extensions[ name ];\n\t\tconst source = json.images[ extension.source ];\n\n\t\tlet loader = parser.textureLoader;\n\t\tif ( source.uri ) {\n\n\t\t\tconst handler = parser.options.manager.getHandler( source.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn this.detectSupport().then( function ( isSupported ) {\n\n\t\t\tif ( isSupported ) return parser.loadTextureImage( textureIndex, extension.source, loader );\n\n\t\t\tif ( json.extensionsRequired && json.extensionsRequired.indexOf( name ) >= 0 ) {\n\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: WebP required by asset but unsupported.' );\n\n\t\t\t}\n\n\t\t\t// Fall back to PNG or JPEG.\n\t\t\treturn parser.loadTexture( textureIndex );\n\n\t\t} );\n\n\t}\n\n\tdetectSupport() {\n\n\t\tif ( ! this.isSupported ) {\n\n\t\t\tthis.isSupported = new Promise( function ( resolve ) {\n\n\t\t\t\tconst image = new Image();\n\n\t\t\t\t// Lossy test image. Support for lossy images doesn't guarantee support for all\n\t\t\t\t// WebP images, unfortunately.\n\t\t\t\timage.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';\n\n\t\t\t\timage.onload = image.onerror = function () {\n\n\t\t\t\t\tresolve( image.height === 1 );\n\n\t\t\t\t};\n\n\t\t\t} );\n\n\t\t}\n\n\t\treturn this.isSupported;\n\n\t}\n\n}\n\n/**\n * meshopt BufferView Compression Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression\n */\nclass GLTFMeshoptCompression {\n\n\tconstructor( parser ) {\n\n\t\tthis.name = EXTENSIONS.EXT_MESHOPT_COMPRESSION;\n\t\tthis.parser = parser;\n\n\t}\n\n\tloadBufferView( index ) {\n\n\t\tconst json = this.parser.json;\n\t\tconst bufferView = json.bufferViews[ index ];\n\n\t\tif ( bufferView.extensions && bufferView.extensions[ this.name ] ) {\n\n\t\t\tconst extensionDef = bufferView.extensions[ this.name ];\n\n\t\t\tconst buffer = this.parser.getDependency( 'buffer', extensionDef.buffer );\n\t\t\tconst decoder = this.parser.options.meshoptDecoder;\n\n\t\t\tif ( ! decoder || ! decoder.supported ) {\n\n\t\t\t\tif ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {\n\n\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files' );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Assumes that the extension is optional and that fallback buffer data is present\n\t\t\t\t\treturn null;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn Promise.all( [ buffer, decoder.ready ] ).then( function ( res ) {\n\n\t\t\t\tconst byteOffset = extensionDef.byteOffset || 0;\n\t\t\t\tconst byteLength = extensionDef.byteLength || 0;\n\n\t\t\t\tconst count = extensionDef.count;\n\t\t\t\tconst stride = extensionDef.byteStride;\n\n\t\t\t\tconst result = new ArrayBuffer( count * stride );\n\t\t\t\tconst source = new Uint8Array( res[ 0 ], byteOffset, byteLength );\n\n\t\t\t\tdecoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter );\n\t\t\t\treturn result;\n\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t}\n\n}\n\n/* BINARY EXTENSION */\nconst BINARY_EXTENSION_HEADER_MAGIC = 'glTF';\nconst BINARY_EXTENSION_HEADER_LENGTH = 12;\nconst BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };\n\nclass GLTFBinaryExtension {\n\n\tconstructor( data ) {\n\n\t\tthis.name = EXTENSIONS.KHR_BINARY_GLTF;\n\t\tthis.content = null;\n\t\tthis.body = null;\n\n\t\tconst headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );\n\n\t\tthis.header = {\n\t\t\tmagic: three__WEBPACK_IMPORTED_MODULE_0__.LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ),\n\t\t\tversion: headerView.getUint32( 4, true ),\n\t\t\tlength: headerView.getUint32( 8, true )\n\t\t};\n\n\t\tif ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );\n\n\t\t} else if ( this.header.version < 2.0 ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );\n\n\t\t}\n\n\t\tconst chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH;\n\t\tconst chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );\n\t\tlet chunkIndex = 0;\n\n\t\twhile ( chunkIndex < chunkContentsLength ) {\n\n\t\t\tconst chunkLength = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tconst chunkType = chunkView.getUint32( chunkIndex, true );\n\t\t\tchunkIndex += 4;\n\n\t\t\tif ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {\n\n\t\t\t\tconst contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );\n\t\t\t\tthis.content = three__WEBPACK_IMPORTED_MODULE_0__.LoaderUtils.decodeText( contentArray );\n\n\t\t\t} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {\n\n\t\t\t\tconst byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;\n\t\t\t\tthis.body = data.slice( byteOffset, byteOffset + chunkLength );\n\n\t\t\t}\n\n\t\t\t// Clients must ignore chunks with unknown types.\n\n\t\t\tchunkIndex += chunkLength;\n\n\t\t}\n\n\t\tif ( this.content === null ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: JSON content not found.' );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * DRACO Mesh Compression Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression\n */\nclass GLTFDracoMeshCompressionExtension {\n\n\tconstructor( json, dracoLoader ) {\n\n\t\tif ( ! dracoLoader ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );\n\n\t\t}\n\n\t\tthis.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;\n\t\tthis.json = json;\n\t\tthis.dracoLoader = dracoLoader;\n\t\tthis.dracoLoader.preload();\n\n\t}\n\n\tdecodePrimitive( primitive, parser ) {\n\n\t\tconst json = this.json;\n\t\tconst dracoLoader = this.dracoLoader;\n\t\tconst bufferViewIndex = primitive.extensions[ this.name ].bufferView;\n\t\tconst gltfAttributeMap = primitive.extensions[ this.name ].attributes;\n\t\tconst threeAttributeMap = {};\n\t\tconst attributeNormalizedMap = {};\n\t\tconst attributeTypeMap = {};\n\n\t\tfor ( const attributeName in gltfAttributeMap ) {\n\n\t\t\tconst threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\n\n\t\t\tthreeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];\n\n\t\t}\n\n\t\tfor ( const attributeName in primitive.attributes ) {\n\n\t\t\tconst threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\n\n\t\t\tif ( gltfAttributeMap[ attributeName ] !== undefined ) {\n\n\t\t\t\tconst accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];\n\t\t\t\tconst componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t\tattributeTypeMap[ threeAttributeName ] = componentType;\n\t\t\t\tattributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {\n\n\t\t\treturn new Promise( function ( resolve ) {\n\n\t\t\t\tdracoLoader.decodeDracoFile( bufferView, function ( geometry ) {\n\n\t\t\t\t\tfor ( const attributeName in geometry.attributes ) {\n\n\t\t\t\t\t\tconst attribute = geometry.attributes[ attributeName ];\n\t\t\t\t\t\tconst normalized = attributeNormalizedMap[ attributeName ];\n\n\t\t\t\t\t\tif ( normalized !== undefined ) attribute.normalized = normalized;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve( geometry );\n\n\t\t\t\t}, threeAttributeMap, attributeTypeMap );\n\n\t\t\t} );\n\n\t\t} );\n\n\t}\n\n}\n\n/**\n * Texture Transform Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform\n */\nclass GLTFTextureTransformExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;\n\n\t}\n\n\textendTexture( texture, transform ) {\n\n\t\tif ( transform.texCoord !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Custom UV sets in \"' + this.name + '\" extension not yet supported.' );\n\n\t\t}\n\n\t\tif ( transform.offset === undefined && transform.rotation === undefined && transform.scale === undefined ) {\n\n\t\t\t// See https://github.com/mrdoob/three.js/issues/21819.\n\t\t\treturn texture;\n\n\t\t}\n\n\t\ttexture = texture.clone();\n\n\t\tif ( transform.offset !== undefined ) {\n\n\t\t\ttexture.offset.fromArray( transform.offset );\n\n\t\t}\n\n\t\tif ( transform.rotation !== undefined ) {\n\n\t\t\ttexture.rotation = transform.rotation;\n\n\t\t}\n\n\t\tif ( transform.scale !== undefined ) {\n\n\t\t\ttexture.repeat.fromArray( transform.scale );\n\n\t\t}\n\n\t\ttexture.needsUpdate = true;\n\n\t\treturn texture;\n\n\t}\n\n}\n\n/**\n * Specular-Glossiness Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness\n */\n\n/**\n * A sub class of StandardMaterial with some of the functionality\n * changed via the `onBeforeCompile` callback\n * @pailhead\n */\nclass GLTFMeshStandardSGMaterial extends three__WEBPACK_IMPORTED_MODULE_0__.MeshStandardMaterial {\n\n\tconstructor( params ) {\n\n\t\tsuper();\n\n\t\tthis.isGLTFSpecularGlossinessMaterial = true;\n\n\t\t//various chunks that need replacing\n\t\tconst specularMapParsFragmentChunk = [\n\t\t\t'#ifdef USE_SPECULARMAP',\n\t\t\t'\tuniform sampler2D specularMap;',\n\t\t\t'#endif'\n\t\t].join( '\\n' );\n\n\t\tconst glossinessMapParsFragmentChunk = [\n\t\t\t'#ifdef USE_GLOSSINESSMAP',\n\t\t\t'\tuniform sampler2D glossinessMap;',\n\t\t\t'#endif'\n\t\t].join( '\\n' );\n\n\t\tconst specularMapFragmentChunk = [\n\t\t\t'vec3 specularFactor = specular;',\n\t\t\t'#ifdef USE_SPECULARMAP',\n\t\t\t'\tvec4 texelSpecular = texture2D( specularMap, vUv );',\n\t\t\t'\t// reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',\n\t\t\t'\tspecularFactor *= texelSpecular.rgb;',\n\t\t\t'#endif'\n\t\t].join( '\\n' );\n\n\t\tconst glossinessMapFragmentChunk = [\n\t\t\t'float glossinessFactor = glossiness;',\n\t\t\t'#ifdef USE_GLOSSINESSMAP',\n\t\t\t'\tvec4 texelGlossiness = texture2D( glossinessMap, vUv );',\n\t\t\t'\t// reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',\n\t\t\t'\tglossinessFactor *= texelGlossiness.a;',\n\t\t\t'#endif'\n\t\t].join( '\\n' );\n\n\t\tconst lightPhysicalFragmentChunk = [\n\t\t\t'PhysicalMaterial material;',\n\t\t\t'material.diffuseColor = diffuseColor.rgb * ( 1. - max( specularFactor.r, max( specularFactor.g, specularFactor.b ) ) );',\n\t\t\t'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );',\n\t\t\t'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );',\n\t\t\t'material.roughness = max( 1.0 - glossinessFactor, 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap.',\n\t\t\t'material.roughness += geometryRoughness;',\n\t\t\t'material.roughness = min( material.roughness, 1.0 );',\n\t\t\t'material.specularColor = specularFactor;',\n\t\t].join( '\\n' );\n\n\t\tconst uniforms = {\n\t\t\tspecular: { value: new three__WEBPACK_IMPORTED_MODULE_0__.Color().setHex( 0xffffff ) },\n\t\t\tglossiness: { value: 1 },\n\t\t\tspecularMap: { value: null },\n\t\t\tglossinessMap: { value: null }\n\t\t};\n\n\t\tthis._extraUniforms = uniforms;\n\n\t\tthis.onBeforeCompile = function ( shader ) {\n\n\t\t\tfor ( const uniformName in uniforms ) {\n\n\t\t\t\tshader.uniforms[ uniformName ] = uniforms[ uniformName ];\n\n\t\t\t}\n\n\t\t\tshader.fragmentShader = shader.fragmentShader\n\t\t\t\t.replace( 'uniform float roughness;', 'uniform vec3 specular;' )\n\t\t\t\t.replace( 'uniform float metalness;', 'uniform float glossiness;' )\n\t\t\t\t.replace( '#include ', specularMapParsFragmentChunk )\n\t\t\t\t.replace( '#include ', glossinessMapParsFragmentChunk )\n\t\t\t\t.replace( '#include ', specularMapFragmentChunk )\n\t\t\t\t.replace( '#include ', glossinessMapFragmentChunk )\n\t\t\t\t.replace( '#include ', lightPhysicalFragmentChunk );\n\n\t\t};\n\n\t\tObject.defineProperties( this, {\n\n\t\t\tspecular: {\n\t\t\t\tget: function () {\n\n\t\t\t\t\treturn uniforms.specular.value;\n\n\t\t\t\t},\n\t\t\t\tset: function ( v ) {\n\n\t\t\t\t\tuniforms.specular.value = v;\n\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tspecularMap: {\n\t\t\t\tget: function () {\n\n\t\t\t\t\treturn uniforms.specularMap.value;\n\n\t\t\t\t},\n\t\t\t\tset: function ( v ) {\n\n\t\t\t\t\tuniforms.specularMap.value = v;\n\n\t\t\t\t\tif ( v ) {\n\n\t\t\t\t\t\tthis.defines.USE_SPECULARMAP = ''; // USE_UV is set by the renderer for specular maps\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tdelete this.defines.USE_SPECULARMAP;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tglossiness: {\n\t\t\t\tget: function () {\n\n\t\t\t\t\treturn uniforms.glossiness.value;\n\n\t\t\t\t},\n\t\t\t\tset: function ( v ) {\n\n\t\t\t\t\tuniforms.glossiness.value = v;\n\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tglossinessMap: {\n\t\t\t\tget: function () {\n\n\t\t\t\t\treturn uniforms.glossinessMap.value;\n\n\t\t\t\t},\n\t\t\t\tset: function ( v ) {\n\n\t\t\t\t\tuniforms.glossinessMap.value = v;\n\n\t\t\t\t\tif ( v ) {\n\n\t\t\t\t\t\tthis.defines.USE_GLOSSINESSMAP = '';\n\t\t\t\t\t\tthis.defines.USE_UV = '';\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tdelete this.defines.USE_GLOSSINESSMAP;\n\t\t\t\t\t\tdelete this.defines.USE_UV;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t} );\n\n\t\tdelete this.metalness;\n\t\tdelete this.roughness;\n\t\tdelete this.metalnessMap;\n\t\tdelete this.roughnessMap;\n\n\t\tthis.setValues( params );\n\n\t}\n\n\tcopy( source ) {\n\n\t\tsuper.copy( source );\n\n\t\tthis.specularMap = source.specularMap;\n\t\tthis.specular.copy( source.specular );\n\t\tthis.glossinessMap = source.glossinessMap;\n\t\tthis.glossiness = source.glossiness;\n\t\tdelete this.metalness;\n\t\tdelete this.roughness;\n\t\tdelete this.metalnessMap;\n\t\tdelete this.roughnessMap;\n\t\treturn this;\n\n\t}\n\n}\n\n\nclass GLTFMaterialsPbrSpecularGlossinessExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS;\n\n\t\tthis.specularGlossinessParams = [\n\t\t\t'color',\n\t\t\t'map',\n\t\t\t'lightMap',\n\t\t\t'lightMapIntensity',\n\t\t\t'aoMap',\n\t\t\t'aoMapIntensity',\n\t\t\t'emissive',\n\t\t\t'emissiveIntensity',\n\t\t\t'emissiveMap',\n\t\t\t'bumpMap',\n\t\t\t'bumpScale',\n\t\t\t'normalMap',\n\t\t\t'normalMapType',\n\t\t\t'displacementMap',\n\t\t\t'displacementScale',\n\t\t\t'displacementBias',\n\t\t\t'specularMap',\n\t\t\t'specular',\n\t\t\t'glossinessMap',\n\t\t\t'glossiness',\n\t\t\t'alphaMap',\n\t\t\t'envMap',\n\t\t\t'envMapIntensity'\n\t\t];\n\n\t}\n\n\tgetMaterialType() {\n\n\t\treturn GLTFMeshStandardSGMaterial;\n\n\t}\n\n\textendParams( materialParams, materialDef, parser ) {\n\n\t\tconst pbrSpecularGlossiness = materialDef.extensions[ this.name ];\n\n\t\tmaterialParams.color = new three__WEBPACK_IMPORTED_MODULE_0__.Color( 1.0, 1.0, 1.0 );\n\t\tmaterialParams.opacity = 1.0;\n\n\t\tconst pending = [];\n\n\t\tif ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {\n\n\t\t\tconst array = pbrSpecularGlossiness.diffuseFactor;\n\n\t\t\tmaterialParams.color.fromArray( array );\n\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t}\n\n\t\tif ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture, three__WEBPACK_IMPORTED_MODULE_0__.sRGBEncoding ) );\n\n\t\t}\n\n\t\tmaterialParams.emissive = new three__WEBPACK_IMPORTED_MODULE_0__.Color( 0.0, 0.0, 0.0 );\n\t\tmaterialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;\n\t\tmaterialParams.specular = new three__WEBPACK_IMPORTED_MODULE_0__.Color( 1.0, 1.0, 1.0 );\n\n\t\tif ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {\n\n\t\t\tmaterialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor );\n\n\t\t}\n\n\t\tif ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {\n\n\t\t\tconst specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;\n\t\t\tpending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );\n\t\t\tpending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef, three__WEBPACK_IMPORTED_MODULE_0__.sRGBEncoding ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n\tcreateMaterial( materialParams ) {\n\n\t\tconst material = new GLTFMeshStandardSGMaterial( materialParams );\n\t\tmaterial.fog = true;\n\n\t\tmaterial.color = materialParams.color;\n\n\t\tmaterial.map = materialParams.map === undefined ? null : materialParams.map;\n\n\t\tmaterial.lightMap = null;\n\t\tmaterial.lightMapIntensity = 1.0;\n\n\t\tmaterial.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap;\n\t\tmaterial.aoMapIntensity = 1.0;\n\n\t\tmaterial.emissive = materialParams.emissive;\n\t\tmaterial.emissiveIntensity = 1.0;\n\t\tmaterial.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap;\n\n\t\tmaterial.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap;\n\t\tmaterial.bumpScale = 1;\n\n\t\tmaterial.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap;\n\t\tmaterial.normalMapType = three__WEBPACK_IMPORTED_MODULE_0__.TangentSpaceNormalMap;\n\n\t\tif ( materialParams.normalScale ) material.normalScale = materialParams.normalScale;\n\n\t\tmaterial.displacementMap = null;\n\t\tmaterial.displacementScale = 1;\n\t\tmaterial.displacementBias = 0;\n\n\t\tmaterial.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap;\n\t\tmaterial.specular = materialParams.specular;\n\n\t\tmaterial.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap;\n\t\tmaterial.glossiness = materialParams.glossiness;\n\n\t\tmaterial.alphaMap = null;\n\n\t\tmaterial.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;\n\t\tmaterial.envMapIntensity = 1.0;\n\n\t\treturn material;\n\n\t}\n\n}\n\n/**\n * Mesh Quantization Extension\n *\n * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization\n */\nclass GLTFMeshQuantizationExtension {\n\n\tconstructor() {\n\n\t\tthis.name = EXTENSIONS.KHR_MESH_QUANTIZATION;\n\n\t}\n\n}\n\n/*********************************/\n/********** INTERPOLATION ********/\n/*********************************/\n\n// Spline Interpolation\n// Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation\nclass GLTFCubicSplineInterpolant extends three__WEBPACK_IMPORTED_MODULE_0__.Interpolant {\n\n\tconstructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\n\n\t\tsuper( parameterPositions, sampleValues, sampleSize, resultBuffer );\n\n\t}\n\n\tcopySampleValue_( index ) {\n\n\t\t// Copies a sample value to the result buffer. See description of glTF\n\t\t// CUBICSPLINE values layout in interpolate_() function below.\n\n\t\tconst result = this.resultBuffer,\n\t\t\tvalues = this.sampleValues,\n\t\t\tvalueSize = this.valueSize,\n\t\t\toffset = index * valueSize * 3 + valueSize;\n\n\t\tfor ( let i = 0; i !== valueSize; i ++ ) {\n\n\t\t\tresult[ i ] = values[ offset + i ];\n\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n}\n\nGLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;\n\nGLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;\n\nGLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) {\n\n\tconst result = this.resultBuffer;\n\tconst values = this.sampleValues;\n\tconst stride = this.valueSize;\n\n\tconst stride2 = stride * 2;\n\tconst stride3 = stride * 3;\n\n\tconst td = t1 - t0;\n\n\tconst p = ( t - t0 ) / td;\n\tconst pp = p * p;\n\tconst ppp = pp * p;\n\n\tconst offset1 = i1 * stride3;\n\tconst offset0 = offset1 - stride3;\n\n\tconst s2 = - 2 * ppp + 3 * pp;\n\tconst s3 = ppp - pp;\n\tconst s0 = 1 - s2;\n\tconst s1 = s3 - pp + p;\n\n\t// Layout of keyframe output values for CUBICSPLINE animations:\n\t// [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]\n\tfor ( let i = 0; i !== stride; i ++ ) {\n\n\t\tconst p0 = values[ offset0 + i + stride ]; // splineVertex_k\n\t\tconst m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)\n\t\tconst p1 = values[ offset1 + i + stride ]; // splineVertex_k+1\n\t\tconst m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)\n\n\t\tresult[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;\n\n\t}\n\n\treturn result;\n\n};\n\nconst _q = new three__WEBPACK_IMPORTED_MODULE_0__.Quaternion();\n\nclass GLTFCubicSplineQuaternionInterpolant extends GLTFCubicSplineInterpolant {\n\n\tinterpolate_( i1, t0, t, t1 ) {\n\n\t\tconst result = super.interpolate_( i1, t0, t, t1 );\n\n\t\t_q.fromArray( result ).normalize().toArray( result );\n\n\t\treturn result;\n\n\t}\n\n}\n\n\n/*********************************/\n/********** INTERNALS ************/\n/*********************************/\n\n/* CONSTANTS */\n\nconst WEBGL_CONSTANTS = {\n\tFLOAT: 5126,\n\t//FLOAT_MAT2: 35674,\n\tFLOAT_MAT3: 35675,\n\tFLOAT_MAT4: 35676,\n\tFLOAT_VEC2: 35664,\n\tFLOAT_VEC3: 35665,\n\tFLOAT_VEC4: 35666,\n\tLINEAR: 9729,\n\tREPEAT: 10497,\n\tSAMPLER_2D: 35678,\n\tPOINTS: 0,\n\tLINES: 1,\n\tLINE_LOOP: 2,\n\tLINE_STRIP: 3,\n\tTRIANGLES: 4,\n\tTRIANGLE_STRIP: 5,\n\tTRIANGLE_FAN: 6,\n\tUNSIGNED_BYTE: 5121,\n\tUNSIGNED_SHORT: 5123\n};\n\nconst WEBGL_COMPONENT_TYPES = {\n\t5120: Int8Array,\n\t5121: Uint8Array,\n\t5122: Int16Array,\n\t5123: Uint16Array,\n\t5125: Uint32Array,\n\t5126: Float32Array\n};\n\nconst WEBGL_FILTERS = {\n\t9728: three__WEBPACK_IMPORTED_MODULE_0__.NearestFilter,\n\t9729: three__WEBPACK_IMPORTED_MODULE_0__.LinearFilter,\n\t9984: three__WEBPACK_IMPORTED_MODULE_0__.NearestMipmapNearestFilter,\n\t9985: three__WEBPACK_IMPORTED_MODULE_0__.LinearMipmapNearestFilter,\n\t9986: three__WEBPACK_IMPORTED_MODULE_0__.NearestMipmapLinearFilter,\n\t9987: three__WEBPACK_IMPORTED_MODULE_0__.LinearMipmapLinearFilter\n};\n\nconst WEBGL_WRAPPINGS = {\n\t33071: three__WEBPACK_IMPORTED_MODULE_0__.ClampToEdgeWrapping,\n\t33648: three__WEBPACK_IMPORTED_MODULE_0__.MirroredRepeatWrapping,\n\t10497: three__WEBPACK_IMPORTED_MODULE_0__.RepeatWrapping\n};\n\nconst WEBGL_TYPE_SIZES = {\n\t'SCALAR': 1,\n\t'VEC2': 2,\n\t'VEC3': 3,\n\t'VEC4': 4,\n\t'MAT2': 4,\n\t'MAT3': 9,\n\t'MAT4': 16\n};\n\nconst ATTRIBUTES = {\n\tPOSITION: 'position',\n\tNORMAL: 'normal',\n\tTANGENT: 'tangent',\n\tTEXCOORD_0: 'uv',\n\tTEXCOORD_1: 'uv2',\n\tCOLOR_0: 'color',\n\tWEIGHTS_0: 'skinWeight',\n\tJOINTS_0: 'skinIndex',\n};\n\nconst PATH_PROPERTIES = {\n\tscale: 'scale',\n\ttranslation: 'position',\n\trotation: 'quaternion',\n\tweights: 'morphTargetInfluences'\n};\n\nconst INTERPOLATION = {\n\tCUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each\n\t\t // keyframe track will be initialized with a default interpolation type, then modified.\n\tLINEAR: three__WEBPACK_IMPORTED_MODULE_0__.InterpolateLinear,\n\tSTEP: three__WEBPACK_IMPORTED_MODULE_0__.InterpolateDiscrete\n};\n\nconst ALPHA_MODES = {\n\tOPAQUE: 'OPAQUE',\n\tMASK: 'MASK',\n\tBLEND: 'BLEND'\n};\n\n/**\n * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material\n */\nfunction createDefaultMaterial( cache ) {\n\n\tif ( cache[ 'DefaultMaterial' ] === undefined ) {\n\n\t\tcache[ 'DefaultMaterial' ] = new three__WEBPACK_IMPORTED_MODULE_0__.MeshStandardMaterial( {\n\t\t\tcolor: 0xFFFFFF,\n\t\t\temissive: 0x000000,\n\t\t\tmetalness: 1,\n\t\t\troughness: 1,\n\t\t\ttransparent: false,\n\t\t\tdepthTest: true,\n\t\t\tside: three__WEBPACK_IMPORTED_MODULE_0__.FrontSide\n\t\t} );\n\n\t}\n\n\treturn cache[ 'DefaultMaterial' ];\n\n}\n\nfunction addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {\n\n\t// Add unknown glTF extensions to an object's userData.\n\n\tfor ( const name in objectDef.extensions ) {\n\n\t\tif ( knownExtensions[ name ] === undefined ) {\n\n\t\t\tobject.userData.gltfExtensions = object.userData.gltfExtensions || {};\n\t\t\tobject.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * @param {Object3D|Material|BufferGeometry} object\n * @param {GLTF.definition} gltfDef\n */\nfunction assignExtrasToUserData( object, gltfDef ) {\n\n\tif ( gltfDef.extras !== undefined ) {\n\n\t\tif ( typeof gltfDef.extras === 'object' ) {\n\n\t\t\tObject.assign( object.userData, gltfDef.extras );\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );\n\n\t\t}\n\n\t}\n\n}\n\n/**\n * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets\n *\n * @param {BufferGeometry} geometry\n * @param {Array} targets\n * @param {GLTFParser} parser\n * @return {Promise}\n */\nfunction addMorphTargets( geometry, targets, parser ) {\n\n\tlet hasMorphPosition = false;\n\tlet hasMorphNormal = false;\n\tlet hasMorphColor = false;\n\n\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\tconst target = targets[ i ];\n\n\t\tif ( target.POSITION !== undefined ) hasMorphPosition = true;\n\t\tif ( target.NORMAL !== undefined ) hasMorphNormal = true;\n\t\tif ( target.COLOR_0 !== undefined ) hasMorphColor = true;\n\n\t\tif ( hasMorphPosition && hasMorphNormal && hasMorphColor ) break;\n\n\t}\n\n\tif ( ! hasMorphPosition && ! hasMorphNormal && ! hasMorphColor ) return Promise.resolve( geometry );\n\n\tconst pendingPositionAccessors = [];\n\tconst pendingNormalAccessors = [];\n\tconst pendingColorAccessors = [];\n\n\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\tconst target = targets[ i ];\n\n\t\tif ( hasMorphPosition ) {\n\n\t\t\tconst pendingAccessor = target.POSITION !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.POSITION )\n\t\t\t\t: geometry.attributes.position;\n\n\t\t\tpendingPositionAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t\tif ( hasMorphNormal ) {\n\n\t\t\tconst pendingAccessor = target.NORMAL !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.NORMAL )\n\t\t\t\t: geometry.attributes.normal;\n\n\t\t\tpendingNormalAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t\tif ( hasMorphColor ) {\n\n\t\t\tconst pendingAccessor = target.COLOR_0 !== undefined\n\t\t\t\t? parser.getDependency( 'accessor', target.COLOR_0 )\n\t\t\t\t: geometry.attributes.color;\n\n\t\t\tpendingColorAccessors.push( pendingAccessor );\n\n\t\t}\n\n\t}\n\n\treturn Promise.all( [\n\t\tPromise.all( pendingPositionAccessors ),\n\t\tPromise.all( pendingNormalAccessors ),\n\t\tPromise.all( pendingColorAccessors )\n\t] ).then( function ( accessors ) {\n\n\t\tconst morphPositions = accessors[ 0 ];\n\t\tconst morphNormals = accessors[ 1 ];\n\t\tconst morphColors = accessors[ 2 ];\n\n\t\tif ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;\n\t\tif ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;\n\t\tif ( hasMorphColor ) geometry.morphAttributes.color = morphColors;\n\t\tgeometry.morphTargetsRelative = true;\n\n\t\treturn geometry;\n\n\t} );\n\n}\n\n/**\n * @param {Mesh} mesh\n * @param {GLTF.Mesh} meshDef\n */\nfunction updateMorphTargets( mesh, meshDef ) {\n\n\tmesh.updateMorphTargets();\n\n\tif ( meshDef.weights !== undefined ) {\n\n\t\tfor ( let i = 0, il = meshDef.weights.length; i < il; i ++ ) {\n\n\t\t\tmesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];\n\n\t\t}\n\n\t}\n\n\t// .extras has user-defined data, so check that .extras.targetNames is an array.\n\tif ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {\n\n\t\tconst targetNames = meshDef.extras.targetNames;\n\n\t\tif ( mesh.morphTargetInfluences.length === targetNames.length ) {\n\n\t\t\tmesh.morphTargetDictionary = {};\n\n\t\t\tfor ( let i = 0, il = targetNames.length; i < il; i ++ ) {\n\n\t\t\t\tmesh.morphTargetDictionary[ targetNames[ i ] ] = i;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );\n\n\t\t}\n\n\t}\n\n}\n\nfunction createPrimitiveKey( primitiveDef ) {\n\n\tconst dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];\n\tlet geometryKey;\n\n\tif ( dracoExtension ) {\n\n\t\tgeometryKey = 'draco:' + dracoExtension.bufferView\n\t\t\t\t+ ':' + dracoExtension.indices\n\t\t\t\t+ ':' + createAttributesKey( dracoExtension.attributes );\n\n\t} else {\n\n\t\tgeometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;\n\n\t}\n\n\treturn geometryKey;\n\n}\n\nfunction createAttributesKey( attributes ) {\n\n\tlet attributesKey = '';\n\n\tconst keys = Object.keys( attributes ).sort();\n\n\tfor ( let i = 0, il = keys.length; i < il; i ++ ) {\n\n\t\tattributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';\n\n\t}\n\n\treturn attributesKey;\n\n}\n\nfunction getNormalizedComponentScale( constructor ) {\n\n\t// Reference:\n\t// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data\n\n\tswitch ( constructor ) {\n\n\t\tcase Int8Array:\n\t\t\treturn 1 / 127;\n\n\t\tcase Uint8Array:\n\t\t\treturn 1 / 255;\n\n\t\tcase Int16Array:\n\t\t\treturn 1 / 32767;\n\n\t\tcase Uint16Array:\n\t\t\treturn 1 / 65535;\n\n\t\tdefault:\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' );\n\n\t}\n\n}\n\nfunction getImageURIMimeType( uri ) {\n\n\tif ( uri.search( /\\.jpe?g($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/jpeg/ ) === 0 ) return 'image/jpeg';\n\tif ( uri.search( /\\.webp($|\\?)/i ) > 0 || uri.search( /^data\\:image\\/webp/ ) === 0 ) return 'image/webp';\n\n\treturn 'image/png';\n\n}\n\n/* GLTF PARSER */\n\nclass GLTFParser {\n\n\tconstructor( json = {}, options = {} ) {\n\n\t\tthis.json = json;\n\t\tthis.extensions = {};\n\t\tthis.plugins = {};\n\t\tthis.options = options;\n\n\t\t// loader object cache\n\t\tthis.cache = new GLTFRegistry();\n\n\t\t// associations between Three.js objects and glTF elements\n\t\tthis.associations = new Map();\n\n\t\t// BufferGeometry caching\n\t\tthis.primitiveCache = {};\n\n\t\t// Object3D instance caches\n\t\tthis.meshCache = { refs: {}, uses: {} };\n\t\tthis.cameraCache = { refs: {}, uses: {} };\n\t\tthis.lightCache = { refs: {}, uses: {} };\n\n\t\tthis.sourceCache = {};\n\t\tthis.textureCache = {};\n\n\t\t// Track node names, to ensure no duplicates\n\t\tthis.nodeNamesUsed = {};\n\n\t\t// Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the\n\t\t// expensive work of uploading a texture to the GPU off the main thread.\n\t\tif ( typeof createImageBitmap !== 'undefined' && /^((?!chrome|android).)*safari/i.test( navigator.userAgent ) === false ) {\n\n\t\t\tthis.textureLoader = new three__WEBPACK_IMPORTED_MODULE_0__.ImageBitmapLoader( this.options.manager );\n\n\t\t} else {\n\n\t\t\tthis.textureLoader = new three__WEBPACK_IMPORTED_MODULE_0__.TextureLoader( this.options.manager );\n\n\t\t}\n\n\t\tthis.textureLoader.setCrossOrigin( this.options.crossOrigin );\n\t\tthis.textureLoader.setRequestHeader( this.options.requestHeader );\n\n\t\tthis.fileLoader = new three__WEBPACK_IMPORTED_MODULE_0__.FileLoader( this.options.manager );\n\t\tthis.fileLoader.setResponseType( 'arraybuffer' );\n\n\t\tif ( this.options.crossOrigin === 'use-credentials' ) {\n\n\t\t\tthis.fileLoader.setWithCredentials( true );\n\n\t\t}\n\n\t}\n\n\tsetExtensions( extensions ) {\n\n\t\tthis.extensions = extensions;\n\n\t}\n\n\tsetPlugins( plugins ) {\n\n\t\tthis.plugins = plugins;\n\n\t}\n\n\tparse( onLoad, onError ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\n\t\t// Clear the loader cache\n\t\tthis.cache.removeAll();\n\n\t\t// Mark the special nodes/meshes in json for efficient parse\n\t\tthis._invokeAll( function ( ext ) {\n\n\t\t\treturn ext._markDefs && ext._markDefs();\n\n\t\t} );\n\n\t\tPromise.all( this._invokeAll( function ( ext ) {\n\n\t\t\treturn ext.beforeRoot && ext.beforeRoot();\n\n\t\t} ) ).then( function () {\n\n\t\t\treturn Promise.all( [\n\n\t\t\t\tparser.getDependencies( 'scene' ),\n\t\t\t\tparser.getDependencies( 'animation' ),\n\t\t\t\tparser.getDependencies( 'camera' ),\n\n\t\t\t] );\n\n\t\t} ).then( function ( dependencies ) {\n\n\t\t\tconst result = {\n\t\t\t\tscene: dependencies[ 0 ][ json.scene || 0 ],\n\t\t\t\tscenes: dependencies[ 0 ],\n\t\t\t\tanimations: dependencies[ 1 ],\n\t\t\t\tcameras: dependencies[ 2 ],\n\t\t\t\tasset: json.asset,\n\t\t\t\tparser: parser,\n\t\t\t\tuserData: {}\n\t\t\t};\n\n\t\t\taddUnknownExtensionsToUserData( extensions, result, json );\n\n\t\t\tassignExtrasToUserData( result, json );\n\n\t\t\tPromise.all( parser._invokeAll( function ( ext ) {\n\n\t\t\t\treturn ext.afterRoot && ext.afterRoot( result );\n\n\t\t\t} ) ).then( function () {\n\n\t\t\t\tonLoad( result );\n\n\t\t\t} );\n\n\t\t} ).catch( onError );\n\n\t}\n\n\t/**\n\t * Marks the special nodes/meshes in json for efficient parse.\n\t */\n\t_markDefs() {\n\n\t\tconst nodeDefs = this.json.nodes || [];\n\t\tconst skinDefs = this.json.skins || [];\n\t\tconst meshDefs = this.json.meshes || [];\n\n\t\t// Nothing in the node definition indicates whether it is a Bone or an\n\t\t// Object3D. Use the skins' joint references to mark bones.\n\t\tfor ( let skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {\n\n\t\t\tconst joints = skinDefs[ skinIndex ].joints;\n\n\t\t\tfor ( let i = 0, il = joints.length; i < il; i ++ ) {\n\n\t\t\t\tnodeDefs[ joints[ i ] ].isBone = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Iterate over all nodes, marking references to shared resources,\n\t\t// as well as skeleton joints.\n\t\tfor ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {\n\n\t\t\tconst nodeDef = nodeDefs[ nodeIndex ];\n\n\t\t\tif ( nodeDef.mesh !== undefined ) {\n\n\t\t\t\tthis._addNodeRef( this.meshCache, nodeDef.mesh );\n\n\t\t\t\t// Nothing in the mesh definition indicates whether it is\n\t\t\t\t// a SkinnedMesh or Mesh. Use the node's mesh reference\n\t\t\t\t// to mark SkinnedMesh if node has skin.\n\t\t\t\tif ( nodeDef.skin !== undefined ) {\n\n\t\t\t\t\tmeshDefs[ nodeDef.mesh ].isSkinnedMesh = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( nodeDef.camera !== undefined ) {\n\n\t\t\t\tthis._addNodeRef( this.cameraCache, nodeDef.camera );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Counts references to shared node / Object3D resources. These resources\n\t * can be reused, or \"instantiated\", at multiple nodes in the scene\n\t * hierarchy. Mesh, Camera, and Light instances are instantiated and must\n\t * be marked. Non-scenegraph resources (like Materials, Geometries, and\n\t * Textures) can be reused directly and are not marked here.\n\t *\n\t * Example: CesiumMilkTruck sample model reuses \"Wheel\" meshes.\n\t */\n\t_addNodeRef( cache, index ) {\n\n\t\tif ( index === undefined ) return;\n\n\t\tif ( cache.refs[ index ] === undefined ) {\n\n\t\t\tcache.refs[ index ] = cache.uses[ index ] = 0;\n\n\t\t}\n\n\t\tcache.refs[ index ] ++;\n\n\t}\n\n\t/** Returns a reference to a shared resource, cloning it if necessary. */\n\t_getNodeRef( cache, index, object ) {\n\n\t\tif ( cache.refs[ index ] <= 1 ) return object;\n\n\t\tconst ref = object.clone();\n\n\t\t// Propagates mappings to the cloned object, prevents mappings on the\n\t\t// original object from being lost.\n\t\tconst updateMappings = ( original, clone ) => {\n\n\t\t\tconst mappings = this.associations.get( original );\n\t\t\tif ( mappings != null ) {\n\n\t\t\t\tthis.associations.set( clone, mappings );\n\n\t\t\t}\n\n\t\t\tfor ( const [ i, child ] of original.children.entries() ) {\n\n\t\t\t\tupdateMappings( child, clone.children[ i ] );\n\n\t\t\t}\n\n\t\t};\n\n\t\tupdateMappings( object, ref );\n\n\t\tref.name += '_instance_' + ( cache.uses[ index ] ++ );\n\n\t\treturn ref;\n\n\t}\n\n\t_invokeOne( func ) {\n\n\t\tconst extensions = Object.values( this.plugins );\n\t\textensions.push( this );\n\n\t\tfor ( let i = 0; i < extensions.length; i ++ ) {\n\n\t\t\tconst result = func( extensions[ i ] );\n\n\t\t\tif ( result ) return result;\n\n\t\t}\n\n\t\treturn null;\n\n\t}\n\n\t_invokeAll( func ) {\n\n\t\tconst extensions = Object.values( this.plugins );\n\t\textensions.unshift( this );\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0; i < extensions.length; i ++ ) {\n\n\t\t\tconst result = func( extensions[ i ] );\n\n\t\t\tif ( result ) pending.push( result );\n\n\t\t}\n\n\t\treturn pending;\n\n\t}\n\n\t/**\n\t * Requests the specified dependency asynchronously, with caching.\n\t * @param {string} type\n\t * @param {number} index\n\t * @return {Promise}\n\t */\n\tgetDependency( type, index ) {\n\n\t\tconst cacheKey = type + ':' + index;\n\t\tlet dependency = this.cache.get( cacheKey );\n\n\t\tif ( ! dependency ) {\n\n\t\t\tswitch ( type ) {\n\n\t\t\t\tcase 'scene':\n\t\t\t\t\tdependency = this.loadScene( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'node':\n\t\t\t\t\tdependency = this.loadNode( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mesh':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadMesh && ext.loadMesh( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'accessor':\n\t\t\t\t\tdependency = this.loadAccessor( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'bufferView':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadBufferView && ext.loadBufferView( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'buffer':\n\t\t\t\t\tdependency = this.loadBuffer( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'material':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadMaterial && ext.loadMaterial( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'texture':\n\t\t\t\t\tdependency = this._invokeOne( function ( ext ) {\n\n\t\t\t\t\t\treturn ext.loadTexture && ext.loadTexture( index );\n\n\t\t\t\t\t} );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'skin':\n\t\t\t\t\tdependency = this.loadSkin( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'animation':\n\t\t\t\t\tdependency = this.loadAnimation( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'camera':\n\t\t\t\t\tdependency = this.loadCamera( index );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error( 'Unknown type: ' + type );\n\n\t\t\t}\n\n\t\t\tthis.cache.add( cacheKey, dependency );\n\n\t\t}\n\n\t\treturn dependency;\n\n\t}\n\n\t/**\n\t * Requests all dependencies of the specified type asynchronously, with caching.\n\t * @param {string} type\n\t * @return {Promise>}\n\t */\n\tgetDependencies( type ) {\n\n\t\tlet dependencies = this.cache.get( type );\n\n\t\tif ( ! dependencies ) {\n\n\t\t\tconst parser = this;\n\t\t\tconst defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];\n\n\t\t\tdependencies = Promise.all( defs.map( function ( def, index ) {\n\n\t\t\t\treturn parser.getDependency( type, index );\n\n\t\t\t} ) );\n\n\t\t\tthis.cache.add( type, dependencies );\n\n\t\t}\n\n\t\treturn dependencies;\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\n\t * @param {number} bufferIndex\n\t * @return {Promise}\n\t */\n\tloadBuffer( bufferIndex ) {\n\n\t\tconst bufferDef = this.json.buffers[ bufferIndex ];\n\t\tconst loader = this.fileLoader;\n\n\t\tif ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );\n\n\t\t}\n\n\t\t// If present, GLB container is required to be the first buffer.\n\t\tif ( bufferDef.uri === undefined && bufferIndex === 0 ) {\n\n\t\t\treturn Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );\n\n\t\t}\n\n\t\tconst options = this.options;\n\n\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\tloader.load( three__WEBPACK_IMPORTED_MODULE_0__.LoaderUtils.resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {\n\n\t\t\t\treject( new Error( 'THREE.GLTFLoader: Failed to load buffer \"' + bufferDef.uri + '\".' ) );\n\n\t\t\t} );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\n\t * @param {number} bufferViewIndex\n\t * @return {Promise}\n\t */\n\tloadBufferView( bufferViewIndex ) {\n\n\t\tconst bufferViewDef = this.json.bufferViews[ bufferViewIndex ];\n\n\t\treturn this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {\n\n\t\t\tconst byteLength = bufferViewDef.byteLength || 0;\n\t\t\tconst byteOffset = bufferViewDef.byteOffset || 0;\n\t\t\treturn buffer.slice( byteOffset, byteOffset + byteLength );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors\n\t * @param {number} accessorIndex\n\t * @return {Promise}\n\t */\n\tloadAccessor( accessorIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\n\t\tconst accessorDef = this.json.accessors[ accessorIndex ];\n\n\t\tif ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {\n\n\t\t\t// Ignore empty accessors, which may be used to declare runtime\n\t\t\t// information about attributes coming from another source (e.g. Draco\n\t\t\t// compression extension).\n\t\t\treturn Promise.resolve( null );\n\n\t\t}\n\n\t\tconst pendingBufferViews = [];\n\n\t\tif ( accessorDef.bufferView !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );\n\n\t\t} else {\n\n\t\t\tpendingBufferViews.push( null );\n\n\t\t}\n\n\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );\n\n\t\t}\n\n\t\treturn Promise.all( pendingBufferViews ).then( function ( bufferViews ) {\n\n\t\t\tconst bufferView = bufferViews[ 0 ];\n\n\t\t\tconst itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];\n\t\t\tconst TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\n\n\t\t\t// For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.\n\t\t\tconst elementBytes = TypedArray.BYTES_PER_ELEMENT;\n\t\t\tconst itemBytes = elementBytes * itemSize;\n\t\t\tconst byteOffset = accessorDef.byteOffset || 0;\n\t\t\tconst byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;\n\t\t\tconst normalized = accessorDef.normalized === true;\n\t\t\tlet array, bufferAttribute;\n\n\t\t\t// The buffer is not interleaved if the stride is the item size in bytes.\n\t\t\tif ( byteStride && byteStride !== itemBytes ) {\n\n\t\t\t\t// Each \"slice\" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer\n\t\t\t\t// This makes sure that IBA.count reflects accessor.count properly\n\t\t\t\tconst ibSlice = Math.floor( byteOffset / byteStride );\n\t\t\t\tconst ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;\n\t\t\t\tlet ib = parser.cache.get( ibCacheKey );\n\n\t\t\t\tif ( ! ib ) {\n\n\t\t\t\t\tarray = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );\n\n\t\t\t\t\t// Integer parameters to IB/IBA are in array elements, not bytes.\n\t\t\t\t\tib = new three__WEBPACK_IMPORTED_MODULE_0__.InterleavedBuffer( array, byteStride / elementBytes );\n\n\t\t\t\t\tparser.cache.add( ibCacheKey, ib );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new three__WEBPACK_IMPORTED_MODULE_0__.InterleavedBufferAttribute( ib, itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );\n\n\t\t\t} else {\n\n\t\t\t\tif ( bufferView === null ) {\n\n\t\t\t\t\tarray = new TypedArray( accessorDef.count * itemSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tarray = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );\n\n\t\t\t\t}\n\n\t\t\t\tbufferAttribute = new three__WEBPACK_IMPORTED_MODULE_0__.BufferAttribute( array, itemSize, normalized );\n\n\t\t\t}\n\n\t\t\t// https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors\n\t\t\tif ( accessorDef.sparse !== undefined ) {\n\n\t\t\t\tconst itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;\n\t\t\t\tconst TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];\n\n\t\t\t\tconst byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;\n\t\t\t\tconst byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;\n\n\t\t\t\tconst sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );\n\t\t\t\tconst sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );\n\n\t\t\t\tif ( bufferView !== null ) {\n\n\t\t\t\t\t// Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.\n\t\t\t\t\tbufferAttribute = new three__WEBPACK_IMPORTED_MODULE_0__.BufferAttribute( bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized );\n\n\t\t\t\t}\n\n\t\t\t\tfor ( let i = 0, il = sparseIndices.length; i < il; i ++ ) {\n\n\t\t\t\t\tconst index = sparseIndices[ i ];\n\n\t\t\t\t\tbufferAttribute.setX( index, sparseValues[ i * itemSize ] );\n\t\t\t\t\tif ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );\n\t\t\t\t\tif ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );\n\t\t\t\t\tif ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );\n\t\t\t\t\tif ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn bufferAttribute;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures\n\t * @param {number} textureIndex\n\t * @return {Promise}\n\t */\n\tloadTexture( textureIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst options = this.options;\n\t\tconst textureDef = json.textures[ textureIndex ];\n\t\tconst sourceIndex = textureDef.source;\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tlet loader = this.textureLoader;\n\n\t\tif ( sourceDef.uri ) {\n\n\t\t\tconst handler = options.manager.getHandler( sourceDef.uri );\n\t\t\tif ( handler !== null ) loader = handler;\n\n\t\t}\n\n\t\treturn this.loadTextureImage( textureIndex, sourceIndex, loader );\n\n\t}\n\n\tloadTextureImage( textureIndex, sourceIndex, loader ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\n\t\tconst textureDef = json.textures[ textureIndex ];\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tconst cacheKey = ( sourceDef.uri || sourceDef.bufferView ) + ':' + textureDef.sampler;\n\n\t\tif ( this.textureCache[ cacheKey ] ) {\n\n\t\t\t// See https://github.com/mrdoob/three.js/issues/21559.\n\t\t\treturn this.textureCache[ cacheKey ];\n\n\t\t}\n\n\t\tconst promise = this.loadImageSource( sourceIndex, loader ).then( function ( texture ) {\n\n\t\t\ttexture.flipY = false;\n\n\t\t\tif ( textureDef.name ) texture.name = textureDef.name;\n\n\t\t\tconst samplers = json.samplers || {};\n\t\t\tconst sampler = samplers[ textureDef.sampler ] || {};\n\n\t\t\ttexture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || three__WEBPACK_IMPORTED_MODULE_0__.LinearFilter;\n\t\t\ttexture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || three__WEBPACK_IMPORTED_MODULE_0__.LinearMipmapLinearFilter;\n\t\t\ttexture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || three__WEBPACK_IMPORTED_MODULE_0__.RepeatWrapping;\n\t\t\ttexture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || three__WEBPACK_IMPORTED_MODULE_0__.RepeatWrapping;\n\n\t\t\tparser.associations.set( texture, { textures: textureIndex } );\n\n\t\t\treturn texture;\n\n\t\t} ).catch( function () {\n\n\t\t\treturn null;\n\n\t\t} );\n\n\t\tthis.textureCache[ cacheKey ] = promise;\n\n\t\treturn promise;\n\n\t}\n\n\tloadImageSource( sourceIndex, loader ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst options = this.options;\n\n\t\tif ( this.sourceCache[ sourceIndex ] !== undefined ) {\n\n\t\t\treturn this.sourceCache[ sourceIndex ].then( ( texture ) => texture.clone() );\n\n\t\t}\n\n\t\tconst sourceDef = json.images[ sourceIndex ];\n\n\t\tconst URL = self.URL || self.webkitURL;\n\n\t\tlet sourceURI = sourceDef.uri || '';\n\t\tlet isObjectURL = false;\n\n\t\tif ( sourceDef.bufferView !== undefined ) {\n\n\t\t\t// Load binary image data from bufferView, if provided.\n\n\t\t\tsourceURI = parser.getDependency( 'bufferView', sourceDef.bufferView ).then( function ( bufferView ) {\n\n\t\t\t\tisObjectURL = true;\n\t\t\t\tconst blob = new Blob( [ bufferView ], { type: sourceDef.mimeType } );\n\t\t\t\tsourceURI = URL.createObjectURL( blob );\n\t\t\t\treturn sourceURI;\n\n\t\t\t} );\n\n\t\t} else if ( sourceDef.uri === undefined ) {\n\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Image ' + sourceIndex + ' is missing URI and bufferView' );\n\n\t\t}\n\n\t\tconst promise = Promise.resolve( sourceURI ).then( function ( sourceURI ) {\n\n\t\t\treturn new Promise( function ( resolve, reject ) {\n\n\t\t\t\tlet onLoad = resolve;\n\n\t\t\t\tif ( loader.isImageBitmapLoader === true ) {\n\n\t\t\t\t\tonLoad = function ( imageBitmap ) {\n\n\t\t\t\t\t\tconst texture = new three__WEBPACK_IMPORTED_MODULE_0__.Texture( imageBitmap );\n\t\t\t\t\t\ttexture.needsUpdate = true;\n\n\t\t\t\t\t\tresolve( texture );\n\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t\tloader.load( three__WEBPACK_IMPORTED_MODULE_0__.LoaderUtils.resolveURL( sourceURI, options.path ), onLoad, undefined, reject );\n\n\t\t\t} );\n\n\t\t} ).then( function ( texture ) {\n\n\t\t\t// Clean up resources and configure Texture.\n\n\t\t\tif ( isObjectURL === true ) {\n\n\t\t\t\tURL.revokeObjectURL( sourceURI );\n\n\t\t\t}\n\n\t\t\ttexture.userData.mimeType = sourceDef.mimeType || getImageURIMimeType( sourceDef.uri );\n\n\t\t\treturn texture;\n\n\t\t} ).catch( function ( error ) {\n\n\t\t\tconsole.error( 'THREE.GLTFLoader: Couldn\\'t load texture', sourceURI );\n\t\t\tthrow error;\n\n\t\t} );\n\n\t\tthis.sourceCache[ sourceIndex ] = promise;\n\t\treturn promise;\n\n\t}\n\n\t/**\n\t * Asynchronously assigns a texture to the given material parameters.\n\t * @param {Object} materialParams\n\t * @param {string} mapName\n\t * @param {Object} mapDef\n\t * @return {Promise}\n\t */\n\tassignTexture( materialParams, mapName, mapDef, encoding ) {\n\n\t\tconst parser = this;\n\n\t\treturn this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {\n\n\t\t\t// Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured\n\t\t\t// However, we will copy UV set 0 to UV set 1 on demand for aoMap\n\t\t\tif ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {\n\n\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Custom UV set ' + mapDef.texCoord + ' for texture ' + mapName + ' not yet supported.' );\n\n\t\t\t}\n\n\t\t\tif ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {\n\n\t\t\t\tconst transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;\n\n\t\t\t\tif ( transform ) {\n\n\t\t\t\t\tconst gltfReference = parser.associations.get( texture );\n\t\t\t\t\ttexture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );\n\t\t\t\t\tparser.associations.set( texture, gltfReference );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( encoding !== undefined ) {\n\n\t\t\t\ttexture.encoding = encoding;\n\n\t\t\t}\n\n\t\t\tmaterialParams[ mapName ] = texture;\n\n\t\t\treturn texture;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Assigns final material to a Mesh, Line, or Points instance. The instance\n\t * already has a material (generated from the glTF material options alone)\n\t * but reuse of the same glTF material may require multiple threejs materials\n\t * to accommodate different primitive types, defines, etc. New materials will\n\t * be created if necessary, and reused from a cache.\n\t * @param {Object3D} mesh Mesh, Line, or Points instance.\n\t */\n\tassignFinalMaterial( mesh ) {\n\n\t\tconst geometry = mesh.geometry;\n\t\tlet material = mesh.material;\n\n\t\tconst useDerivativeTangents = geometry.attributes.tangent === undefined;\n\t\tconst useVertexColors = geometry.attributes.color !== undefined;\n\t\tconst useFlatShading = geometry.attributes.normal === undefined;\n\n\t\tif ( mesh.isPoints ) {\n\n\t\t\tconst cacheKey = 'PointsMaterial:' + material.uuid;\n\n\t\t\tlet pointsMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! pointsMaterial ) {\n\n\t\t\t\tpointsMaterial = new three__WEBPACK_IMPORTED_MODULE_0__.PointsMaterial();\n\t\t\t\tthree__WEBPACK_IMPORTED_MODULE_0__.Material.prototype.copy.call( pointsMaterial, material );\n\t\t\t\tpointsMaterial.color.copy( material.color );\n\t\t\t\tpointsMaterial.map = material.map;\n\t\t\t\tpointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px\n\n\t\t\t\tthis.cache.add( cacheKey, pointsMaterial );\n\n\t\t\t}\n\n\t\t\tmaterial = pointsMaterial;\n\n\t\t} else if ( mesh.isLine ) {\n\n\t\t\tconst cacheKey = 'LineBasicMaterial:' + material.uuid;\n\n\t\t\tlet lineMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! lineMaterial ) {\n\n\t\t\t\tlineMaterial = new three__WEBPACK_IMPORTED_MODULE_0__.LineBasicMaterial();\n\t\t\t\tthree__WEBPACK_IMPORTED_MODULE_0__.Material.prototype.copy.call( lineMaterial, material );\n\t\t\t\tlineMaterial.color.copy( material.color );\n\n\t\t\t\tthis.cache.add( cacheKey, lineMaterial );\n\n\t\t\t}\n\n\t\t\tmaterial = lineMaterial;\n\n\t\t}\n\n\t\t// Clone the material if it will be modified\n\t\tif ( useDerivativeTangents || useVertexColors || useFlatShading ) {\n\n\t\t\tlet cacheKey = 'ClonedMaterial:' + material.uuid + ':';\n\n\t\t\tif ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';\n\t\t\tif ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';\n\t\t\tif ( useVertexColors ) cacheKey += 'vertex-colors:';\n\t\t\tif ( useFlatShading ) cacheKey += 'flat-shading:';\n\n\t\t\tlet cachedMaterial = this.cache.get( cacheKey );\n\n\t\t\tif ( ! cachedMaterial ) {\n\n\t\t\t\tcachedMaterial = material.clone();\n\n\t\t\t\tif ( useVertexColors ) cachedMaterial.vertexColors = true;\n\t\t\t\tif ( useFlatShading ) cachedMaterial.flatShading = true;\n\n\t\t\t\tif ( useDerivativeTangents ) {\n\n\t\t\t\t\t// https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995\n\t\t\t\t\tif ( cachedMaterial.normalScale ) cachedMaterial.normalScale.y *= - 1;\n\t\t\t\t\tif ( cachedMaterial.clearcoatNormalScale ) cachedMaterial.clearcoatNormalScale.y *= - 1;\n\n\t\t\t\t}\n\n\t\t\t\tthis.cache.add( cacheKey, cachedMaterial );\n\n\t\t\t\tthis.associations.set( cachedMaterial, this.associations.get( material ) );\n\n\t\t\t}\n\n\t\t\tmaterial = cachedMaterial;\n\n\t\t}\n\n\t\t// workarounds for mesh and geometry\n\n\t\tif ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) {\n\n\t\t\tgeometry.setAttribute( 'uv2', geometry.attributes.uv );\n\n\t\t}\n\n\t\tmesh.material = material;\n\n\t}\n\n\tgetMaterialType( /* materialIndex */ ) {\n\n\t\treturn three__WEBPACK_IMPORTED_MODULE_0__.MeshStandardMaterial;\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials\n\t * @param {number} materialIndex\n\t * @return {Promise}\n\t */\n\tloadMaterial( materialIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\t\tconst materialDef = json.materials[ materialIndex ];\n\n\t\tlet materialType;\n\t\tconst materialParams = {};\n\t\tconst materialExtensions = materialDef.extensions || {};\n\n\t\tconst pending = [];\n\n\t\tif ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {\n\n\t\t\tconst sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];\n\t\t\tmaterialType = sgExtension.getMaterialType();\n\t\t\tpending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );\n\n\t\t} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {\n\n\t\t\tconst kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];\n\t\t\tmaterialType = kmuExtension.getMaterialType();\n\t\t\tpending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );\n\n\t\t} else {\n\n\t\t\t// Specification:\n\t\t\t// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material\n\n\t\t\tconst metallicRoughness = materialDef.pbrMetallicRoughness || {};\n\n\t\t\tmaterialParams.color = new three__WEBPACK_IMPORTED_MODULE_0__.Color( 1.0, 1.0, 1.0 );\n\t\t\tmaterialParams.opacity = 1.0;\n\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\n\n\t\t\t\tconst array = metallicRoughness.baseColorFactor;\n\n\t\t\t\tmaterialParams.color.fromArray( array );\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\n\n\t\t\t}\n\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, three__WEBPACK_IMPORTED_MODULE_0__.sRGBEncoding ) );\n\n\t\t\t}\n\n\t\t\tmaterialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;\n\t\t\tmaterialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;\n\n\t\t\tif ( metallicRoughness.metallicRoughnessTexture !== undefined ) {\n\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );\n\n\t\t\t}\n\n\t\t\tmaterialType = this._invokeOne( function ( ext ) {\n\n\t\t\t\treturn ext.getMaterialType && ext.getMaterialType( materialIndex );\n\n\t\t\t} );\n\n\t\t\tpending.push( Promise.all( this._invokeAll( function ( ext ) {\n\n\t\t\t\treturn ext.extendMaterialParams && ext.extendMaterialParams( materialIndex, materialParams );\n\n\t\t\t} ) ) );\n\n\t\t}\n\n\t\tif ( materialDef.doubleSided === true ) {\n\n\t\t\tmaterialParams.side = three__WEBPACK_IMPORTED_MODULE_0__.DoubleSide;\n\n\t\t}\n\n\t\tconst alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;\n\n\t\tif ( alphaMode === ALPHA_MODES.BLEND ) {\n\n\t\t\tmaterialParams.transparent = true;\n\n\t\t\t// See: https://github.com/mrdoob/three.js/issues/17706\n\t\t\tmaterialParams.depthWrite = false;\n\n\t\t} else {\n\n\t\t\tmaterialParams.transparent = false;\n\n\t\t\tif ( alphaMode === ALPHA_MODES.MASK ) {\n\n\t\t\t\tmaterialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.normalTexture !== undefined && materialType !== three__WEBPACK_IMPORTED_MODULE_0__.MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );\n\n\t\t\tmaterialParams.normalScale = new three__WEBPACK_IMPORTED_MODULE_0__.Vector2( 1, 1 );\n\n\t\t\tif ( materialDef.normalTexture.scale !== undefined ) {\n\n\t\t\t\tconst scale = materialDef.normalTexture.scale;\n\n\t\t\t\tmaterialParams.normalScale.set( scale, scale );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.occlusionTexture !== undefined && materialType !== three__WEBPACK_IMPORTED_MODULE_0__.MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );\n\n\t\t\tif ( materialDef.occlusionTexture.strength !== undefined ) {\n\n\t\t\t\tmaterialParams.aoMapIntensity = materialDef.occlusionTexture.strength;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( materialDef.emissiveFactor !== undefined && materialType !== three__WEBPACK_IMPORTED_MODULE_0__.MeshBasicMaterial ) {\n\n\t\t\tmaterialParams.emissive = new three__WEBPACK_IMPORTED_MODULE_0__.Color().fromArray( materialDef.emissiveFactor );\n\n\t\t}\n\n\t\tif ( materialDef.emissiveTexture !== undefined && materialType !== three__WEBPACK_IMPORTED_MODULE_0__.MeshBasicMaterial ) {\n\n\t\t\tpending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture, three__WEBPACK_IMPORTED_MODULE_0__.sRGBEncoding ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\tlet material;\n\n\t\t\tif ( materialType === GLTFMeshStandardSGMaterial ) {\n\n\t\t\t\tmaterial = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );\n\n\t\t\t} else {\n\n\t\t\t\tmaterial = new materialType( materialParams );\n\n\t\t\t}\n\n\t\t\tif ( materialDef.name ) material.name = materialDef.name;\n\n\t\t\tassignExtrasToUserData( material, materialDef );\n\n\t\t\tparser.associations.set( material, { materials: materialIndex } );\n\n\t\t\tif ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );\n\n\t\t\treturn material;\n\n\t\t} );\n\n\t}\n\n\t/** When Object3D instances are targeted by animation, they need unique names. */\n\tcreateUniqueName( originalName ) {\n\n\t\tconst sanitizedName = three__WEBPACK_IMPORTED_MODULE_0__.PropertyBinding.sanitizeNodeName( originalName || '' );\n\n\t\tlet name = sanitizedName;\n\n\t\tfor ( let i = 1; this.nodeNamesUsed[ name ]; ++ i ) {\n\n\t\t\tname = sanitizedName + '_' + i;\n\n\t\t}\n\n\t\tthis.nodeNamesUsed[ name ] = true;\n\n\t\treturn name;\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry\n\t *\n\t * Creates BufferGeometries from primitives.\n\t *\n\t * @param {Array} primitives\n\t * @return {Promise>}\n\t */\n\tloadGeometries( primitives ) {\n\n\t\tconst parser = this;\n\t\tconst extensions = this.extensions;\n\t\tconst cache = this.primitiveCache;\n\n\t\tfunction createDracoPrimitive( primitive ) {\n\n\t\t\treturn extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]\n\t\t\t\t.decodePrimitive( primitive, parser )\n\t\t\t\t.then( function ( geometry ) {\n\n\t\t\t\t\treturn addPrimitiveAttributes( geometry, primitive, parser );\n\n\t\t\t\t} );\n\n\t\t}\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = primitives.length; i < il; i ++ ) {\n\n\t\t\tconst primitive = primitives[ i ];\n\t\t\tconst cacheKey = createPrimitiveKey( primitive );\n\n\t\t\t// See if we've already created this geometry\n\t\t\tconst cached = cache[ cacheKey ];\n\n\t\t\tif ( cached ) {\n\n\t\t\t\t// Use the cached geometry if it exists\n\t\t\t\tpending.push( cached.promise );\n\n\t\t\t} else {\n\n\t\t\t\tlet geometryPromise;\n\n\t\t\t\tif ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {\n\n\t\t\t\t\t// Use DRACO geometry if available\n\t\t\t\t\tgeometryPromise = createDracoPrimitive( primitive );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Otherwise create a new geometry\n\t\t\t\t\tgeometryPromise = addPrimitiveAttributes( new three__WEBPACK_IMPORTED_MODULE_0__.BufferGeometry(), primitive, parser );\n\n\t\t\t\t}\n\n\t\t\t\t// Cache this geometry\n\t\t\t\tcache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };\n\n\t\t\t\tpending.push( geometryPromise );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes\n\t * @param {number} meshIndex\n\t * @return {Promise}\n\t */\n\tloadMesh( meshIndex ) {\n\n\t\tconst parser = this;\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\n\t\tconst meshDef = json.meshes[ meshIndex ];\n\t\tconst primitives = meshDef.primitives;\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = primitives.length; i < il; i ++ ) {\n\n\t\t\tconst material = primitives[ i ].material === undefined\n\t\t\t\t? createDefaultMaterial( this.cache )\n\t\t\t\t: this.getDependency( 'material', primitives[ i ].material );\n\n\t\t\tpending.push( material );\n\n\t\t}\n\n\t\tpending.push( parser.loadGeometries( primitives ) );\n\n\t\treturn Promise.all( pending ).then( function ( results ) {\n\n\t\t\tconst materials = results.slice( 0, results.length - 1 );\n\t\t\tconst geometries = results[ results.length - 1 ];\n\n\t\t\tconst meshes = [];\n\n\t\t\tfor ( let i = 0, il = geometries.length; i < il; i ++ ) {\n\n\t\t\t\tconst geometry = geometries[ i ];\n\t\t\t\tconst primitive = primitives[ i ];\n\n\t\t\t\t// 1. create Mesh\n\n\t\t\t\tlet mesh;\n\n\t\t\t\tconst material = materials[ i ];\n\n\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||\n\t\t\t\t\t\tprimitive.mode === undefined ) {\n\n\t\t\t\t\t// .isSkinnedMesh isn't in glTF spec. See ._markDefs()\n\t\t\t\t\tmesh = meshDef.isSkinnedMesh === true\n\t\t\t\t\t\t? new three__WEBPACK_IMPORTED_MODULE_0__.SkinnedMesh( geometry, material )\n\t\t\t\t\t\t: new three__WEBPACK_IMPORTED_MODULE_0__.Mesh( geometry, material );\n\n\t\t\t\t\tif ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {\n\n\t\t\t\t\t\t// we normalize floating point skin weight array to fix malformed assets (see #15319)\n\t\t\t\t\t\t// it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs\n\t\t\t\t\t\tmesh.normalizeSkinWeights();\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {\n\n\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, three__WEBPACK_IMPORTED_MODULE_0__.TriangleStripDrawMode );\n\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {\n\n\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, three__WEBPACK_IMPORTED_MODULE_0__.TriangleFanDrawMode );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {\n\n\t\t\t\t\tmesh = new three__WEBPACK_IMPORTED_MODULE_0__.LineSegments( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {\n\n\t\t\t\t\tmesh = new three__WEBPACK_IMPORTED_MODULE_0__.Line( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {\n\n\t\t\t\t\tmesh = new three__WEBPACK_IMPORTED_MODULE_0__.LineLoop( geometry, material );\n\n\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {\n\n\t\t\t\t\tmesh = new three__WEBPACK_IMPORTED_MODULE_0__.Points( geometry, material );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );\n\n\t\t\t\t}\n\n\t\t\t\tif ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {\n\n\t\t\t\t\tupdateMorphTargets( mesh, meshDef );\n\n\t\t\t\t}\n\n\t\t\t\tmesh.name = parser.createUniqueName( meshDef.name || ( 'mesh_' + meshIndex ) );\n\n\t\t\t\tassignExtrasToUserData( mesh, meshDef );\n\n\t\t\t\tif ( primitive.extensions ) addUnknownExtensionsToUserData( extensions, mesh, primitive );\n\n\t\t\t\tparser.assignFinalMaterial( mesh );\n\n\t\t\t\tmeshes.push( mesh );\n\n\t\t\t}\n\n\t\t\tfor ( let i = 0, il = meshes.length; i < il; i ++ ) {\n\n\t\t\t\tparser.associations.set( meshes[ i ], {\n\t\t\t\t\tmeshes: meshIndex,\n\t\t\t\t\tprimitives: i\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\tif ( meshes.length === 1 ) {\n\n\t\t\t\treturn meshes[ 0 ];\n\n\t\t\t}\n\n\t\t\tconst group = new three__WEBPACK_IMPORTED_MODULE_0__.Group();\n\n\t\t\tparser.associations.set( group, { meshes: meshIndex } );\n\n\t\t\tfor ( let i = 0, il = meshes.length; i < il; i ++ ) {\n\n\t\t\t\tgroup.add( meshes[ i ] );\n\n\t\t\t}\n\n\t\t\treturn group;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras\n\t * @param {number} cameraIndex\n\t * @return {Promise}\n\t */\n\tloadCamera( cameraIndex ) {\n\n\t\tlet camera;\n\t\tconst cameraDef = this.json.cameras[ cameraIndex ];\n\t\tconst params = cameraDef[ cameraDef.type ];\n\n\t\tif ( ! params ) {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing camera parameters.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( cameraDef.type === 'perspective' ) {\n\n\t\t\tcamera = new three__WEBPACK_IMPORTED_MODULE_0__.PerspectiveCamera( three__WEBPACK_IMPORTED_MODULE_0__.MathUtils.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );\n\n\t\t} else if ( cameraDef.type === 'orthographic' ) {\n\n\t\t\tcamera = new three__WEBPACK_IMPORTED_MODULE_0__.OrthographicCamera( - params.xmag, params.xmag, params.ymag, - params.ymag, params.znear, params.zfar );\n\n\t\t}\n\n\t\tif ( cameraDef.name ) camera.name = this.createUniqueName( cameraDef.name );\n\n\t\tassignExtrasToUserData( camera, cameraDef );\n\n\t\treturn Promise.resolve( camera );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins\n\t * @param {number} skinIndex\n\t * @return {Promise}\n\t */\n\tloadSkin( skinIndex ) {\n\n\t\tconst skinDef = this.json.skins[ skinIndex ];\n\n\t\tconst skinEntry = { joints: skinDef.joints };\n\n\t\tif ( skinDef.inverseBindMatrices === undefined ) {\n\n\t\t\treturn Promise.resolve( skinEntry );\n\n\t\t}\n\n\t\treturn this.getDependency( 'accessor', skinDef.inverseBindMatrices ).then( function ( accessor ) {\n\n\t\t\tskinEntry.inverseBindMatrices = accessor;\n\n\t\t\treturn skinEntry;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations\n\t * @param {number} animationIndex\n\t * @return {Promise}\n\t */\n\tloadAnimation( animationIndex ) {\n\n\t\tconst json = this.json;\n\n\t\tconst animationDef = json.animations[ animationIndex ];\n\n\t\tconst pendingNodes = [];\n\t\tconst pendingInputAccessors = [];\n\t\tconst pendingOutputAccessors = [];\n\t\tconst pendingSamplers = [];\n\t\tconst pendingTargets = [];\n\n\t\tfor ( let i = 0, il = animationDef.channels.length; i < il; i ++ ) {\n\n\t\t\tconst channel = animationDef.channels[ i ];\n\t\t\tconst sampler = animationDef.samplers[ channel.sampler ];\n\t\t\tconst target = channel.target;\n\t\t\tconst name = target.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated.\n\t\t\tconst input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;\n\t\t\tconst output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;\n\n\t\t\tpendingNodes.push( this.getDependency( 'node', name ) );\n\t\t\tpendingInputAccessors.push( this.getDependency( 'accessor', input ) );\n\t\t\tpendingOutputAccessors.push( this.getDependency( 'accessor', output ) );\n\t\t\tpendingSamplers.push( sampler );\n\t\t\tpendingTargets.push( target );\n\n\t\t}\n\n\t\treturn Promise.all( [\n\n\t\t\tPromise.all( pendingNodes ),\n\t\t\tPromise.all( pendingInputAccessors ),\n\t\t\tPromise.all( pendingOutputAccessors ),\n\t\t\tPromise.all( pendingSamplers ),\n\t\t\tPromise.all( pendingTargets )\n\n\t\t] ).then( function ( dependencies ) {\n\n\t\t\tconst nodes = dependencies[ 0 ];\n\t\t\tconst inputAccessors = dependencies[ 1 ];\n\t\t\tconst outputAccessors = dependencies[ 2 ];\n\t\t\tconst samplers = dependencies[ 3 ];\n\t\t\tconst targets = dependencies[ 4 ];\n\n\t\t\tconst tracks = [];\n\n\t\t\tfor ( let i = 0, il = nodes.length; i < il; i ++ ) {\n\n\t\t\t\tconst node = nodes[ i ];\n\t\t\t\tconst inputAccessor = inputAccessors[ i ];\n\t\t\t\tconst outputAccessor = outputAccessors[ i ];\n\t\t\t\tconst sampler = samplers[ i ];\n\t\t\t\tconst target = targets[ i ];\n\n\t\t\t\tif ( node === undefined ) continue;\n\n\t\t\t\tnode.updateMatrix();\n\t\t\t\tnode.matrixAutoUpdate = true;\n\n\t\t\t\tlet TypedKeyframeTrack;\n\n\t\t\t\tswitch ( PATH_PROPERTIES[ target.path ] ) {\n\n\t\t\t\t\tcase PATH_PROPERTIES.weights:\n\n\t\t\t\t\t\tTypedKeyframeTrack = three__WEBPACK_IMPORTED_MODULE_0__.NumberKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PATH_PROPERTIES.rotation:\n\n\t\t\t\t\t\tTypedKeyframeTrack = three__WEBPACK_IMPORTED_MODULE_0__.QuaternionKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PATH_PROPERTIES.position:\n\t\t\t\t\tcase PATH_PROPERTIES.scale:\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tTypedKeyframeTrack = three__WEBPACK_IMPORTED_MODULE_0__.VectorKeyframeTrack;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tconst targetName = node.name ? node.name : node.uuid;\n\n\t\t\t\tconst interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : three__WEBPACK_IMPORTED_MODULE_0__.InterpolateLinear;\n\n\t\t\t\tconst targetNames = [];\n\n\t\t\t\tif ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {\n\n\t\t\t\t\tnode.traverse( function ( object ) {\n\n\t\t\t\t\t\tif ( object.morphTargetInfluences ) {\n\n\t\t\t\t\t\t\ttargetNames.push( object.name ? object.name : object.uuid );\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\ttargetNames.push( targetName );\n\n\t\t\t\t}\n\n\t\t\t\tlet outputArray = outputAccessor.array;\n\n\t\t\t\tif ( outputAccessor.normalized ) {\n\n\t\t\t\t\tconst scale = getNormalizedComponentScale( outputArray.constructor );\n\t\t\t\t\tconst scaled = new Float32Array( outputArray.length );\n\n\t\t\t\t\tfor ( let j = 0, jl = outputArray.length; j < jl; j ++ ) {\n\n\t\t\t\t\t\tscaled[ j ] = outputArray[ j ] * scale;\n\n\t\t\t\t\t}\n\n\t\t\t\t\toutputArray = scaled;\n\n\t\t\t\t}\n\n\t\t\t\tfor ( let j = 0, jl = targetNames.length; j < jl; j ++ ) {\n\n\t\t\t\t\tconst track = new TypedKeyframeTrack(\n\t\t\t\t\t\ttargetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],\n\t\t\t\t\t\tinputAccessor.array,\n\t\t\t\t\t\toutputArray,\n\t\t\t\t\t\tinterpolation\n\t\t\t\t\t);\n\n\t\t\t\t\t// Override interpolation with custom factory method.\n\t\t\t\t\tif ( sampler.interpolation === 'CUBICSPLINE' ) {\n\n\t\t\t\t\t\ttrack.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {\n\n\t\t\t\t\t\t\t// A CUBICSPLINE keyframe in glTF has three output values for each input value,\n\t\t\t\t\t\t\t// representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()\n\t\t\t\t\t\t\t// must be divided by three to get the interpolant's sampleSize argument.\n\n\t\t\t\t\t\t\tconst interpolantType = ( this instanceof three__WEBPACK_IMPORTED_MODULE_0__.QuaternionKeyframeTrack ) ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant;\n\n\t\t\t\t\t\t\treturn new interpolantType( this.times, this.values, this.getValueSize() / 3, result );\n\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.\n\t\t\t\t\t\ttrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;\n\n\t\t\t\t\t}\n\n\t\t\t\t\ttracks.push( track );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tconst name = animationDef.name ? animationDef.name : 'animation_' + animationIndex;\n\n\t\t\treturn new three__WEBPACK_IMPORTED_MODULE_0__.AnimationClip( name, undefined, tracks );\n\n\t\t} );\n\n\t}\n\n\tcreateNodeMesh( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst parser = this;\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\tif ( nodeDef.mesh === undefined ) return null;\n\n\t\treturn parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {\n\n\t\t\tconst node = parser._getNodeRef( parser.meshCache, nodeDef.mesh, mesh );\n\n\t\t\t// if weights are provided on the node, override weights on the mesh.\n\t\t\tif ( nodeDef.weights !== undefined ) {\n\n\t\t\t\tnode.traverse( function ( o ) {\n\n\t\t\t\t\tif ( ! o.isMesh ) return;\n\n\t\t\t\t\tfor ( let i = 0, il = nodeDef.weights.length; i < il; i ++ ) {\n\n\t\t\t\t\t\to.morphTargetInfluences[ i ] = nodeDef.weights[ i ];\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy\n\t * @param {number} nodeIndex\n\t * @return {Promise}\n\t */\n\tloadNode( nodeIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\t\tconst parser = this;\n\n\t\tconst nodeDef = json.nodes[ nodeIndex ];\n\n\t\t// reserve node's name before its dependencies, so the root has the intended name.\n\t\tconst nodeName = nodeDef.name ? parser.createUniqueName( nodeDef.name ) : '';\n\n\t\treturn ( function () {\n\n\t\t\tconst pending = [];\n\n\t\t\tconst meshPromise = parser._invokeOne( function ( ext ) {\n\n\t\t\t\treturn ext.createNodeMesh && ext.createNodeMesh( nodeIndex );\n\n\t\t\t} );\n\n\t\t\tif ( meshPromise ) {\n\n\t\t\t\tpending.push( meshPromise );\n\n\t\t\t}\n\n\t\t\tif ( nodeDef.camera !== undefined ) {\n\n\t\t\t\tpending.push( parser.getDependency( 'camera', nodeDef.camera ).then( function ( camera ) {\n\n\t\t\t\t\treturn parser._getNodeRef( parser.cameraCache, nodeDef.camera, camera );\n\n\t\t\t\t} ) );\n\n\t\t\t}\n\n\t\t\tparser._invokeAll( function ( ext ) {\n\n\t\t\t\treturn ext.createNodeAttachment && ext.createNodeAttachment( nodeIndex );\n\n\t\t\t} ).forEach( function ( promise ) {\n\n\t\t\t\tpending.push( promise );\n\n\t\t\t} );\n\n\t\t\treturn Promise.all( pending );\n\n\t\t}() ).then( function ( objects ) {\n\n\t\t\tlet node;\n\n\t\t\t// .isBone isn't in glTF spec. See ._markDefs\n\t\t\tif ( nodeDef.isBone === true ) {\n\n\t\t\t\tnode = new three__WEBPACK_IMPORTED_MODULE_0__.Bone();\n\n\t\t\t} else if ( objects.length > 1 ) {\n\n\t\t\t\tnode = new three__WEBPACK_IMPORTED_MODULE_0__.Group();\n\n\t\t\t} else if ( objects.length === 1 ) {\n\n\t\t\t\tnode = objects[ 0 ];\n\n\t\t\t} else {\n\n\t\t\t\tnode = new three__WEBPACK_IMPORTED_MODULE_0__.Object3D();\n\n\t\t\t}\n\n\t\t\tif ( node !== objects[ 0 ] ) {\n\n\t\t\t\tfor ( let i = 0, il = objects.length; i < il; i ++ ) {\n\n\t\t\t\t\tnode.add( objects[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( nodeDef.name ) {\n\n\t\t\t\tnode.userData.name = nodeDef.name;\n\t\t\t\tnode.name = nodeName;\n\n\t\t\t}\n\n\t\t\tassignExtrasToUserData( node, nodeDef );\n\n\t\t\tif ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );\n\n\t\t\tif ( nodeDef.matrix !== undefined ) {\n\n\t\t\t\tconst matrix = new three__WEBPACK_IMPORTED_MODULE_0__.Matrix4();\n\t\t\t\tmatrix.fromArray( nodeDef.matrix );\n\t\t\t\tnode.applyMatrix4( matrix );\n\n\t\t\t} else {\n\n\t\t\t\tif ( nodeDef.translation !== undefined ) {\n\n\t\t\t\t\tnode.position.fromArray( nodeDef.translation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.rotation !== undefined ) {\n\n\t\t\t\t\tnode.quaternion.fromArray( nodeDef.rotation );\n\n\t\t\t\t}\n\n\t\t\t\tif ( nodeDef.scale !== undefined ) {\n\n\t\t\t\t\tnode.scale.fromArray( nodeDef.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( ! parser.associations.has( node ) ) {\n\n\t\t\t\tparser.associations.set( node, {} );\n\n\t\t\t}\n\n\t\t\tparser.associations.get( node ).nodes = nodeIndex;\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes\n\t * @param {number} sceneIndex\n\t * @return {Promise}\n\t */\n\tloadScene( sceneIndex ) {\n\n\t\tconst json = this.json;\n\t\tconst extensions = this.extensions;\n\t\tconst sceneDef = this.json.scenes[ sceneIndex ];\n\t\tconst parser = this;\n\n\t\t// Loader returns Group, not Scene.\n\t\t// See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172\n\t\tconst scene = new three__WEBPACK_IMPORTED_MODULE_0__.Group();\n\t\tif ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name );\n\n\t\tassignExtrasToUserData( scene, sceneDef );\n\n\t\tif ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );\n\n\t\tconst nodeIds = sceneDef.nodes || [];\n\n\t\tconst pending = [];\n\n\t\tfor ( let i = 0, il = nodeIds.length; i < il; i ++ ) {\n\n\t\t\tpending.push( buildNodeHierarchy( nodeIds[ i ], scene, json, parser ) );\n\n\t\t}\n\n\t\treturn Promise.all( pending ).then( function () {\n\n\t\t\t// Removes dangling associations, associations that reference a node that\n\t\t\t// didn't make it into the scene.\n\t\t\tconst reduceAssociations = ( node ) => {\n\n\t\t\t\tconst reducedAssociations = new Map();\n\n\t\t\t\tfor ( const [ key, value ] of parser.associations ) {\n\n\t\t\t\t\tif ( key instanceof three__WEBPACK_IMPORTED_MODULE_0__.Material || key instanceof three__WEBPACK_IMPORTED_MODULE_0__.Texture ) {\n\n\t\t\t\t\t\treducedAssociations.set( key, value );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tnode.traverse( ( node ) => {\n\n\t\t\t\t\tconst mappings = parser.associations.get( node );\n\n\t\t\t\t\tif ( mappings != null ) {\n\n\t\t\t\t\t\treducedAssociations.set( node, mappings );\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\treturn reducedAssociations;\n\n\t\t\t};\n\n\t\t\tparser.associations = reduceAssociations( scene );\n\n\t\t\treturn scene;\n\n\t\t} );\n\n\t}\n\n}\n\nfunction buildNodeHierarchy( nodeId, parentObject, json, parser ) {\n\n\tconst nodeDef = json.nodes[ nodeId ];\n\n\treturn parser.getDependency( 'node', nodeId ).then( function ( node ) {\n\n\t\tif ( nodeDef.skin === undefined ) return node;\n\n\t\t// build skeleton here as well\n\n\t\tlet skinEntry;\n\n\t\treturn parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) {\n\n\t\t\tskinEntry = skin;\n\n\t\t\tconst pendingJoints = [];\n\n\t\t\tfor ( let i = 0, il = skinEntry.joints.length; i < il; i ++ ) {\n\n\t\t\t\tpendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) );\n\n\t\t\t}\n\n\t\t\treturn Promise.all( pendingJoints );\n\n\t\t} ).then( function ( jointNodes ) {\n\n\t\t\tnode.traverse( function ( mesh ) {\n\n\t\t\t\tif ( ! mesh.isMesh ) return;\n\n\t\t\t\tconst bones = [];\n\t\t\t\tconst boneInverses = [];\n\n\t\t\t\tfor ( let j = 0, jl = jointNodes.length; j < jl; j ++ ) {\n\n\t\t\t\t\tconst jointNode = jointNodes[ j ];\n\n\t\t\t\t\tif ( jointNode ) {\n\n\t\t\t\t\t\tbones.push( jointNode );\n\n\t\t\t\t\t\tconst mat = new three__WEBPACK_IMPORTED_MODULE_0__.Matrix4();\n\n\t\t\t\t\t\tif ( skinEntry.inverseBindMatrices !== undefined ) {\n\n\t\t\t\t\t\t\tmat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tboneInverses.push( mat );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Joint \"%s\" could not be found.', skinEntry.joints[ j ] );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tmesh.bind( new three__WEBPACK_IMPORTED_MODULE_0__.Skeleton( bones, boneInverses ), mesh.matrixWorld );\n\n\t\t\t} );\n\n\t\t\treturn node;\n\n\t\t} );\n\n\t} ).then( function ( node ) {\n\n\t\t// build node hierachy\n\n\t\tparentObject.add( node );\n\n\t\tconst pending = [];\n\n\t\tif ( nodeDef.children ) {\n\n\t\t\tconst children = nodeDef.children;\n\n\t\t\tfor ( let i = 0, il = children.length; i < il; i ++ ) {\n\n\t\t\t\tconst child = children[ i ];\n\t\t\t\tpending.push( buildNodeHierarchy( child, node, json, parser ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn Promise.all( pending );\n\n\t} );\n\n}\n\n/**\n * @param {BufferGeometry} geometry\n * @param {GLTF.Primitive} primitiveDef\n * @param {GLTFParser} parser\n */\nfunction computeBounds( geometry, primitiveDef, parser ) {\n\n\tconst attributes = primitiveDef.attributes;\n\n\tconst box = new three__WEBPACK_IMPORTED_MODULE_0__.Box3();\n\n\tif ( attributes.POSITION !== undefined ) {\n\n\t\tconst accessor = parser.json.accessors[ attributes.POSITION ];\n\n\t\tconst min = accessor.min;\n\t\tconst max = accessor.max;\n\n\t\t// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.\n\n\t\tif ( min !== undefined && max !== undefined ) {\n\n\t\t\tbox.set(\n\t\t\t\tnew three__WEBPACK_IMPORTED_MODULE_0__.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),\n\t\t\t\tnew three__WEBPACK_IMPORTED_MODULE_0__.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] )\n\t\t\t);\n\n\t\t\tif ( accessor.normalized ) {\n\n\t\t\t\tconst boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );\n\t\t\t\tbox.min.multiplyScalar( boxScale );\n\t\t\t\tbox.max.multiplyScalar( boxScale );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );\n\n\t\t\treturn;\n\n\t\t}\n\n\t} else {\n\n\t\treturn;\n\n\t}\n\n\tconst targets = primitiveDef.targets;\n\n\tif ( targets !== undefined ) {\n\n\t\tconst maxDisplacement = new three__WEBPACK_IMPORTED_MODULE_0__.Vector3();\n\t\tconst vector = new three__WEBPACK_IMPORTED_MODULE_0__.Vector3();\n\n\t\tfor ( let i = 0, il = targets.length; i < il; i ++ ) {\n\n\t\t\tconst target = targets[ i ];\n\n\t\t\tif ( target.POSITION !== undefined ) {\n\n\t\t\t\tconst accessor = parser.json.accessors[ target.POSITION ];\n\t\t\t\tconst min = accessor.min;\n\t\t\t\tconst max = accessor.max;\n\n\t\t\t\t// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.\n\n\t\t\t\tif ( min !== undefined && max !== undefined ) {\n\n\t\t\t\t\t// we need to get max of absolute components because target weight is [-1,1]\n\t\t\t\t\tvector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );\n\t\t\t\t\tvector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );\n\t\t\t\t\tvector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );\n\n\n\t\t\t\t\tif ( accessor.normalized ) {\n\n\t\t\t\t\t\tconst boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );\n\t\t\t\t\t\tvector.multiplyScalar( boxScale );\n\n\t\t\t\t\t}\n\n\t\t\t\t\t// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative\n\t\t\t\t\t// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets\n\t\t\t\t\t// are used to implement key-frame animations and as such only two are active at a time - this results in very large\n\t\t\t\t\t// boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size.\n\t\t\t\t\tmaxDisplacement.max( vector );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets.\n\t\tbox.expandByVector( maxDisplacement );\n\n\t}\n\n\tgeometry.boundingBox = box;\n\n\tconst sphere = new three__WEBPACK_IMPORTED_MODULE_0__.Sphere();\n\n\tbox.getCenter( sphere.center );\n\tsphere.radius = box.min.distanceTo( box.max ) / 2;\n\n\tgeometry.boundingSphere = sphere;\n\n}\n\n/**\n * @param {BufferGeometry} geometry\n * @param {GLTF.Primitive} primitiveDef\n * @param {GLTFParser} parser\n * @return {Promise}\n */\nfunction addPrimitiveAttributes( geometry, primitiveDef, parser ) {\n\n\tconst attributes = primitiveDef.attributes;\n\n\tconst pending = [];\n\n\tfunction assignAttributeAccessor( accessorIndex, attributeName ) {\n\n\t\treturn parser.getDependency( 'accessor', accessorIndex )\n\t\t\t.then( function ( accessor ) {\n\n\t\t\t\tgeometry.setAttribute( attributeName, accessor );\n\n\t\t\t} );\n\n\t}\n\n\tfor ( const gltfAttributeName in attributes ) {\n\n\t\tconst threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();\n\n\t\t// Skip attributes already provided by e.g. Draco extension.\n\t\tif ( threeAttributeName in geometry.attributes ) continue;\n\n\t\tpending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );\n\n\t}\n\n\tif ( primitiveDef.indices !== undefined && ! geometry.index ) {\n\n\t\tconst accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {\n\n\t\t\tgeometry.setIndex( accessor );\n\n\t\t} );\n\n\t\tpending.push( accessor );\n\n\t}\n\n\tassignExtrasToUserData( geometry, primitiveDef );\n\n\tcomputeBounds( geometry, primitiveDef, parser );\n\n\treturn Promise.all( pending ).then( function () {\n\n\t\treturn primitiveDef.targets !== undefined\n\t\t\t? addMorphTargets( geometry, primitiveDef.targets, parser )\n\t\t\t: geometry;\n\n\t} );\n\n}\n\n/**\n * @param {BufferGeometry} geometry\n * @param {Number} drawMode\n * @return {BufferGeometry}\n */\nfunction toTrianglesDrawMode( geometry, drawMode ) {\n\n\tlet index = geometry.getIndex();\n\n\t// generate index if not present\n\n\tif ( index === null ) {\n\n\t\tconst indices = [];\n\n\t\tconst position = geometry.getAttribute( 'position' );\n\n\t\tif ( position !== undefined ) {\n\n\t\t\tfor ( let i = 0; i < position.count; i ++ ) {\n\n\t\t\t\tindices.push( i );\n\n\t\t\t}\n\n\t\t\tgeometry.setIndex( indices );\n\t\t\tindex = geometry.getIndex();\n\n\t\t} else {\n\n\t\t\tconsole.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );\n\t\t\treturn geometry;\n\n\t\t}\n\n\t}\n\n\t//\n\n\tconst numberOfTriangles = index.count - 2;\n\tconst newIndices = [];\n\n\tif ( drawMode === three__WEBPACK_IMPORTED_MODULE_0__.TriangleFanDrawMode ) {\n\n\t\t// gl.TRIANGLE_FAN\n\n\t\tfor ( let i = 1; i <= numberOfTriangles; i ++ ) {\n\n\t\t\tnewIndices.push( index.getX( 0 ) );\n\t\t\tnewIndices.push( index.getX( i ) );\n\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\n\t\t}\n\n\t} else {\n\n\t\t// gl.TRIANGLE_STRIP\n\n\t\tfor ( let i = 0; i < numberOfTriangles; i ++ ) {\n\n\t\t\tif ( i % 2 === 0 ) {\n\n\t\t\t\tnewIndices.push( index.getX( i ) );\n\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\n\n\n\t\t\t} else {\n\n\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\n\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\n\t\t\t\tnewIndices.push( index.getX( i ) );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tif ( ( newIndices.length / 3 ) !== numberOfTriangles ) {\n\n\t\tconsole.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );\n\n\t}\n\n\t// build final geometry\n\n\tconst newGeometry = geometry.clone();\n\tnewGeometry.setIndex( newIndices );\n\n\treturn newGeometry;\n\n}\n\n\n\n\n//# sourceURL=webpack://shelves/./node_modules/_three@0.139.2@three/examples/jsm/loaders/gltfloader.js?"); - -/***/ }), - /***/ "./node_modules/_three@0.139.2@three/examples/jsm/objects/Sky.js": /*!***********************************************************************!*\ !*** ./node_modules/_three@0.139.2@three/examples/jsm/objects/Sky.js ***!